Skip to content

Linearize curve geometries before exporting to WKT - #110

Merged
iandees merged 1 commit into
masterfrom
fix-issue-62-multisurface
Aug 22, 2026
Merged

Linearize curve geometries before exporting to WKT#110
iandees merged 1 commit into
masterfrom
fix-issue-62-multisurface

Conversation

@iandees

@iandees iandees commented Aug 22, 2026

Copy link
Copy Markdown
Member

Problem

Fixes #62.

Parcel/building sources loaded from Esri file geodatabases (GDB) can contain curve geometry types such as MULTISURFACE, CURVEPOLYGON, and COMPOUNDCURVE when the source data has curved boundary segments (arcs, circular street features, etc). This is common in some county-sourced building/parcel GDBs.

ogr_source_to_csv() in openaddr/conform.py reads each feature's geometry with OGR and exports it directly to WKT via geom.ExportToWkt(). That WKT is later parsed with shapely's wkt_loads(). Shapely/GEOS does not understand GDAL's curve-geometry WKT types, so any GDB source containing curved geometry causes a downstream parse failure (reported as Unknown type: MULTISURFACE in the issue).

Fix

In ogr_source_to_csv, after reprojecting each feature's geometry, check geom.HasCurveGeometry() and if true, call geom.GetLinearGeometry() (available since GDAL 2.0) before further processing. This converts curve types to their linear equivalents (e.g. MULTISURFACE -> MULTIPOLYGON, CURVEPOLYGON -> POLYGON) that shapely can parse, while leaving already-linear geometries (the common case for shapefile/GeoJSON/most GDB data) untouched.

This function is shared by shapefile, GDB, GML/XML, and GeoKPG sources (format_string in ("shapefile", "xml", "gdb", "gpkg")), so the fix is applied at the one call site that's actually reachable from GDB sources rather than scattered across every ExportToWkt() call in the file. The other ExportToWkt() call sites (geojson_source_to_csv, row_extract_and_reproject) operate on GeoJSON/CSV-sourced geometry, which cannot contain OGR curve types, so they're left alone.

Verification

I don't have a real failing GDB file, so I reproduced this synthetically:

  1. Constructed a MULTISURFACE (CURVEPOLYGON (CIRCULARSTRING (...))) geometry directly with ogr.CreateGeometryFromWkt(...) and confirmed wkt_loads(geom.ExportToWkt()) raises NotImplementedError: Nonlinear geometry types are not currently supported on unpatched code — same failure class as the issue (shapely/GEOS choking on curve WKT).
  2. Built a synthetic GeoPackage (.gpkg, one of the formats sharing this code path with .gdb) containing a single feature with that same curve geometry, and ran it through the actual ogr_source_to_csv() function end-to-end.
    • On unpatched code, the function writes the raw curve WKT (MULTISURFACE (CURVEPOLYGON (...))) straight into the output CSV, which would later fail to parse downstream via wkt_loads.
    • With the fix, the output WKT is a MULTIPOLYGON, parses cleanly with wkt_loads, and its bounds/area are sane (not degenerate) relative to the original curve geometry.
  3. Added a regression test, test_ogr_source_to_csv_multisurface in openaddr/tests/conform.py, that builds this synthetic GPKG fixture, runs it through ogr_source_to_csv, and asserts the output WKT contains no CURVE/SURFACE type names, parses as a MultiPolygon via shapely, and has sane bounds/area.
  4. Ran the full openaddr.tests.conform suite in the repo's batch-machine-test:latest docker image: all 66 tests pass, including the new one.

Caveat for reviewers: this is verified against a synthetic curve geometry (constructed directly with OGR, and via a synthetic GeoPackage fixture standing in for a GDB), not a real downloaded parcel/building GDB from one of the affected sources. The reasoning for why GeoPackage is a faithful stand-in is that both formats share the exact same ogr_source_to_csv() code path and both can carry OGR curve geometry types end-to-end through the OGR API. If possible, it'd be worth testing against one of the real GDB sources referenced in the issue (e.g. Trempealeau County, WI) before/after this change.

@iandees
iandees merged commit b6b45bc into master Aug 22, 2026
1 check passed
@iandees
iandees deleted the fix-issue-62-multisurface branch August 22, 2026 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parcel/building gdb sources error out

1 participant