From 798d0a3d66d23fab2c71b88426fb04a50e393317 Mon Sep 17 00:00:00 2001 From: Martin Fleischmann Date: Mon, 5 Aug 2024 13:27:52 +0200 Subject: [PATCH] keep only a single dangle in a loop --- core/algorithms/simplify.py | 78 +++++++++++++++---------------------- 1 file changed, 32 insertions(+), 46 deletions(-) diff --git a/core/algorithms/simplify.py b/core/algorithms/simplify.py index ea968b8..d7f239b 100644 --- a/core/algorithms/simplify.py +++ b/core/algorithms/simplify.py @@ -346,57 +346,43 @@ def loop( ) split_points.extend(splitters) - possible_dangle = possible_dangle[shapely.disjoint(possible_dangle, dropped)] - n_comps = graph.Graph.build_contiguity( - gpd.GeoSeries(possible_dangle), rook=False - ).n_components - if n_comps == 1: - logger.debug("LOOP components 1") - dangle_coins = momepy.COINS( - gpd.GeoSeries(shapely.line_merge(possible_dangle)).explode(), - flow_mode=True, - ).stroke_gdf() - candidate = dangle_coins.loc[dangle_coins.length.idxmax()].geometry - if candidate.intersects(snap_to.union_all().buffer(eps)) and ( - candidate.length > min_dangle_length - ): - logger.debug("LOOP intersects and length > min_dangle_length") - if not primes.empty: - points = [ - shapely.get_point(candidate, 0), - shapely.get_point(candidate, -1), - ] - distances = shapely.distance(points, highest_hierarchy.union_all()) - if distances.max() > min_dangle_length: - logger.debug("LOOP prime check passed") - to_add.append(candidate) - else: - to_add.append(candidate) - elif n_comps > 1: + possible_dangle = gpd.GeoDataFrame( + geometry=possible_dangle[shapely.disjoint(possible_dangle, dropped)] + ) + comps = graph.Graph.build_contiguity( + possible_dangle.difference(snap_to.union_all().buffer(eps)), rook=False + ) + if comps.n_components > 1: # NOTE: it is unclear to me what exactly should happen here. I believe that # there will be cases when we may want to keep multiple dangles. Now keeping # only one. logger.debug("LOOP components many") - dangle_coins = momepy.COINS( - gpd.GeoSeries(shapely.line_merge(possible_dangle)).explode(), - flow_mode=True, - ).stroke_gdf() - candidate = dangle_coins.loc[dangle_coins.length.idxmax()].geometry - if candidate.intersects(snap_to.union_all().buffer(eps)) and ( - candidate.length > min_dangle_length - ): - logger.debug("LOOP intersects and length > min_dangle_length") - if not primes.empty: - points = [ - shapely.get_point(candidate, 0), - shapely.get_point(candidate, -1), - ] - distances = shapely.distance(points, highest_hierarchy.union_all()) - if distances.max() > min_dangle_length: - logger.debug("LOOP prime check passed") - to_add.append(candidate) - else: + comp_labels = comps.component_labels.values + longest_component = possible_dangle.dissolve( + comps.component_labels + ).length.idxmax() + possible_dangle = possible_dangle[comp_labels == longest_component] + + dangle_coins = momepy.COINS( + possible_dangle, + flow_mode=True, + ).stroke_gdf() + candidate = dangle_coins.loc[dangle_coins.length.idxmax()].geometry + if candidate.intersects(snap_to.union_all().buffer(eps)) and ( + candidate.length > min_dangle_length + ): + logger.debug("LOOP intersects and length > min_dangle_length") + if not primes.empty: + points = [ + shapely.get_point(candidate, 0), + shapely.get_point(candidate, -1), + ] + distances = shapely.distance(points, highest_hierarchy.union_all()) + if distances.max() > min_dangle_length: + logger.debug("LOOP prime check passed") to_add.append(candidate) + else: + to_add.append(candidate) return to_add