给出两个多边形:
POLYGON((1 0, 1 8, 6 4, 1 0))
POLYGON((4 1, 3 5, 4 9, 9 5, 4 1),(4 5, 5 7, 6 7, 4 4, 4 5))
如何计算并集(组合多边形)?
Dave's example使用SQL服务器生成联合,但我需要在代码中完成相同的操作。我正在寻找任何暴露实际数学的语言的数学公式或代码示例。我正在尝试制作将国家动态组合到地区的地图。我在这里问了一个相关的问题:Grouping geographical shapes
答案 0 :(得分:54)
这是一个非常好的问题。我前段时间在c#上实现了相同的算法。算法构造两个多边形的公共轮廓(即构造一个没有孔的联合)。在这里。
输入:第一个多边形(n个点),第二个多边形(m个点)。输出:图表。顶点 - 多边形交点。
我们应该找到交叉点。遍历两个多边形[O(n * m)]中的所有多边形边并找到任何交点。
如果找不到交叉点,只需添加顶点并连接它们即可 到了边缘。
如果找到任何交叉点,请按长度对它们的起点进行排序,然后添加全部 顶点(开始,结束和交叉点)并连接它们(已经在 排序顺序)到边缘。
如果我们在构建图形时没有找到任何交叉点,则我们有以下条件之一:
找到最小x和y坐标(minx,miny)。然后找到(minx,miny)和多边形点之间的最小距离。这一点将是左下角。
我们开始从左下角遍历图表并继续直到我们回到它。在开始时,我们将所有边标记为未访问。在每次迭代中,您应该选择下一个点并将其标记为已访问。
要选择下一个点,请选择逆时针方向内角最大的边。
我计算了两个向量:当前边缘的vector1和下一个未访问边缘的vector2(如图所示)。
对于我计算的向量:
结果我得到了一个具有最大角度的边(和一个对应的下一个顶点)。
我将每个传递的顶点添加到结果列表中。结果列表是联合多边形。
答案 1 :(得分:7)
这是一个具有挑战性但很容易理解的话题 名为“多边形上的正则化布尔运算”。 你可能会看 this MathOverflow answer, 其中包括下图 (来自Alan Murta's clipping library), 使用粉红色联合OP的组合:
<小时/>
答案 2 :(得分:6)
您需要determine which points lie inside。删除这些点后,您可以将一组“外部”点插入另一组。您的插入点(例如,右侧图片中有箭头的位置)是您必须从输入集中删除点的位置。
答案 3 :(得分:4)
好问题!我以前从未尝试过这个,但我现在会对它进行一次破解。
首先:您需要知道这两个形状重叠的位置。要做到这一点,你可以查看Polygon A中的每一条边,看看它在Polygon B中的相交和边缘。在这个例子中,应该有两个交点。
然后:使联合形状。您可以获取A和B中的所有顶点,以及交点,然后排除最终形状包含的顶点。为了找到这些点,看起来你可以找到B内部的A的任何顶点,以及A内部的任何B的椎骨。
答案 4 :(得分:4)
尝试gpc。
答案 5 :(得分:2)
我已经看到了使用BSP树的解决方案here。
基本上,它根据多边形 A 边缘的并集来描述交集,这些边在多边形 B 内(包括部分边缘,并使用{{3计算) }})。然后,您可以将 A / B 定义为〜(〜 A / \〜 B ),其中〜表示反转多边形的绕组,/表示联合和/ \表示交叉。
答案 6 :(得分:1)
在对国家进行分组时,我希望没有重叠 - 您可以采用一种相当天真的算法来寻找共享顶点 - 一个简单的视图就是迭代一个多边形上的点,看看它是否在任何一个上您的其他多边形,并分享相同的下一个或上一个点,以查看是否匹配。然后只需删除共享顶点即可创建联合
答案 7 :(得分:1)
我今天需要解决同样的问题并找到了这个lib的解决方案:http://www.cs.man.ac.uk/~toby/alan/software/。
它有很多语言实现the list here,包括Java,Obj-C,C#,Lua,python等。
答案 8 :(得分:1)
我遇到了同样的问题,并通过以下方式解决了问题
Cython包装器,用于Angus Johnson's Clipper库的C ++翻译(版本6.4.2) https://github.com/fonttools/pyclipper
pc = pyclipper.Pyclipper()
def get_poly_union(polygons):
pc.AddPaths(polygons, pyclipper.PT_SUBJECT, True)
solution = pc.Execute(pyclipper.CT_UNION, pyclipper.PFT_NONZERO, pyclipper.PFT_NONZERO)
return solution[0]
print_image = image.copy()
solution = get_poly_union(polygons_array)
#polygons_array=[polygon,polygon,polygon, ...,polygon] and polygon=[point,point,point...,point]
cv2.drawContours(print_image, [np.asarray(solution)], -1, (0, 255, 0), 2)
plt.imshow(print_image)
答案 9 :(得分:0)
这是一个非常老的问题,但是Boost的Union_函数对我有用。
请参见以下代码段:
#include <iostream>
#include <vector>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/foreach.hpp>
int main()
{
typedef boost::geometry::model::polygon<boost::geometry::model::d2::point_xy<double> > polygon;
polygon green, blue;
boost::geometry::read_wkt(
"POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))", green);
boost::geometry::read_wkt(
"POLYGON((5 5, 5 15, 15 15, 15 5, 5 5))", blue);
std::vector<polygon> output;
boost::geometry::union_(green, blue, output);
int i = 0;
std::cout << "green || blue:" << std::endl;
BOOST_FOREACH(polygon const& p, output)
{
std::cout << i++ << ": " << boost::geometry::area(p) << std::endl;
for (int i = 0; i < p.outer().size(); i++)
{
std::cout << p.outer().at(i).x() << " " << p.outer().at(i).y() << std::endl;
}
}
return 0;
}