Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shape Utility Classes #11

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions src/main/java/com/projectkorra/core/util/ShapeUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package com.projectkorra.core.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;

import org.bukkit.Color;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.Vector;

import com.projectkorra.core.util.ParticleUtil.DirectionalParticle;
import com.projectkorra.core.util.ParticleUtil.NoteColor;
import com.projectkorra.core.util.shape.Shape;

public class ShapeUtil {

private ShapeUtil() {}

/**
* Take the given shape and construct its locations to the given collection
* @param shape shape to construct
* @param locs where to collect to
*/
public static void collect(Shape shape, Collection<Location> locs) {
shape.construct((loc) -> locs.add(loc));
}

/**
* Take the given shape and construct only the locations which pass the
* filter test to the given collection
* @param shape shape to construct
* @param locs where to collect to
* @param filter any location that passes this test is added to the collection
*/
public static void collect(Shape shape, Collection<Location> locs, Predicate<Location> filter) {
shape.construct((loc) -> {
if (filter.test(loc)) {
locs.add(loc);
}
});
}

/**
* Show the shape using the given particle
* @param shape shape to show
* @param particle particle to show with
*/
public static void showParticle(Shape shape, Particle particle) {
shape.construct((loc) -> ParticleUtil.spawn(particle, loc));
}

/**
* Show the shape using BLOCK_CRACK and the given data
* @param shape shape to show
* @param block data to use for particle
*/
public static void showBlockCrack(Shape shape, BlockData block) {
shape.construct((loc) -> ParticleUtil.spawnBlockCrack(block, loc));
}

/**
* Show the shape using BLOCK_DUST and the given data
* @param shape shape to show
* @param block data to use for particle
*/
public static void showBlockDust(Shape shape, BlockData block) {
shape.construct((loc) -> ParticleUtil.spawnBlockDust(block, loc));
}

/**
* Show the shape using colored NOTE particles
* @param shape shape to show
* @param color note color
*/
public static void showColoredNote(Shape shape, NoteColor color) {
shape.construct((loc) -> ParticleUtil.spawnColoredNote(color, loc));
}

/**
* Show the shape using colored REDSTONE particles
* @param shape shape to show
* @param color redstone color
* @param size redstone size
*/
public static void showColoredRedstone(Shape shape, Color color, float size) {
shape.construct((loc) -> ParticleUtil.spawnColoredRedstone(color, size, loc));
}

/**
* Show the shape using colored MOB_SPELL particles
* @param shape shape to show
* @param color spell color
* @param ambient true for transparency
*/
public static void showColoredSpell(Shape shape, Color color, boolean ambient) {
shape.construct((loc) -> ParticleUtil.spawnColoredSpell(color, ambient, loc));
}

/**
* Show the shape using a directional particle
* @param shape shape to show
* @param type particle to show
* @param direction to move particles in
*/
public static void showDirectional(Shape shape, DirectionalParticle type, Vector direction) {
shape.construct((loc) -> ParticleUtil.spawnWithDirection(type, direction, loc));
}

/**
* Show the shape using FALLING_DUST particles
* @param shape shape to show
* @param block data to use for particles
*/
public static void showFallingDust(Shape shape, BlockData block) {
shape.construct((loc) -> ParticleUtil.spawnFallingDust(block, loc));
}

/**
* Show the shape using ITEM_CRACK particles
* @param shape shape to show
* @param item data to use for particles
*/
public static void showItemCrack(Shape shape, ItemStack item) {
shape.construct((loc) -> ParticleUtil.spawnItemCrack(item, loc));
}

/**
* Construct the given shape into a List
* @param shape shape to construct
* @return List of shape locations
*/
public static List<Location> toList(Shape shape) {
List<Location> locs = new ArrayList<>();
shape.construct((loc) -> locs.add(loc));
return locs;
}

/**
* Construct the given shape into a Set
* @param shape shape to construct
* @return Set of shape locations
*/
public static Set<Location> toSet(Shape shape) {
Set<Location> locs = new HashSet<>();
shape.construct((loc) -> locs.add(loc));
return locs;
}
}
14 changes: 14 additions & 0 deletions src/main/java/com/projectkorra/core/util/VectorUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@ public static Vector direction(Location from, Location to) {
return new Vector(to.getX() - from.getX(), to.getY() - from.getY(), to.getZ() - from.getZ());
}

/**
* Get a vector for the direction of the given yaw and pitch
* @param yaw horizontal rotation, between +/- 180
* @param pitch vertical rotation, between -/+ 90 (negative is up)
* @return vector from yaw and pitch
*/
public static Vector direction(float yaw, float pitch) {
double y = Math.sin(-Math.toRadians(pitch));
double xz = Math.cos(Math.toRadians(pitch));
double x = -xz * Math.sin(Math.toRadians(yaw));
double z = xz * Math.cos(Math.toRadians(yaw));
return new Vector(x, y, z);
}

/**
* Returns an orthogonal vector from an axis
* @param axis vector to be orthogonal of
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/com/projectkorra/core/util/math/Angle.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ public void setValue(double value) {
this.value = value;
}

public void increment(double value) {
this.value += value;
}

public void decrement(double value) {
this.value -= value;
}

public static Angle radians(double value) {
return new Angle(AngleMode.RADIANS, value);
}
Expand Down
42 changes: 42 additions & 0 deletions src/main/java/com/projectkorra/core/util/math/Plane.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package com.projectkorra.core.util.math;

import org.apache.commons.lang.Validate;
import org.bukkit.Location;
import org.bukkit.util.Vector;

import com.projectkorra.core.util.VectorUtil;

public class Plane {

public static final Plane XY = new Plane(UnitVector.POSITIVE_X.normal(), UnitVector.POSITIVE_Y.normal());
public static final Plane ZY = new Plane(UnitVector.POSITIVE_Z.normal(), UnitVector.POSITIVE_Y.normal());
public static final Plane XZ = new Plane(UnitVector.POSITIVE_X.normal(), UnitVector.POSITIVE_Z.normal());

private Vector horizontal, vertical;

private Plane(Vector horizontal, Vector vertical) {
this.horizontal = horizontal.clone().normalize();
this.vertical = vertical.clone().normalize();
}

public Vector getHorizontalAxis() {
return horizontal.clone();
}

public Vector getVerticalAxis() {
return vertical.clone();
}

public Location moveAlongAxes(Location position, double rightward, double upward) {
return position.add(horizontal.clone().multiply(rightward)).add(vertical.clone().multiply(upward));
}

public static Plane fromPerpendicular(Vector perpendicular) throws IllegalArgumentException {
Validate.isTrue(!perpendicular.equals(UnitVector.ZERO.normal()), "Perpendicular vector cannot be zero");

Vector horizontal = VectorUtil.orthogonal(perpendicular, 1, Angle.radians(0));
Vector vertical = VectorUtil.orthogonal(perpendicular, 1, Angle.degrees(90));

return new Plane(horizontal, vertical);
}
}
114 changes: 114 additions & 0 deletions src/main/java/com/projectkorra/core/util/shape/Circle.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package com.projectkorra.core.util.shape;

import java.util.function.Consumer;

import org.bukkit.Location;

import com.projectkorra.core.util.math.Angle;
import com.projectkorra.core.util.math.Angle.AngleMode;
import com.projectkorra.core.util.math.Plane;

public class Circle extends Polygon {

private double radius;
private Angle theta, initial;

/**
* Creates a hollow circle in the XZ plane with no initial angle
* @param center center location
* @param radius distance from center to any point on the circle
* @param theta angle between each location in the circle
*/
public Circle(Location center, double radius, Angle theta) {
this(center, radius, theta, Angle.radians(0), Plane.XZ, true);
}

/**
* Creates a hollow circle in the XZ plane
* @param center center location
* @param radius distance from center to any point on the circle
* @param theta angle between each location in the circle
* @param initial angle to start constructing circle from
*/
public Circle(Location center, double radius, Angle theta, Angle initial) {
this(center, radius, theta, initial, Plane.XZ, true);
}

/**
* Creates a hollow circle
* @param center center location
* @param radius distance from center to any point on the circle
* @param theta angle between each location in the circle
* @param initial angle to start constructing circle from
* @param reference plane to construct circle in
*/
public Circle(Location center, double radius, Angle theta, Angle initial, Plane reference) {
this(center, radius, theta, initial, reference, true);
}

/**
* Creates a circle
* @param center center location
* @param radius distance from center to any point on the circle
* @param theta angle between each location in the circle
* @param initial angle to start constructing circle from
* @param reference plane to construct circle in
* @param hollow true to only draw outline
*/
public Circle(Location center, double radius, Angle theta, Angle initial, Plane reference, boolean hollow) {
super(center, reference, hollow);
this.radius = radius;
this.theta = theta;
this.initial = initial;

if (theta.getRawValue() <= 0) {
theta.set(AngleMode.DEGREES, 1);
}
}

@Override
public void construct(Consumer<Location> func) {
double angle = theta.getValue(AngleMode.RADIANS); // angle between each location in the circle
double init = initial.getValue(AngleMode.RADIANS); // initial angle for the circle to start from

if (!hollow) {
double rinc = radius * angle / (2 * Math.PI); // interval between each circle generated when not hollow

// construct the inner bits of the circle
for (double r = 0.0; r < radius; r += rinc) {
for (double i = init; i < init + 2 * Math.PI; i += angle) {
func.accept(reference.moveAlongAxes(center.clone(), r * Math.cos(i), r * Math.sin(i)));
}
}
}

// construct outer ring of circle only
for (double i = init; i < init + 2 * Math.PI; i += angle) {
func.accept(reference.moveAlongAxes(center.clone(), radius * Math.cos(i), radius * Math.sin(i)));
}
}

public double getRadius() {
return radius;
}

public void setRadius(double radius) {
this.radius = radius;
}

public Angle getTheta() {
return theta;
}

public void setTheta(Angle theta) {
this.theta = theta;
}

public Angle getInitial() {
return initial;
}

public void setInitial(Angle initial) {
this.initial = initial;
}
}
Loading