说我有两个矩形的两个坐标(x,y)数组,例如[(0,0),(0,1),(2,1),(2,0)]和[(1 ,0),(1,2),(3,2),(3,0)]],我如何将这两个坐标数组合并为一个表示结果多边形的数组?
以图形方式看起来像这样:
_ _
_|_ |
|_|_|_|
到
_ _
_| |
|_ _ _|
具有结果数组[[0,0),(0,1),(1,1),(1,2),(3,2),(3,0)]。
我正在尝试设计某种合并算法,但是我不确定从哪里开始。
对于输入,将有两个数组,此方法将返回一个合并的数组。
我完全不知道该从哪里开始。
答案 0 :(得分:1)
作为指针,请考虑以下内容:
我假设每个数组(r1和r2)的构造都与以下方式相同: [(左下方)(左上方)(右上方)(左上方)]
如果矩形(实体而不仅仅是角)有任何重叠,则结果可能是新数组内的四到十二个不同坐标之间。
我们首先检查哪对是最左边的,如果有一对,我们将其添加到新数组中。将r1的左下角的X坐标与r2的左下角的X坐标进行比较就足够了。如果不是,并且两个矩形的左侧都在同一X坐标上,则将左下角的Y值降低,并将左上角的Y值较大。该逻辑可以应用于所有四个方面。
在这种情况下,例如在最左侧的位置,我们仍然需要检查较小的左侧是否与顶部或底部重叠。我们可以通过从左上角r2的Y值中减去左上角r1的Y来实现。如果存在差异(也就是,左侧越小越高),我们将R2的左上角坐标与(r2 X's,r1 Y's)一起添加到数组中。极端。
因此,一般的流程是
答案 1 :(得分:0)
(排列顺序永远不会太麻烦(但在这里可能无济于事:按正旋转顺序排列点,例如从左上边缘开始)。
对于合并(a.topx .. a.bottomx)和(b.topx .. b.bottomx)必须重叠,与y相同。
外部矩形是external.topx = min(a.topx,b.topx)等等。
X坐标(可能是偶然的)是external.topx,a.topx,b.topx,external.bottom.x。 现在,您找到了多边形的一个边界。依此类推。
连接的内部边缘微不足道。
请注意,有很多形式,但广义的形式是:
...._____.....
:___| |___:
|___ ___|
:...|____|...:
问题是您是否希望合并 any 多边形的更通用算法,因为添加第三个矩形将变成完全不同的情况。
答案 2 :(得分:0)
首先,请确保第一个矩形的左下角不在另一个矩形内。如果是,请交换它们。角可以重叠或角可以在另一个矩形的一侧,这很好。
然后,开始沿逆时针方向在左侧矩形旁边并排,然后在底部右侧移至右侧。检查您是否会因为以下原因而结束:
如果到达终点,请继续在第一个矩形的右边缘上走。如果您碰到另一个矩形,则在另一个矩形的左墙上走下去。
重复直到再次加热第一个矩形的左下角。在每个点上,您都需要记住:走哪条路/走到哪一边(由于您总是逆时针方向行驶,因此可以很容易地计算出另一边),以及您要走的矩形。
如果您在步行中完全没有碰到另一个矩形,则意味着该矩形未触摸,或者第二个矩形位于第一个矩形内。
请确保仔细考虑将要使用的不等式,例如:
______
| |_| |
| |
|______|
这两个小弯角应该合并为一个,还是直线上合并3条直线的6多边形?还是应该这样:
_
|_|_
|_|
是2个不同的矩形,还是1个具有2个相同点的8多边形?
答案 3 :(得分:0)
这里有许多个自由度,用于说明方法和实际实现。只是从我的脑海中考虑一些相关的问题:
在某些情况下(如果前三个问题回答为“是”),您可能会采用一种技术上非常简单的方法:将整个输入视为“网格”,其中矩形定义了网格单元,被“填充”,最后返回填充区域的边界。
如果对其中一个的回答可能是“否”,那么您正在打开一罐蠕虫,它具有许多很多微妙之处。
幸运的是,Sun / Oracle的员工已经很好地解决了这个问题,即使对于非常复杂的问题,仍然仍然是一个简单的解决方案:您可以将输入形状,然后使用Area#add
方法来计算合并的形状。
在此示例中实现。但是请注意,与可以用于更简单情况的基于网格的方法相比,这不是很有效。而且,对于不重叠的矩形该如何处理仍然存在疑问。但是,至少对于给定的输入,结果是预期的:
import java.awt.Point;
import java.awt.Shape;
import java.awt.geom.Area;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class RectangleMerge {
public static void main(String[] args) {
List<Point2D> pointsA = Arrays.asList(new Point(0, 0), new Point(0, 1), new Point(2, 1), new Point(2, 0));
List<Point2D> pointsB = Arrays.asList(new Point(1, 0), new Point(1, 2), new Point(3, 2), new Point(3, 0));
System.out.println(merge(pointsA, pointsB));
}
private static List<Point2D> merge(List<? extends Point2D> pointsA, List<? extends Point2D> pointsB) {
Area aa = new Area(toShape(pointsA));
aa.add(new Area(toShape(pointsB)));
return toPoints(aa);
}
private static Shape toShape(List<? extends Point2D> points) {
Path2D path = new Path2D.Double();
for (int i = 0; i < points.size(); i++) {
Point2D p = points.get(i);
if (i == 0) {
path.moveTo(p.getX(), p.getY());
} else {
path.lineTo(p.getX(), p.getY());
}
}
path.closePath();
return path;
}
private static List<Point2D> toPoints(Shape shape) {
List<Point2D> result = new ArrayList<Point2D>();
PathIterator pi = shape.getPathIterator(null, 0.0);
double[] coords = new double[6];
while (!pi.isDone()) {
int segment = pi.currentSegment(coords);
switch (segment) {
case PathIterator.SEG_MOVETO:
case PathIterator.SEG_LINETO:
result.add(new Point2D.Double(coords[0], coords[1]));
break;
}
pi.next();
}
return result;
}
}