Skip to content

Add opt-in linearization of curve types when reading - #35

Open
grootstebozewolf wants to merge 1 commit into
NetTopologySuite:developfrom
grootstebozewolf:feature/curve-linearization
Open

Add opt-in linearization of curve types when reading#35
grootstebozewolf wants to merge 1 commit into
NetTopologySuite:developfrom
grootstebozewolf:feature/curve-linearization

Conversation

@grootstebozewolf

@grootstebozewolf grootstebozewolf commented Jul 20, 2026

Copy link
Copy Markdown

Follow-up to #18, as offered in this comment (thanks @bjornharrtell for the go-ahead).

Reading CIRCULARSTRING, COMPOUNDCURVE or CURVEPOLYGON values currently throws a ParseException, which (as discussed in #18) can't even be intercepted by an EF Core value converter. Since NTS itself has no curve geometry types yet (NetTopologySuite/NetTopologySuite#854 is still in progress), this adds a self-contained, opt-in client-side approximation instead — the equivalent of calling STCurveToLine in SQL, but without having to change your queries:

var reader = new SqlServerBytesReader { LinearizeCurves = true };

What it does

  • Decodes the version-2 serialization's curve structures (FigureAttribute.Arc / FigureAttribute.Curve figures and the segment-type array) and approximates them using LineString and Polygon values. Works for curves nested inside GEOMETRYCOLLECTION and for CURVEPOLYGON rings that mix line, arc and compound figures, for both geometry and geography data.
  • A new MaxLinearizationAngle property controls accuracy (maximum angle subtended by one line segment). The default, π/32, matches the granularity SQL Server's STCurveToLine uses, so default output is point-wise identical to what STCurveToLine returns (verified in tests).
  • Each half of an arc (start→mid, mid→end) is subdivided separately — again matching STCurveToLine — so the original points of an arc are always preserved in the output.
  • Z and M values of inserted points are interpolated linearly (STCurveToLine just drops them; SQL Server requires constant Z along an arc anyway).
  • Degenerate (collinear) arcs fall back to straight line segments; malformed curve data throws a ParseException.
  • The default behavior is unchanged: without LinearizeCurves, the existing ParseException is thrown (its message now mentions the new option).

What it doesn't do

  • Writing curve geometries is not supported (there is no NTS type to write them from). Once NTS gains native curve types, LinearizeCurves can be complemented by returning real curve geometries.
  • Geography arcs are approximated in longitude/latitude space rather than on the ellipsoid; this is documented on the property and in the README.

Testing

All serialized test values were generated by SQL Server 2025 via CAST(geometry::Parse(N'...') AS varbinary(max)), including the exact CURVEPOLYGON circle from #18. Expected values are point-wise comparisons against SQL Server's actual STCurveToLine output, plus geometric invariants (all approximated points lie on the arc's circle, rings close exactly, polygon areas match the inscribed-polygon formula). 113 tests pass (95 existing + 18 new).

Happy to adjust naming, defaults or scope however you prefer.

🤖 Generated with Claude Code

Reading CircularString, CompoundCurve and CurvePolygon values threw a
ParseException. Add SqlServerBytesReader.LinearizeCurves to approximate
them using LineString and Polygon values instead, and
MaxLinearizationAngle to control the accuracy of the approximation. The
default (pi/32) matches the granularity of SQL Server's STCurveToLine
method. The original points of an arc are always preserved, and Z and M
values of inserted points are interpolated linearly.

Serialized test values were produced by SQL Server 2025, including the
CurvePolygon circle from NetTopologySuite#18, and the expected values are point-wise
comparisons against SQL Server's STCurveToLine output.

Part of NetTopologySuite#18

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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.

1 participant