My coworker noticed the the ESRI Line WKB
is malformed contains unspecified trailing data, and since he's not active on GIS.SE, I posted his remarks as an answer. I'll wait a few days for critiques before accepting it in case someone has a more definitive reaction.
In the meantime, I can recreate the exception between ESRI Line Geometry WKB and SqlServer.Types by making a brand new feature class, giving it a single line geometry, and bingo---it's repeatable. Every time. But I Googled this all day yesterday and didn't find any confirmation of this. I must be a bad Googler!
When I try converting an esriPolylineGeometry to IWkb, then go through the motions of exporting to wkbBytes and consuming it in
SqlServer.Types.SqlGeometry.STGeomFromWKB() the conversion always fails with the error "well-known binary (WKB) input is not valid". However, if I use the same approach to get wkbBytes, it works fine when I send it through SharpMap converters. I've done everything I can imagine to rule-out poor geometries, and I'm thinking surely someone has run into this before.
On the ESRI-side, I've tried using ITopologyOperator to perform
.Buffer(0), and neither makes a difference. I've also tried adding
STGeomFromWKB() to no use. And there is also no difference from either
IWkb.ExportToWkb() or the alternative
So my question is: Is the WKB really invalid? If so, then why is it converting properly in SharpMap?
The WKB coming out of ESRI looks like this:
Below, the first code block shows the failing approach when I attempt to consume using SqlGeometry's static method STGeomFromWKB(). The second block shows the SharpMap approach, which works when consuming the same wkbBytes data.
This approach using SqlServer.Types fails..
// At this point, feature.Shape is esriPolylineGeometry IWkb wkb = feature.Shape as IWkb; int byteCount = wkb.WkbSize; byte wkbBytes = new byte[byteCount]; wkb.ExportToWkb(ref byteCount, out wkbBytes); // FYI: This alternate approach to get the byte is no different.. //IGeometry geom = feature.Shape; //IGeometryFactory3 geomFactory = new GeometryEnvironment() as IGeometryFactory3; //byte wkbBytes = geomFactory3.CreateWkbVariantFromGeometry(wkb) as byte; int srid = feature.Shape.SpatialReference.FactoryCode; // It fails here noting... // "24115: The well-known binary (WKB) input is not valid." SqlGeometry sqlGeometry = SqlGeometry.STGeomFromWKB(new SqlBytes(wkbBytes), srid); string wkt = sqlGeometry.ToString(); MessageBox.Show(wkt);
But this approach using SharpMap converters works.. ?!?!
IWkb geomWKB = feature.Shape as IWkb; int wkbSize = wkb.WkbSize; byte geomWkbBytes = new byte[wkbSize]; wkb.ExportToWkb(ref wkbSize, out geomWkbBytes); SharpMap.Geometries.IGeometry sharpGeom = SharpMap.Converters.WellKnownBinary.GeometryFromWKB.Parse(geomWkbBytes); string sharpWKT = SharpMap.Converters.WellKnownText.GeometryToWKT.Write(sharpGeom);
Both approaches accept Polygon geometries, but I'm hoping someone knows how to get the SqlServer.Types approach to work on Line geometries, as we have other projects already using that library. I won't hesitate to use SharpMap converters if that is the answer, but it bothers me that an unknown condition is causing SqlServer.Types to fail in the context of Line geometries. :/