mirror of
https://github.com/EngineHub/WorldGuard.git
synced 2024-12-27 19:47:56 +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.Vector;
|
||||
|
||||
import java.awt.geom.Area;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@ -47,6 +49,11 @@ public GlobalProtectedRegion(String id) {
|
||||
max = new BlockVector(0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPhysicalArea() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockVector2D> getPoints() {
|
||||
// This doesn't make sense
|
||||
@ -74,7 +81,12 @@ public RegionType getType() {
|
||||
@Override
|
||||
public List<ProtectedRegion> getIntersectingRegions(Collection<ProtectedRegion> regions) {
|
||||
// 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.worldguard.util.MathUtils;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Area;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
@ -83,6 +84,11 @@ public void setMaximumPoint(BlockVector position) {
|
||||
setMinMaxPoints(min, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPhysicalArea() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockVector2D> getPoints() {
|
||||
List<BlockVector2D> pts = new ArrayList<BlockVector2D>();
|
||||
@ -115,30 +121,21 @@ public RegionType getType() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProtectedRegion> getIntersectingRegions(Collection<ProtectedRegion> regions) {
|
||||
checkNotNull(regions);
|
||||
Area toArea() {
|
||||
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>();
|
||||
|
||||
for (ProtectedRegion region : regions) {
|
||||
if (!intersectsBoundingBox(region)) continue;
|
||||
|
||||
// If both regions are Cuboids and their bounding boxes intersect, they intersect
|
||||
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.");
|
||||
}
|
||||
@Override
|
||||
protected boolean intersects(ProtectedRegion region, Area thisArea) {
|
||||
if (region instanceof ProtectedCuboidRegion) {
|
||||
return intersectsBoundingBox(region);
|
||||
} else {
|
||||
return super.intersects(region, thisArea);
|
||||
}
|
||||
return intersectingRegions;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -22,8 +22,10 @@
|
||||
import com.sk89q.worldedit.BlockVector2D;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Area;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
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) {
|
||||
super(id);
|
||||
setMinMaxPoints(points, minY, maxY);
|
||||
this.points = points;
|
||||
this.points = Collections.unmodifiableList(points);
|
||||
this.minY = min.getBlockY();
|
||||
this.maxY = max.getBlockY();
|
||||
}
|
||||
@ -61,6 +63,11 @@ private void setMinMaxPoints(List<BlockVector2D> points2D, int minY, int maxY) {
|
||||
setMinMaxPoints(points);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPhysicalArea() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockVector2D> getPoints() {
|
||||
return points;
|
||||
@ -133,27 +140,21 @@ public RegionType getType() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProtectedRegion> getIntersectingRegions(Collection<ProtectedRegion> regions) {
|
||||
checkNotNull(regions);
|
||||
Area toArea() {
|
||||
List<BlockVector2D> points = getPoints();
|
||||
int numPoints = points.size();
|
||||
int[] xCoords = new int[numPoints];
|
||||
int[] yCoords = new int[numPoints];
|
||||
|
||||
List<ProtectedRegion> intersectingRegions = new ArrayList<ProtectedRegion>();
|
||||
|
||||
for (ProtectedRegion region : regions) {
|
||||
if (!intersectsBoundingBox(region)) continue;
|
||||
|
||||
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.");
|
||||
}
|
||||
int i = 0;
|
||||
for (BlockVector2D point : points) {
|
||||
xCoords[i] = point.getBlockX();
|
||||
yCoords[i] = point.getBlockZ();
|
||||
i++;
|
||||
}
|
||||
return intersectingRegions;
|
||||
|
||||
Polygon polygon = new Polygon(xCoords, yCoords, numPoints);
|
||||
return new Area(polygon);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package com.sk89q.worldguard.protection.regions;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.BlockVector2D;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
@ -29,6 +30,7 @@
|
||||
import com.sk89q.worldguard.util.Normal;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.awt.geom.Area;
|
||||
import java.awt.geom.Line2D;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@ -118,6 +120,13 @@ public String getId() {
|
||||
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
|
||||
* 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
|
||||
* @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
|
||||
@ -631,6 +672,14 @@ protected boolean intersectsEdges(ProtectedRegion region) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the AWT area, otherwise null if
|
||||
* {@link #isPhysicalArea()} if false.
|
||||
*
|
||||
* @return The shape version
|
||||
*/
|
||||
abstract Area toArea();
|
||||
|
||||
@Override
|
||||
public boolean isDirty() {
|
||||
return dirty || owners.isDirty() || members.isDirty();
|
||||
|
Loading…
Reference in New Issue
Block a user