DHI.Spatial.GeoAPI — Internal Developer Guide¶
This tiny bridge converts between our DHI.Spatial geometry types and NetTopologySuite (NTS) geometries using well-known binary (WKB) as the interchange. It lets you run robust NTS operations (area, intersect, buffer, etc.) while keeping DHI’s lightweight model on the edges.
What it exposes¶
Namespace: DHI.Spatial.GeoAPI
public static class Geometry
{
public static IGeometry FromWkb(byte[] wkb);
public static NetTopologySuite.Geometries.Geometry ToGeoAPIGeometry(this IGeometry geometry);
public static byte[] ToWkb(this IGeometry geometry);
}
Internally it reuses:
GeometryFactory(static)WKBWriter(static)- A fresh
WKBReaderper call
Supported geometry types¶
| Type | FromWkb → DHI.Spatial | DHI.Spatial → ToWkb | Notes |
|---|---|---|---|
Point |
✓ | ✓ | Z read from WKB into Position if present; Z is not written back (2D WKB output). |
LineString |
✓ | ✓ | Z ignored; XY only. |
Polygon (outer + holes) |
✓ | ✓ | Rings must be closed. ToWkb will auto-close any unclosed ring. |
MultiPoint |
✓ | ✓ | Z ignored; XY only. |
MultiLineString |
✓ | ✓ | Z ignored; XY only. |
MultiPolygon |
✓ | ✓ | Holes must be closed; unclosed holes are skipped on read. |
GeometryCollection |
✖ | ✖ | Not handled by this bridge. Use NTS directly if needed. |
ToGeoAPIGeometry(this IGeometry) is implemented by: geometry.ToWkb() → WKBReader.Read(…). That means it inherits the same dimensional rules as ToWkb.
Coordinate & CRS expectations¶
- Coordinates are treated as plain XY (optionally Z for Point on read only).
- No SRID/CRS is carried through WKB here. If you need SRID, set it later on the returned NTS geometry, or manage CRS metadata on the DHI side (
IGeometry.CRS).
Ring & hole handling¶
-
Write (ToWkb) For
PolygonandMultiPolygon, each linear ring is auto-closed (first != last→ append first). -
Read (FromWkb)
Polygon: outer shell + all holes imported.MultiPolygon: each polygon’s holes are imported only if closed. Unclosed rings are ignored:- .NET 4.7.2 check:
StartPoint.Equals(EndPoint) - Newer targets:
StartPoint.EqualsExact(EndPoint)
- .NET 4.7.2 check:
Z-dimension rules¶
- Read:
Pointpreserves Z intoPosition; all other types ignore Z. - Write: always emits 2D WKB (XY only). Even if
Position.Zexists, it’s dropped.
If you need full 3D round-trips, extend the writer/reader to use NTS WKBWriter(3) and populate Z-coordinates when building NTS objects.
Usage examples¶
1) Read WKB (from DB) → DHI geometry¶
byte[] wkb = /* read from DB */;
IGeometry g = DHI.Spatial.GeoAPI.Geometry.FromWkb(wkb);
// Use within our stack
if (g is Polygon poly)
{
// poly.Coordinates: List<List<Position>>
}
2) DHI geometry → WKB (store/send)¶
var poly = new Polygon();
poly.Coordinates.Add(new List<Position> {
new(0,0), new(10,0), new(10,5), new(0,5), new(0,0)
});
byte[] wkb = poly.ToWkb();
// Save to DB, send over wire, etc.
3) Run NTS ops by round-tripping via WKB¶
IGeometry dhi = Geometry.FromWKT("POLYGON ((0 0, 5 0, 5 5, 0 5, 0 0))");
var nts = dhi.ToGeoAPIGeometry();
var buffered = nts.Buffer(1.0); // NTS operation
var dhiBuffered = DHI.Spatial.GeoAPI.Geometry.FromWkb(new WKBWriter().Write(buffered));
// now back in DHI.Spatial
Error behavior¶
- Unsupported geometry →
NotSupportedException("Geometry type '…' is not supported.") - Invalid WKB → exceptions from
WKBReader.Read. - MultiPolygon: unclosed hole rings are silently skipped on read (by design).
Performance notes¶
WKBWriterandGeometryFactoryare static singletons (stateless in our usage).WKBReaderis new per call (cheap).- Zero allocations on our geometry side beyond list building. If you do heavy multi-threaded work and want to avoid shared singletons, you can locally instantiate a
WKBWriterper hot path.
When to use this bridge¶
- You want to keep DHI.Spatial at API boundaries but leverage NTS for computational geometry.
- Persisting geometries as WKB in a database.
- Interop with systems that already speak WKB.
If you need GeometryCollection, 3D, SRID-aware pipelines, or advanced predicates, call NTS directly and only convert at the very edge where DHI types are required.