mirror of
https://github.com/EngineHub/WorldGuard.git
synced 2024-12-28 12:07:46 +01:00
Fix region intersection tests involving polygons.
Fixes WORLDGUARD-3216.
This commit is contained in:
parent
47a8bcc442
commit
bca1c2bdb3
@ -23,8 +23,10 @@
|
|||||||
import com.sk89q.worldedit.BlockVector2D;
|
import com.sk89q.worldedit.BlockVector2D;
|
||||||
import com.sk89q.worldedit.Vector;
|
import com.sk89q.worldedit.Vector;
|
||||||
|
|
||||||
|
import java.awt.geom.Area;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,6 +49,11 @@ public GlobalProtectedRegion(String id) {
|
|||||||
max = new BlockVector(0, 0, 0);
|
max = new BlockVector(0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPhysicalArea() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<BlockVector2D> getPoints() {
|
public List<BlockVector2D> getPoints() {
|
||||||
// This doesn't make sense
|
// This doesn't make sense
|
||||||
@ -74,7 +81,12 @@ public RegionType getType() {
|
|||||||
@Override
|
@Override
|
||||||
public List<ProtectedRegion> getIntersectingRegions(Collection<ProtectedRegion> regions) {
|
public List<ProtectedRegion> getIntersectingRegions(Collection<ProtectedRegion> regions) {
|
||||||
// Global regions are handled separately so it must not contain any positions
|
// Global regions are handled separately so it must not contain any positions
|
||||||
return new ArrayList<ProtectedRegion>();
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Area toArea() {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,8 +24,9 @@
|
|||||||
import com.sk89q.worldedit.Vector;
|
import com.sk89q.worldedit.Vector;
|
||||||
import com.sk89q.worldguard.util.MathUtils;
|
import com.sk89q.worldguard.util.MathUtils;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.geom.Area;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
@ -83,6 +84,11 @@ public void setMaximumPoint(BlockVector position) {
|
|||||||
setMinMaxPoints(min, position);
|
setMinMaxPoints(min, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPhysicalArea() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<BlockVector2D> getPoints() {
|
public List<BlockVector2D> getPoints() {
|
||||||
List<BlockVector2D> pts = new ArrayList<BlockVector2D>();
|
List<BlockVector2D> pts = new ArrayList<BlockVector2D>();
|
||||||
@ -115,30 +121,21 @@ public RegionType getType() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ProtectedRegion> getIntersectingRegions(Collection<ProtectedRegion> regions) {
|
Area toArea() {
|
||||||
checkNotNull(regions);
|
int x = getMinimumPoint().getBlockX();
|
||||||
|
int z = getMinimumPoint().getBlockZ();
|
||||||
|
int width = getMaximumPoint().getBlockX() - x;
|
||||||
|
int height = getMaximumPoint().getBlockZ() - z;
|
||||||
|
return new Area(new Rectangle(x, z, width, height));
|
||||||
|
}
|
||||||
|
|
||||||
List<ProtectedRegion> intersectingRegions = new ArrayList<ProtectedRegion>();
|
@Override
|
||||||
|
protected boolean intersects(ProtectedRegion region, Area thisArea) {
|
||||||
for (ProtectedRegion region : regions) {
|
if (region instanceof ProtectedCuboidRegion) {
|
||||||
if (!intersectsBoundingBox(region)) continue;
|
return intersectsBoundingBox(region);
|
||||||
|
} else {
|
||||||
// If both regions are Cuboids and their bounding boxes intersect, they intersect
|
return super.intersects(region, thisArea);
|
||||||
if (region instanceof ProtectedCuboidRegion) {
|
|
||||||
intersectingRegions.add(region);
|
|
||||||
} else if (region instanceof ProtectedPolygonalRegion) {
|
|
||||||
// If either region contains the points of the other,
|
|
||||||
// or if any edges intersect, the regions intersect
|
|
||||||
if (containsAny(region.getPoints()) || region.containsAny(getPoints()) || intersectsEdges(region)) {
|
|
||||||
intersectingRegions.add(region);
|
|
||||||
}
|
|
||||||
} else if (region instanceof GlobalProtectedRegion) {
|
|
||||||
// Never intersects
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Not supported yet.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return intersectingRegions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -22,8 +22,10 @@
|
|||||||
import com.sk89q.worldedit.BlockVector2D;
|
import com.sk89q.worldedit.BlockVector2D;
|
||||||
import com.sk89q.worldedit.Vector;
|
import com.sk89q.worldedit.Vector;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.geom.Area;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
@ -37,7 +39,7 @@ public class ProtectedPolygonalRegion extends ProtectedRegion {
|
|||||||
public ProtectedPolygonalRegion(String id, List<BlockVector2D> points, int minY, int maxY) {
|
public ProtectedPolygonalRegion(String id, List<BlockVector2D> points, int minY, int maxY) {
|
||||||
super(id);
|
super(id);
|
||||||
setMinMaxPoints(points, minY, maxY);
|
setMinMaxPoints(points, minY, maxY);
|
||||||
this.points = points;
|
this.points = Collections.unmodifiableList(points);
|
||||||
this.minY = min.getBlockY();
|
this.minY = min.getBlockY();
|
||||||
this.maxY = max.getBlockY();
|
this.maxY = max.getBlockY();
|
||||||
}
|
}
|
||||||
@ -61,6 +63,11 @@ private void setMinMaxPoints(List<BlockVector2D> points2D, int minY, int maxY) {
|
|||||||
setMinMaxPoints(points);
|
setMinMaxPoints(points);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPhysicalArea() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<BlockVector2D> getPoints() {
|
public List<BlockVector2D> getPoints() {
|
||||||
return points;
|
return points;
|
||||||
@ -133,27 +140,21 @@ public RegionType getType() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ProtectedRegion> getIntersectingRegions(Collection<ProtectedRegion> regions) {
|
Area toArea() {
|
||||||
checkNotNull(regions);
|
List<BlockVector2D> points = getPoints();
|
||||||
|
int numPoints = points.size();
|
||||||
|
int[] xCoords = new int[numPoints];
|
||||||
|
int[] yCoords = new int[numPoints];
|
||||||
|
|
||||||
List<ProtectedRegion> intersectingRegions = new ArrayList<ProtectedRegion>();
|
int i = 0;
|
||||||
|
for (BlockVector2D point : points) {
|
||||||
for (ProtectedRegion region : regions) {
|
xCoords[i] = point.getBlockX();
|
||||||
if (!intersectsBoundingBox(region)) continue;
|
yCoords[i] = point.getBlockZ();
|
||||||
|
i++;
|
||||||
if (region instanceof ProtectedPolygonalRegion || region instanceof ProtectedCuboidRegion) {
|
|
||||||
// If either region contains the points of the other,
|
|
||||||
// or if any edges intersect, the regions intersect
|
|
||||||
if (containsAny(region.getPoints()) || region.containsAny(getPoints()) || intersectsEdges(region)) {
|
|
||||||
intersectingRegions.add(region);
|
|
||||||
}
|
|
||||||
} else if (region instanceof GlobalProtectedRegion) {
|
|
||||||
// Never intersects
|
|
||||||
} else {
|
|
||||||
throw new IllegalArgumentException("Not supported yet.");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return intersectingRegions;
|
|
||||||
|
Polygon polygon = new Polygon(xCoords, yCoords, numPoints);
|
||||||
|
return new Area(polygon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package com.sk89q.worldguard.protection.regions;
|
package com.sk89q.worldguard.protection.regions;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
import com.sk89q.worldedit.BlockVector;
|
import com.sk89q.worldedit.BlockVector;
|
||||||
import com.sk89q.worldedit.BlockVector2D;
|
import com.sk89q.worldedit.BlockVector2D;
|
||||||
import com.sk89q.worldedit.Vector;
|
import com.sk89q.worldedit.Vector;
|
||||||
@ -29,6 +30,7 @@
|
|||||||
import com.sk89q.worldguard.util.Normal;
|
import com.sk89q.worldguard.util.Normal;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import java.awt.geom.Area;
|
||||||
import java.awt.geom.Line2D;
|
import java.awt.geom.Line2D;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -118,6 +120,13 @@ public String getId() {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether this type of region encompasses physical area.
|
||||||
|
*
|
||||||
|
* @return Whether physical area is encompassed
|
||||||
|
*/
|
||||||
|
public abstract boolean isPhysicalArea();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a vector containing the smallest X, Y, and Z components for the
|
* Get a vector containing the smallest X, Y, and Z components for the
|
||||||
* corner of the axis-aligned bounding box that contains this region.
|
* corner of the axis-aligned bounding box that contains this region.
|
||||||
@ -570,7 +579,39 @@ public final String getTypeName() {
|
|||||||
* @param regions a list of regions to source from
|
* @param regions a list of regions to source from
|
||||||
* @return the elements of {@code regions} that intersect with this region
|
* @return the elements of {@code regions} that intersect with this region
|
||||||
*/
|
*/
|
||||||
public abstract List<ProtectedRegion> getIntersectingRegions(Collection<ProtectedRegion> regions);
|
public List<ProtectedRegion> getIntersectingRegions(Collection<ProtectedRegion> regions) {
|
||||||
|
checkNotNull(regions, "regions");
|
||||||
|
|
||||||
|
List<ProtectedRegion> intersecting = Lists.newArrayList();
|
||||||
|
Area thisArea = toArea();
|
||||||
|
|
||||||
|
for (ProtectedRegion region : regions) {
|
||||||
|
if (!region.isPhysicalArea()) continue;
|
||||||
|
|
||||||
|
if (intersects(region, thisArea)) {
|
||||||
|
intersecting.add(region);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return intersecting;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether the given region intersects with this area.
|
||||||
|
*
|
||||||
|
* @param region the region to test
|
||||||
|
* @param thisArea an area object for this region
|
||||||
|
* @return true if the two regions intersect
|
||||||
|
*/
|
||||||
|
protected boolean intersects(ProtectedRegion region, Area thisArea) {
|
||||||
|
if (intersectsBoundingBox(region)) {
|
||||||
|
Area testArea = region.toArea();
|
||||||
|
testArea.intersect(thisArea);
|
||||||
|
return !testArea.isEmpty();
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the bounding box of a region intersects with with the bounding
|
* Checks if the bounding box of a region intersects with with the bounding
|
||||||
@ -631,6 +672,14 @@ protected boolean intersectsEdges(ProtectedRegion region) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the AWT area, otherwise null if
|
||||||
|
* {@link #isPhysicalArea()} if false.
|
||||||
|
*
|
||||||
|
* @return The shape version
|
||||||
|
*/
|
||||||
|
abstract Area toArea();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDirty() {
|
public boolean isDirty() {
|
||||||
return dirty || owners.isDirty() || members.isDirty();
|
return dirty || owners.isDirty() || members.isDirty();
|
||||||
|
Loading…
Reference in New Issue
Block a user