diff --git a/src/main/java/com/sk89q/worldedit/regions/AbstractRegion.java b/src/main/java/com/sk89q/worldedit/regions/AbstractRegion.java index 506b7e867..b82e70dc1 100644 --- a/src/main/java/com/sk89q/worldedit/regions/AbstractRegion.java +++ b/src/main/java/com/sk89q/worldedit/regions/AbstractRegion.java @@ -19,9 +19,12 @@ package com.sk89q.worldedit.regions; +import java.util.ArrayList; import java.util.Iterator; +import java.util.List; import com.sk89q.worldedit.BlockVector; +import com.sk89q.worldedit.BlockVector2D; import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.Vector; @@ -69,4 +72,23 @@ public abstract class AbstractRegion implements Region { return null; } } + + @Override + public List polygonize(int maxPoints) { + if (maxPoints >= 0 && maxPoints < 4) { + throw new IllegalArgumentException("Cannot polygonize an AbstractRegion with no overridden polygonize method into less than 4 points."); + } + + final BlockVector min = getMinimumPoint().toBlockVector(); + final BlockVector max = getMaximumPoint().toBlockVector(); + + final List points = new ArrayList(4); + + points.add(new BlockVector2D(min.getX(), min.getZ())); + points.add(new BlockVector2D(min.getX(), max.getZ())); + points.add(new BlockVector2D(max.getX(), max.getZ())); + points.add(new BlockVector2D(max.getX(), min.getZ())); + + return points; + } } diff --git a/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java b/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java index 536316c9f..7f8c3ce73 100644 --- a/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java +++ b/src/main/java/com/sk89q/worldedit/regions/CylinderRegion.java @@ -19,8 +19,10 @@ package com.sk89q.worldedit.regions; +import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; +import java.util.List; import java.util.Set; import com.sk89q.worldedit.BlockVector; @@ -408,4 +410,25 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion { public CylinderRegion clone() { return (CylinderRegion) super.clone(); } + + @Override + public List polygonize(int maxPoints) { + final Vector2D radius = getRadius(); + 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 points = new ArrayList(nPoints); + for (int i = 0; i < nPoints; ++i) { + double angle = i * (2.0 * Math.PI) / nPoints; + final Vector2D pos = new Vector2D(Math.cos(angle), Math.sin(angle)); + final BlockVector2D blockVector2D = pos.multiply(radius).add(center).toBlockVector2D(); + points.add(blockVector2D); + } + + return points; + } } diff --git a/src/main/java/com/sk89q/worldedit/regions/Polygonal2DRegion.java b/src/main/java/com/sk89q/worldedit/regions/Polygonal2DRegion.java index 070c5dcdb..204200ddd 100644 --- a/src/main/java/com/sk89q/worldedit/regions/Polygonal2DRegion.java +++ b/src/main/java/com/sk89q/worldedit/regions/Polygonal2DRegion.java @@ -530,4 +530,13 @@ public class Polygonal2DRegion extends AbstractRegion implements FlatRegion { clone.points = new ArrayList(points); return clone; } + + @Override + public List polygonize(int maxPoints) { + if (maxPoints >= 0 && maxPoints < points.size()) { + throw new IllegalArgumentException("Cannot polygonize a this Polygonal2DRegion into the amount of points given."); + } + + return points; + } } diff --git a/src/main/java/com/sk89q/worldedit/regions/Polygonal2DRegionSelector.java b/src/main/java/com/sk89q/worldedit/regions/Polygonal2DRegionSelector.java index 8e24ed7e0..628179a96 100644 --- a/src/main/java/com/sk89q/worldedit/regions/Polygonal2DRegionSelector.java +++ b/src/main/java/com/sk89q/worldedit/regions/Polygonal2DRegionSelector.java @@ -19,7 +19,6 @@ package com.sk89q.worldedit.regions; -import java.util.ArrayList; import java.util.Collections; import java.util.List; import com.sk89q.worldedit.BlockVector; @@ -29,7 +28,6 @@ import com.sk89q.worldedit.LocalPlayer; import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.Vector; -import com.sk89q.worldedit.Vector2D; import com.sk89q.worldedit.cui.CUIRegion; import com.sk89q.worldedit.cui.SelectionMinMaxEvent; import com.sk89q.worldedit.cui.SelectionPoint2DEvent; @@ -67,33 +65,6 @@ public class Polygonal2DRegionSelector implements RegionSelector, CUIRegion { pos1 = polygonal2DRegionSelector.pos1; region = new Polygonal2DRegion(polygonal2DRegionSelector.region); - } else if (oldSelector instanceof CylinderRegionSelector) { - final CylinderRegionSelector cylinderRegionSelector = (CylinderRegionSelector) oldSelector; - - final CylinderRegion oldRegion = cylinderRegionSelector.region; - - final Vector2D radius = oldRegion.getRadius(); - final Vector2D center = oldRegion.getCenter().toVector2D(); - int nPoints = (int) Math.ceil(Math.PI*radius.length()); - - // These strange semantics for maxPoints are copied from the selectSecondary method. - if (maxPoints > -1 && nPoints >= maxPoints) { - nPoints = maxPoints - 1; - } - - final List points = new ArrayList(nPoints); - for (int i = 0; i < nPoints; ++i) { - double angle = i * (2.0 * Math.PI) / nPoints; - final Vector2D pos = new Vector2D(Math.cos(angle), Math.sin(angle)); - final BlockVector2D blockVector2D = pos.multiply(radius).add(center).toBlockVector2D(); - points.add(blockVector2D); - } - - final int minY = oldRegion.getMinimumY(); - - pos1 = points.get(0).toVector(minY).toBlockVector(); - region = new Polygonal2DRegion(oldRegion.getWorld(), points, minY, oldRegion.getMaximumY()); - } else { final Region oldRegion; try { @@ -102,20 +73,12 @@ public class Polygonal2DRegionSelector implements RegionSelector, CUIRegion { return; } - BlockVector min = oldRegion.getMinimumPoint().toBlockVector(); - BlockVector max = oldRegion.getMaximumPoint().toBlockVector(); + final int minY = oldRegion.getMinimumPoint().getBlockY(); + final int maxY = oldRegion.getMaximumPoint().getBlockY(); - int minY = min.getBlockY(); - int maxY = max.getBlockY(); + List points = oldRegion.polygonize(maxPoints); - List points = new ArrayList(4); - - points.add(new BlockVector2D(min.getX(), min.getZ())); - points.add(new BlockVector2D(min.getX(), max.getZ())); - points.add(new BlockVector2D(max.getX(), max.getZ())); - points.add(new BlockVector2D(max.getX(), min.getZ())); - - pos1 = min; + pos1 = points.get(0).toVector(minY).toBlockVector(); region = new Polygonal2DRegion(oldRegion.getWorld(), points, minY, maxY); } } @@ -148,7 +111,7 @@ public class Polygonal2DRegionSelector implements RegionSelector, CUIRegion { return false; } - if (maxPoints > -1 && points.size() >= maxPoints) { + if (maxPoints >= 0 && points.size() > maxPoints) { return false; } } diff --git a/src/main/java/com/sk89q/worldedit/regions/Region.java b/src/main/java/com/sk89q/worldedit/regions/Region.java index 1eb179f0d..e1785a132 100644 --- a/src/main/java/com/sk89q/worldedit/regions/Region.java +++ b/src/main/java/com/sk89q/worldedit/regions/Region.java @@ -20,9 +20,12 @@ package com.sk89q.worldedit.regions; import com.sk89q.worldedit.BlockVector; +import com.sk89q.worldedit.BlockVector2D; import com.sk89q.worldedit.LocalWorld; import com.sk89q.worldedit.Vector; import com.sk89q.worldedit.Vector2D; + +import java.util.List; import java.util.Set; /** @@ -142,4 +145,12 @@ public interface Region extends Iterable, Cloneable { public void setWorld(LocalWorld world); public Region clone(); + + /** + * Polygonizes a cross-section or a 2D projection of the region orthogonal to the Y axis. + * + * @param maxPoints maximum number of points to generate. -1 for no limit. + * @return the points. + */ + public List polygonize(int maxPoints); }