Skip to content

Commit 68cc745

Browse files
RaczeQkylebarron
andauthored
Feat: reverse the layer order for automatically split geometry (#516)
## What I am changing <!-- What were the high-level goals of the change? --> - Layer order for objects with mixed geometry types ## How I did it Changed list appending order for `split_mixed_gdf` and `parse_wkb_table` function from [`points`, `linestrings`, `polygons`] to [`polygons`, `linestrings`, `points`] ## How you can test it <!-- How might a reviewer test your changes to verify that they work as expected? --> - Points and paths should be now plotted on top of polygon for better visibility. Old: ![Untitled](https://github.com/developmentseed/lonboard/assets/17250607/f0d4a4f5-d69d-4e27-bbc7-3d159d1d2e6b) New: ![image](https://github.com/developmentseed/lonboard/assets/17250607/8e154ff7-996a-4556-9406-daa355d4184a) ## Related Issues #513 --------- Co-authored-by: Kyle Barron <[email protected]>
1 parent 68cec33 commit 68cc745

File tree

3 files changed

+40
-41
lines changed

3 files changed

+40
-41
lines changed

lonboard/_geoarrow/parse_wkb.py

+23-30
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ def parse_wkb_table(table: pa.Table) -> List[pa.Table]:
4141
return [table]
4242

4343
# Handle WKB input
44-
parsed_tables = []
4544
crs_str = get_field_crs(field)
4645
shapely_arr = shapely.from_wkb(column)
4746

@@ -67,35 +66,29 @@ def parse_wkb_table(table: pa.Table) -> List[pa.Table]:
6766
(type_ids == GeometryType.POLYGON) | (type_ids == GeometryType.MULTIPOLYGON)
6867
)[0]
6968

70-
if len(point_indices) > 0:
71-
point_field, point_arr = construct_geometry_array(
72-
shapely_arr[point_indices],
73-
crs_str=crs_str,
74-
)
75-
point_table = table.take(point_indices).set_column(
76-
field_idx, point_field, point_arr
77-
)
78-
parsed_tables.append(point_table)
79-
80-
if len(linestring_indices) > 0:
81-
linestring_field, linestring_arr = construct_geometry_array(
82-
shapely_arr[linestring_indices],
83-
crs_str=crs_str,
84-
)
85-
linestring_table = table.take(linestring_indices).set_column(
86-
field_idx, linestring_field, linestring_arr
87-
)
88-
parsed_tables.append(linestring_table)
89-
90-
if len(polygon_indices) > 0:
91-
polygon_field, polygon_arr = construct_geometry_array(
92-
shapely_arr[polygon_indices],
93-
crs_str=crs_str,
94-
)
95-
polygon_table = table.take(polygon_indices).set_column(
96-
field_idx, polygon_field, polygon_arr
97-
)
98-
parsed_tables.append(polygon_table)
69+
# Here we intentionally check geometries in a specific order.
70+
# Starting from polygons, then linestrings, then points,
71+
# so that the order of generated layers is polygon, then path then scatterplot.
72+
# This ensures that points are rendered on top and polygons on the bottom.
73+
parsed_tables = []
74+
for single_type_geometry_indices in (
75+
polygon_indices,
76+
linestring_indices,
77+
point_indices,
78+
):
79+
if len(single_type_geometry_indices) > 0:
80+
single_type_geometry_field, single_type_geometry_arr = (
81+
construct_geometry_array(
82+
shapely_arr[single_type_geometry_indices],
83+
crs_str=crs_str,
84+
)
85+
)
86+
single_type_geometry_table = table.take(
87+
single_type_geometry_indices
88+
).set_column(
89+
field_idx, single_type_geometry_field, single_type_geometry_arr
90+
)
91+
parsed_tables.append(single_type_geometry_table)
9992

10093
return parsed_tables
10194

lonboard/_utils.py

+13-7
Original file line numberDiff line numberDiff line change
@@ -140,24 +140,30 @@ def split_mixed_gdf(gdf: gpd.GeoDataFrame) -> List[gpd.GeoDataFrame]:
140140
if unique_type_ids == {GeometryType.POLYGON, GeometryType.MULTIPOLYGON}:
141141
return [gdf]
142142

143-
gdfs = []
144143
point_indices = np.where(
145144
(type_ids == GeometryType.POINT) | (type_ids == GeometryType.MULTIPOINT)
146145
)[0]
147-
if len(point_indices) > 0:
148-
gdfs.append(gdf.iloc[point_indices])
149146

150147
linestring_indices = np.where(
151148
(type_ids == GeometryType.LINESTRING)
152149
| (type_ids == GeometryType.MULTILINESTRING)
153150
)[0]
154-
if len(linestring_indices) > 0:
155-
gdfs.append(gdf.iloc[linestring_indices])
156151

157152
polygon_indices = np.where(
158153
(type_ids == GeometryType.POLYGON) | (type_ids == GeometryType.MULTIPOLYGON)
159154
)[0]
160-
if len(polygon_indices) > 0:
161-
gdfs.append(gdf.iloc[polygon_indices])
155+
156+
# Here we intentionally check geometries in a specific order.
157+
# Starting from polygons, then linestrings, then points,
158+
# so that the order of generated layers is polygon, then path then scatterplot.
159+
# This ensures that points are rendered on top and polygons on the bottom.
160+
gdfs = []
161+
for single_type_geometry_indices in (
162+
polygon_indices,
163+
linestring_indices,
164+
point_indices,
165+
):
166+
if len(single_type_geometry_indices) > 0:
167+
gdfs.append(gdf.iloc[single_type_geometry_indices])
162168

163169
return gdfs

tests/test_viz.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ def test_viz_wkb_pyarrow():
4747
def test_viz_wkb_mixed_pyarrow():
4848
table = pq.read_table(fixtures_dir / "monaco_nofilter_noclip_compact.parquet")
4949
map_ = viz(table)
50-
assert isinstance(map_.layers[0], ScatterplotLayer)
50+
assert isinstance(map_.layers[0], PolygonLayer)
5151
assert isinstance(map_.layers[1], PathLayer)
52-
assert isinstance(map_.layers[2], PolygonLayer)
52+
assert isinstance(map_.layers[2], ScatterplotLayer)
5353

5454

5555
def test_viz_reproject():
@@ -84,9 +84,9 @@ def test_viz_geo_interface_mixed_feature_collection():
8484
geo_interface_obj = GeoInterfaceHolder(gdf)
8585
map_ = viz(geo_interface_obj)
8686

87-
assert isinstance(map_.layers[0], ScatterplotLayer)
87+
assert isinstance(map_.layers[0], PolygonLayer)
8888
assert isinstance(map_.layers[1], PathLayer)
89-
assert isinstance(map_.layers[2], PolygonLayer)
89+
assert isinstance(map_.layers[2], ScatterplotLayer)
9090

9191

9292
def test_viz_geopandas_geodataframe():

0 commit comments

Comments
 (0)