Skip to content

Commit

Permalink
ENH: do not fail with 3d nodes - preprocess.remove_false_nodes() (#661
Browse files Browse the repository at this point in the history
)

* graceful failure with 3d nodes - remove_false_nodes()

* martin comments

* Update momepy/preprocessing.py

Co-authored-by: Martin Fleischmann <[email protected]>

* re-leint

---------

Co-authored-by: Martin Fleischmann <[email protected]>
  • Loading branch information
jGaboardi and martinfleis authored Oct 23, 2024
1 parent d831976 commit f1965cc
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 5 deletions.
10 changes: 6 additions & 4 deletions momepy/preprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,8 @@ def preprocess(
def remove_false_nodes(gdf):
"""
Clean topology of existing LineString geometry by removal of nodes of degree 2.
Returns the original gdf if there's no node of degree 2.
Returns the original gdf if there's no node of degree 2. Some geometries may
be forced to 2D where a Z coordinate is present.
Parameters
----------
Expand All @@ -178,7 +178,7 @@ def remove_false_nodes(gdf):
-------
gdf : GeoDataFrame, GeoSeries
See also
See Also
--------
momepy.extend_lines
momepy.close_gaps
Expand Down Expand Up @@ -247,14 +247,16 @@ def remove_false_nodes(gdf):
),
lines=False,
)

loops = combined[combined.is_ring]

node_ix, loop_ix = loops.sindex.query(nodes.geometry, predicate="intersects")
for ix in np.unique(loop_ix):
loop_geom = loops.geometry.iloc[ix]
target_nodes = nodes.geometry.iloc[node_ix[loop_ix == ix]]
if len(target_nodes) == 2:
node_coords = shapely.get_coordinates(target_nodes)
coords = np.array(loop_geom.coords)
coords = shapely.get_coordinates(loop_geom)
new_start = (
node_coords[0]
if (node_coords[0] != coords[0]).all()
Expand Down
12 changes: 11 additions & 1 deletion momepy/tests/test_preprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import numpy as np
import pytest
from geopandas.testing import assert_geodataframe_equal
from shapely import affinity
from shapely import affinity, force_3d
from shapely.geometry import LineString, MultiPoint, Point, Polygon
from shapely.ops import polygonize

Expand Down Expand Up @@ -67,6 +67,16 @@ def test_remove_false_nodes(self):
df = self.df_streets.drop([4, 7, 17, 22])
assert_geodataframe_equal(df, mm.remove_false_nodes(df))

# check 3d coords in loop
line_1 = LineString((Point(1, 1), Point(2, 2)))
line_2 = LineString((Point(2, 2), Point(3, 3)))
line_3 = force_3d(LineString((Point(2, 2), Point(1, 2))))
line_4 = LineString((Point(1, 2), Point(1, 3)))
line_5 = LineString((Point(1, 3), Point(2, 2)))
with_3d = np.array([line_1, line_2, line_3, line_4, line_5])
no_3d = mm.remove_false_nodes(with_3d)
assert len(no_3d) == 3

def test_CheckTessellationInput(self):
df = self.df_buildings
df.loc[144, "geometry"] = Polygon([(0, 0), (0, 1), (1, 0)])
Expand Down

0 comments on commit f1965cc

Please sign in to comment.