diff --git a/momepy/preprocessing.py b/momepy/preprocessing.py index 196331a4..839cdca6 100644 --- a/momepy/preprocessing.py +++ b/momepy/preprocessing.py @@ -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() diff --git a/momepy/tests/test_preprocess.py b/momepy/tests/test_preprocess.py index 98f8ee44..01803374 100644 --- a/momepy/tests/test_preprocess.py +++ b/momepy/tests/test_preprocess.py @@ -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)])