Search in sources :

Example 1 with BlockVector2

use of com.sk89q.worldedit.math.BlockVector2 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++;
    }
}
Also used : BlockVector2(com.sk89q.worldedit.math.BlockVector2) Vector2(com.sk89q.worldedit.math.Vector2) ArrayList(java.util.ArrayList) BlockVector2(com.sk89q.worldedit.math.BlockVector2)

Example 2 with BlockVector2

use of com.sk89q.worldedit.math.BlockVector2 in project ProtectionStones by espidev.

the class WGMerge method mergeRegions.

// returns a merged region; root and merge must be overlapping or adjacent
// merge parameter must all be decomposed regions (down to cuboids, no polygon)
private static ProtectedRegion mergeRegions(String newID, PSRegion root, List<PSRegion> merge) throws RegionHoleException {
    HashSet<BlockVector2> points = new HashSet<>();
    List<ProtectedRegion> regions = new ArrayList<>();
    // decompose regions down to their points
    for (PSRegion r : merge) {
        points.addAll(WGUtils.getPointsFromDecomposedRegion(r));
        regions.add(r.getWGRegion());
    }
    // points of new region
    List<BlockVector2> vertex = new ArrayList<>();
    HashMap<Integer, ArrayList<BlockVector2>> vertexGroups = new HashMap<>();
    // traverse region edges for vertex
    RegionTraverse.traverseRegionEdge(points, regions, tr -> {
        if (tr.isVertex) {
            if (vertexGroups.containsKey(tr.vertexGroupID)) {
                vertexGroups.get(tr.vertexGroupID).add(tr.point);
            } else {
                vertexGroups.put(tr.vertexGroupID, new ArrayList<>(Arrays.asList(tr.point)));
            }
        }
    });
    // prevent holes from being formed
    if (vertexGroups.size() > 1 && !ProtectionStones.getInstance().getConfigOptions().allowMergingHoles) {
        throw new RegionHoleException();
    }
    // assemble vertex group
    // draw in and out lines between holes
    boolean first = true;
    BlockVector2 backPoint = null;
    for (List<BlockVector2> l : vertexGroups.values()) {
        if (first) {
            first = false;
            vertex.addAll(l);
            backPoint = l.get(0);
        } else {
            vertex.addAll(l);
            vertex.add(l.get(0));
        }
        vertex.add(backPoint);
    }
    // merge sets of region name flag
    Set<String> regionNames = new HashSet<>(), regionLines = new HashSet<>();
    for (PSRegion r : merge) {
        if (r.getWGRegion().getFlag(FlagHandler.PS_MERGED_REGIONS) != null) {
            regionNames.addAll(r.getWGRegion().getFlag(FlagHandler.PS_MERGED_REGIONS));
            regionLines.addAll(r.getWGRegion().getFlag(FlagHandler.PS_MERGED_REGIONS_TYPES));
        } else {
            regionNames.add(r.getId());
            regionLines.add(r.getId() + " " + r.getType());
        }
    }
    // create new merged region
    ProtectedRegion r = new ProtectedPolygonalRegion(newID, vertex, WGUtils.MIN_BUILD_HEIGHT, WGUtils.MAX_BUILD_HEIGHT);
    r.copyFrom(root.getWGRegion());
    // only make it a merged region if there is more than one contained region
    if (regionNames.size() > 1 && regionLines.size() > 1) {
        r.setFlag(FlagHandler.PS_MERGED_REGIONS, regionNames);
        r.setFlag(FlagHandler.PS_MERGED_REGIONS_TYPES, regionLines);
    } else {
        r.setFlag(FlagHandler.PS_MERGED_REGIONS, null);
        r.setFlag(FlagHandler.PS_MERGED_REGIONS_TYPES, null);
    }
    return r;
}
Also used : BlockVector2(com.sk89q.worldedit.math.BlockVector2) ProtectedRegion(com.sk89q.worldguard.protection.regions.ProtectedRegion) ProtectedPolygonalRegion(com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion)

Example 3 with BlockVector2

use of com.sk89q.worldedit.math.BlockVector2 in project FastAsyncWorldEdit by IntellectualSites.

the class Polygonal2DRegion method toString.

/**
 * Returns string representation in the format
 * "(x1, z1) - ... - (xN, zN) * (minY - maxY)"
 *
 * @return string
 */
@Override
public String toString() {
    StringBuilder sb = new StringBuilder();
    List<BlockVector2> pts = getPoints();
    Iterator<BlockVector2> it = pts.iterator();
    while (it.hasNext()) {
        BlockVector2 current = it.next();
        sb.append("(").append(current.getBlockX()).append(", ").append(current.getBlockZ()).append(")");
        if (it.hasNext()) {
            sb.append(" - ");
        }
    }
    sb.append(" * (").append(minY).append(" - ").append(maxY).append(")");
    return sb.toString();
}
Also used : BlockVector2(com.sk89q.worldedit.math.BlockVector2)

Example 4 with BlockVector2

use of com.sk89q.worldedit.math.BlockVector2 in project FastAsyncWorldEdit by IntellectualSites.

the class Polygonal2DRegion method shift.

@Override
public void shift(BlockVector3 change) throws RegionOperationException {
    final double changeX = change.getX();
    final double changeY = change.getY();
    final double changeZ = change.getZ();
    for (int i = 0; i < points.size(); ++i) {
        BlockVector2 point = points.get(i);
        points.set(i, BlockVector2.at(point.getX() + changeX, point.getZ() + changeZ));
    }
    minY += changeY;
    maxY += changeY;
    recalculate();
}
Also used : BlockVector2(com.sk89q.worldedit.math.BlockVector2)

Example 5 with BlockVector2

use of com.sk89q.worldedit.math.BlockVector2 in project FastAsyncWorldEdit by IntellectualSites.

the class Polygonal2DRegion method recalculate.

/**
 * Recalculate the bounding box of this polygonal region. This should be
 * called after points have been changed.
 */
protected void recalculate() {
    if (points.isEmpty()) {
        min = BlockVector2.ZERO;
        minY = 0;
        max = BlockVector2.ZERO;
        maxY = 0;
        return;
    }
    int minX = points.get(0).getBlockX();
    int minZ = points.get(0).getBlockZ();
    int maxX = points.get(0).getBlockX();
    int maxZ = points.get(0).getBlockZ();
    for (BlockVector2 v : points) {
        int x = v.getBlockX();
        int z = v.getBlockZ();
        if (x < minX) {
            minX = x;
        }
        if (z < minZ) {
            minZ = z;
        }
        if (x > maxX) {
            maxX = x;
        }
        if (z > maxZ) {
            maxZ = z;
        }
    }
    int oldMinY = minY;
    int oldMaxY = maxY;
    minY = Math.min(oldMinY, oldMaxY);
    maxY = Math.max(oldMinY, oldMaxY);
    minY = Math.min(Math.max(getWorldMinY(), minY), getWorldMaxY());
    maxY = Math.min(Math.max(getWorldMinY(), maxY), getWorldMaxY());
    min = BlockVector2.at(minX, minZ);
    max = BlockVector2.at(maxX, maxZ);
}
Also used : BlockVector2(com.sk89q.worldedit.math.BlockVector2)

Aggregations

BlockVector2 (com.sk89q.worldedit.math.BlockVector2)55 BlockVector3 (com.sk89q.worldedit.math.BlockVector3)19 ArrayList (java.util.ArrayList)13 IOException (java.io.IOException)9 Map (java.util.Map)9 ProtectedPolygonalRegion (com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion)7 ProtectedRegion (com.sk89q.worldguard.protection.regions.ProtectedRegion)6 LinkedHashMap (java.util.LinkedHashMap)6 GlobalProtectedRegion (com.sk89q.worldguard.protection.regions.GlobalProtectedRegion)5 Path (java.nio.file.Path)5 Iterator (java.util.Iterator)5 Set (java.util.Set)5 JsonIOException (com.google.gson.JsonIOException)4 CuboidRegion (com.sk89q.worldedit.regions.CuboidRegion)4 Location (com.sk89q.worldedit.util.Location)4 HashMap (java.util.HashMap)4 HashSet (java.util.HashSet)4 List (java.util.List)4 CommandPermissions (com.sk89q.worldedit.command.util.CommandPermissions)3 Region (com.sk89q.worldedit.regions.Region)3