use of com.sk89q.worldedit.math.Vector2 in project ProtectionStones by espidev.
the class RegionTraverse method traverseRegionEdge.
// can't use recursion because stack overflow
// doesn't do so well with 1 block wide segments jutting out
public static void traverseRegionEdge(HashSet<BlockVector2> points, List<ProtectedRegion> regions, Consumer<TraverseReturn> run) {
int pointID = 0;
while (!points.isEmpty()) {
BlockVector2 start = points.iterator().next();
TraverseData td = new TraverseData(start, null, true);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ algorithm starts ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
boolean cont = true;
while (cont) {
cont = false;
BlockVector2 v = td.v, previous = td.previous;
if (!td.first && v.equals(start))
break;
int exposedEdges = 0;
List<BlockVector2> insideVertex = new ArrayList<>();
for (Vector2 dir : DIRECTIONS) {
BlockVector2 test = BlockVector2.at(v.getX() + dir.getX(), v.getZ() + dir.getZ());
if (!isInRegion(test, regions)) {
exposedEdges++;
} else {
insideVertex.add(test);
}
}
// remove current point if it exists
points.remove(v);
switch(exposedEdges) {
case // normal edge
1:
// run consumer
run.accept(new TraverseReturn(v, false, pointID, exposedEdges));
if (previous == null) {
// if this is the first node we need to determine a direction to go to (that isn't into the polygon, but is on edge)
if (insideVertex.get(0).getX() == insideVertex.get(1).getZ() || insideVertex.get(0).getZ() == insideVertex.get(1).getZ() || insideVertex.get(0).getX() == insideVertex.get(2).getZ() || insideVertex.get(0).getZ() == insideVertex.get(2).getZ()) {
previous = insideVertex.get(0);
} else {
previous = insideVertex.get(1);
}
}
td = new TraverseData(BlockVector2.at(v.getX() + (v.getX() - previous.getX()), v.getZ() + (v.getZ() - previous.getZ())), v, false);
cont = true;
break;
case // convex vertex
2:
// possibly also 1 block wide segment with 2 edges opposite, but we'll ignore that
// run consumer
run.accept(new TraverseReturn(v, true, pointID, exposedEdges));
if (insideVertex.get(0).equals(previous)) {
td = new TraverseData(insideVertex.get(1), v, false);
cont = true;
} else {
td = new TraverseData(insideVertex.get(0), v, false);
cont = true;
}
break;
case // random 1x1 jutting out
3:
// it's fine right now but it'd be nice if it worked
break;
case // concave vertex, or point in middle of region
0:
List<Vector2> cornersNotIn = new ArrayList<>();
for (Vector2 dir : CORNER_DIRECTIONS) {
BlockVector2 test = BlockVector2.at(v.getX() + dir.getX(), v.getZ() + dir.getZ());
if (!isInRegion(test, regions))
cornersNotIn.add(dir);
}
if (cornersNotIn.size() == 1) {
// concave vertex
// run consumer
run.accept(new TraverseReturn(v, true, pointID, exposedEdges));
Vector2 dir = cornersNotIn.get(0);
if (previous == null || previous.equals(BlockVector2.at(v.getX() + dir.getX(), v.getZ()))) {
td = new TraverseData(BlockVector2.at(v.getX(), v.getZ() + dir.getZ()), v, false);
cont = true;
} else {
td = new TraverseData(BlockVector2.at(v.getX() + dir.getX(), v.getZ()), v, false);
cont = true;
}
} else if (cornersNotIn.size() == 2) {
// 1 block diagonal perfect overlap
// run consumer
run.accept(new TraverseReturn(v, false, pointID, exposedEdges));
if (previous == null)
previous = insideVertex.get(0);
td = new TraverseData(BlockVector2.at(v.getX() + (v.getX() - previous.getX()), v.getZ() + (v.getZ() - previous.getZ())), v, false);
cont = true;
}
// ignore if in middle of region (cornersNotIn size = 0)
break;
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ algorithm ends ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pointID++;
}
}
use of com.sk89q.worldedit.math.Vector2 in project FastAsyncWorldEdit by IntellectualSites.
the class CylinderRegionSelector method selectSecondary.
@Override
public boolean selectSecondary(BlockVector3 position, SelectorLimits limits) {
if (!selectedCenter) {
return true;
}
final Vector2 diff = position.toVector3().subtract(region.getCenter()).toVector2();
final Vector2 minRadius = diff.getMaximum(diff.multiply(-1.0));
region.extendRadius(minRadius);
region.setY(position.getBlockY());
selectedRadius = true;
return true;
}
use of com.sk89q.worldedit.math.Vector2 in project FastAsyncWorldEdit by IntellectualSites.
the class CylinderRegion method createRadius.
/**
* Return a new instance with the given center and radius in the X and Z
* axes with a Y that extends from the bottom of the extent to the top
* of the extent.
*
* @param extent the extent
* @param center the center position
* @param radius the radius in the X and Z axes
* @return a region
*/
public static CylinderRegion createRadius(Extent extent, BlockVector3 center, double radius) {
checkNotNull(extent);
checkNotNull(center);
Vector2 radiusVec = Vector2.at(radius, radius);
int minY = extent.getMinimumPoint().getBlockY();
int maxY = extent.getMaximumPoint().getBlockY();
return new CylinderRegion(center, radiusVec, minY, maxY);
}
use of com.sk89q.worldedit.math.Vector2 in project FastAsyncWorldEdit by IntellectualSites.
the class Polygons method polygonizeCylinder.
/**
* Calculates the polygon shape of a cylinder which can then be used for e.g. intersection detection.
*
* @param center the center point of the cylinder
* @param radius the radius of the cylinder
* @param maxPoints max points to be used for the calculation
* @return a list of {@link BlockVector2} which resemble the shape as a polygon
*/
public static List<BlockVector2> polygonizeCylinder(BlockVector2 center, Vector2 radius, int maxPoints) {
int nPoints = (int) Math.ceil(Math.PI * radius.length());
// These strange semantics for maxPoints are copied from the selectSecondary method.
if (maxPoints >= 0 && nPoints >= maxPoints) {
nPoints = maxPoints - 1;
}
final List<BlockVector2> points = new ArrayList<>(nPoints);
for (int i = 0; i < nPoints; ++i) {
double angle = i * (2.0 * Math.PI) / nPoints;
final Vector2 pos = Vector2.at(Math.cos(angle), Math.sin(angle));
final BlockVector2 blockVector2D = pos.multiply(radius).toBlockPoint().add(center);
points.add(blockVector2D);
}
return points;
}
use of com.sk89q.worldedit.math.Vector2 in project FastAsyncWorldEdit by IntellectualSites.
the class Spline method pastePositionDirect.
/**
* Paste structure at the provided position on the curve. The position will not be position-corrected
* but will be passed directly to the interpolation algorithm.
*
* @param position The position on the curve. Must be between 0.0 and 1.0 (both inclusive)
* @return The amount of blocks that have been changed
* @throws MaxChangedBlocksException Thrown by WorldEdit if the limit of block changes for the {@link EditSession} has been reached
*/
public int pastePositionDirect(double position) throws MaxChangedBlocksException {
Preconditions.checkArgument(position >= 0);
Preconditions.checkArgument(position <= 1);
// Calculate position from spline
Vector3 target = interpolation.getPosition(position);
BlockVector3 blockTarget = target.toBlockPoint();
Vector3 offset = target.subtract(target.floor());
// Calculate rotation from spline
Vector3 deriv = interpolation.get1stDerivative(position);
Vector2 deriv2D = Vector2.at(deriv.getX(), deriv.getZ()).normalize();
double angle = Math.toDegrees(-Math.atan2(cross2D(direction, deriv2D), direction.dot(deriv2D)));
// Wrap to 360 degrees
angle = ((angle % 360) + 360) % 360;
return pasteBlocks(blockTarget, offset, angle);
}
Aggregations