2つのポリゴンがある場合:
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))
結合(結合されたポリゴン)を計算するにはどうすればよいですか?
デイブの例 はSQLサーバーを使用してユニオンを生成しますが、コードで同じことを行う必要があります。実際の数学を公開する任意の言語の数式またはコード例を探しています。国を動的に地域に組み合わせた地図を作成しようとしています。ここで関連する質問をしました。 地理的形状のグループ化
これは非常に良い質問です。少し前に同じアルゴリズムをc#に実装しました。アルゴリズムは、2つのポリゴンの共通の輪郭を作成します(つまり、穴のない結合を作成します)。ここにあります。
入力:最初のポリゴン(nポイント)、2番目のポリゴン(mポイント)。出力:グラフ。頂点-交点のポリゴンポイント。
交差点を見つける必要があります。両方のポリゴン[O(n * m)]のすべてのポリゴンサイドを反復処理し、交差点を見つけます。
交差点が見つからない場合は、頂点を追加してエッジに接続します。
交差点が見つかった場合は、開始点までの長さで並べ替え、すべての頂点(開始点、終了点、交差点)を追加し、それらを(並べ替え済みの順序で)Edgeに接続します。
グラフの作成時に交点が見つからなかった場合、次のいずれかの条件があります。
最小のxおよびy座標(minx、miny)を見つけます。次に、(minx、miny)とポリゴンのポイント間の最小距離を見つけます。このポイントは左下のポイントになります。
左下のポイントからグラフを走査し始め、そこに戻るまで続けます。最初に、すべてのエッジを未訪問としてマークします。すべての反復で、次のポイントを選択し、訪問済みとしてマークする必要があります。
次の点を選択するには、反時計回り方向に最大の内角を持つエッジを選択します。
2つのベクトルを計算します。現在のEdgeのvector1と、次の未訪問の各Edgeのvector2です(図を参照)。
私が計算するベクトルの場合:
その結果、最大の角度を持つEdge(および対応する次の頂点)を取得します。
渡された各頂点を結果リストに追加します。結果リストはユニオンポリゴンです。
これはやりがいがありますが、よく理解されているトピックであり、「ポリゴンに対する正規化されたブール演算」という名前で呼ばれることがよくあります。 このMathOverflowの回答 を見ると、下の図が含まれています( Alan Murtaのクリッピングライブラリ から)、OPのピンクのユニオン結合:
どのポイントが内側にあるかを決定する が必要です。これらのポイントを削除した後、「外部」ポイントのセットをもう一方に挿入できます。挿入ポイント(たとえば、右側の図に矢印がある場所)は、入力セットからポイントを削除する必要があった場所です。
良い質問!これを試したことはありませんが、今すぐ試してみます。
最初に、これら2つの形状が重複する場所を知る必要があります。これを行うには、ポリゴンAのすべてのエッジを見て、それが交差する場所とポリゴンBのエッジを確認します。この例では、2つの交差点が必要です。
次に、ユニオン形状を作成します。 AとBのすべての頂点、および交差点を取得し、最終形状に含まれる頂点を除外できます。これらの点を見つけるには、Bの内側にあるAの頂点と、Aの内側にあるBの頂点を見つけることができるように見えます。
gpc を試してください。
国をグループ化するとき、重複しないことを願っています-共有された頂点を探すかなり素朴なアルゴリズムを取ることができます-単純なビューは、1つのポリゴンのポイントを反復処理し、他のポリゴンのいずれかにあるかどうかを確認します、同じ次または前のポイントを共有して、一致するかどうかを確認します。次に、共有頂点を削除してユニオンを作成します
今日、この同じ問題を解決する必要があり、このlibで解決策を見つけました: http://www.cs.man.ac.uk/~toby/alan/software/ 。
Java、Obj-C、C#、Lua、pythonなど)を含む多くの言語実装 ここのリスト があります。
私は同じ問題に直面しており、次の方法を使用して問題を解決しました
Angus JohnsonのClipperライブラリ(ver。6.4.2)のC++翻訳用のCythonラッパー 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)
これは非常に古い質問ですが、 nion _ Boostの関数が機能しました。
以下のスニペットをご覧ください。
#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;
}