穴は、shapelyのポリラベルアルゴリズムの実装では正しく考慮されていません。
from shapely.geometry import Polygon
from shapely.algorithms.polylabel import polylabel
poly1=Polygon(shell=[(0,0),(10,0),(10,10),(0,10),(0,0)][::-1], holes=[[(2,2),(6,2),(6,6),(2,6),(2,2)]])
import geopandas
gdf2 = geopandas.GeoDataFrame(geometry=[poly1])
gdf2.plot()
label_location = polylabel(poly1, tolerance=0.05)
print(label_location.x)
print(label_location.y)
このスクリプトの出力は次のとおりです。
6.25
3.75
しかし、正しい位置は7.65625、7.65625に近いものです。 これは、このポリゴンのプロットを見ると確認できます
ポリゴンの定義で何か間違ったことをしているのかもしれませんが、このポリゴンをインスタンス化するさまざまな方法を試しましたが、常に同じ結果が得られます。
Linux
形の良いバージョン1.6および1.7a3でテスト済み
https://github.com/mapbox/polylabel自体が示唆する座標が異なることを確認してください。
TypeScriptの元のアルゴリズム:
import polylabel from "polylabel";
let exterior = [[0,0],[10,0],[10,10],[0,10],[0,0]];
let hole = [[2,2],[6,2],[6,6],[2,6],[2,2]];
let polygon = [exterior, hole]
console.log(polylabel(polygon, 0.01));
PS> .\node_modules\.bin\tsc test.ts
PS> node .\test.js
[ 7.65625, 7.65625 ]
形の良い:
>>> from shapely.ops import polylabel
>>> from shapely.geometry import Polygon
>>> exterior = [[0,0],[10,0],[10,10],[0,10],[0,0]]
>>> hole = [[2,2],[6,2],[6,6],[2,6],[2,2]]
>>> p = Polygon(exterior, [hole])
>>> polylabel(p, 0.01).coords[:]
[(6.25, 3.75)]
あなたは正しい@benediktbrandtです。 Shapely実装は、ポリゴンの外部までの距離のみを考慮するため、穴を正しく処理しません。 これはバグであり、元のアルゴリズムの動作と一致するように修正する必要があると思います。
ポリゴンの外部からラインストリングへの変換は、作成されたすべてのセルに対して行われるため、ここでも少し非効率的です。
最も参考になるコメント
あなたは正しい@benediktbrandtです。 Shapely実装は、ポリゴンの外部までの距離のみを考慮するため、穴を正しく処理しません。 これはバグであり、元のアルゴリズムの動作と一致するように修正する必要があると思います。
https://github.com/Toblerity/Shapely/blob/cfa66d418fe3afe2fcb48438fcc9156142abaeb8/shapely/algorithms/polylabel.py#L44 -L53
ポリゴンの外部からラインストリングへの変換は、作成されたすべてのセルに対して行われるため、ここでも少し非効率的です。