IIUC, you want the induced / chordless_cycles
. If so, here is a primal approach with networkx:
points = MultiPoint(list(batched(chain.from_iterable(coordinates), 2)))
lines = [
line
for coo in coordinates
for pop in pairwise(batched(coo, 2))
for gc in [split(LineString(pop), points)]
for line in gc.geoms
]
G = gdf_to_nx(
gpd.GeoDataFrame(geometry=lines), multigraph=False, approach="primal"
)
cycles = [
[
tuple(chain.from_iterable(pair))
for pair in pairwise(cyc)
] for cyc in nx.chordless_cycles(G)
for cyc in [cyc + [cyc[0]]]
]
输出(cycles
,clockwise):
[
[ # top/green cycle
(70.0, 50.0, 80.0, 50.0),
(80.0, 50.0, 77.5, 45.0),
(77.5, 45.0, 72.5, 45.0),
(72.5, 45.0, 70.0, 50.0),
],
[ # bottom/red cycle
(72.5, 45.0, 77.5, 45.0),
(77.5, 45.0, 75.0, 40.0),
(75.0, 40.0, 72.5, 45.0),
],
]
使用的输入(coordinates
):
from itertools import chain, batched, pairwise
import geopandas as gpd
from momepy import gdf_to_nx
import networkx as nx
from shapely import LineString, MultiPoint
from shapely.ops import split
coordinates = [
(50.0, 50.0, 100.0, 50.0),
(70.0, 50.0, 75.0, 40.0, 80.0, 50.0),
(72.5, 45.0, 77.5, 45.0)
]
Full code
Old answer