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 <martin@martinfleischmann.net>

* re-leint

---------

Co-authored-by: Martin Fleischmann <martin@martinfleischmann.net>
jGaboardi and martinfleis authored Oct 23, 2024
1 parent d831976 commit f1965cc
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
@@ -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
----------
@@ -178,7 +178,7 @@ def remove_false_nodes(gdf):
-------
gdf : GeoDataFrame, GeoSeries
See also
See Also
--------
momepy.extend_lines
momepy.close_gaps
@@ -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()
12 changes: 11 additions & 1 deletion momepy/tests/test_preprocess.py
Original file line number Diff line number Diff line change
@@ -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

@@ -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)])

0 comments on commit f1965cc

Please sign in to comment.