package tc.oc.pgm.regions; import java.util.Random; import org.bukkit.geometry.Cuboid; import org.bukkit.util.ImVector; import org.bukkit.util.Vector; import static com.google.common.base.Preconditions.checkArgument; public class CylindricalRegion extends Region.Impl { private final @Inspect ImVector center; private final @Inspect double bottom; private final @Inspect double top; private final @Inspect double radius; private final double radiusSq; public CylindricalRegion(Vector base, double radius, double top) { checkArgument(radius >= 0); checkArgument(Double.isFinite(base.getX())); checkArgument(Double.isFinite(base.getZ())); this.center = ImVector.of(base.getX(), 0, base.getZ()); this.bottom = base.getY(); this.top = top; this.radius = radius; this.radiusSq = radius * radius; } @Override public boolean contains(Vector point) { return point.getY() >= bottom && point.getY() <= top && center.distanceSquared(ImVector.of(point.getX(), center.getY(), point.getZ())) <= radiusSq; } @Override public boolean canGetRandom() { return isBlockBounded(); } @Override public boolean isBlockBounded() { return Double.isFinite(radius) && Double.isFinite(bottom) && Double.isFinite(top); } @Override public Cuboid getBounds() { return Cuboid.between(new Vector(center.getX() - this.radius, bottom, center.getZ() - this.radius), new Vector(center.getX() + this.radius, top, center.getZ() + this.radius)); } @Override public Vector getRandom(Random random) { double angle = random.nextDouble() * Math.PI * 2; double hyp = random.nextDouble() + random.nextDouble(); hyp = (hyp < 1D ? hyp : 2 - hyp) * radius; double x = Math.cos(angle) * hyp + center.getX(); double z = Math.sin(angle) * hyp + center.getZ(); double y = bottom + random.nextDouble() * (top - bottom); return new Vector(x, y, z); } }