-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SqlGeometry validation flag behaviour should be documented #12
Comments
Can you please provide an example of a geometry that NTS claims is valid, but which SQL Server would claim is invalid? |
Sure, here is one example: A bit easier to read:
NTS considers this valid, but SQL Server does not:
If needed, I can also find some test data for the other case, where NTS claims it is invalid but SQL Server does not. I would need some more time for this though, I deal with a lot of test data and I don't remember exactly which test cases this occurred in. |
For reference, here's a related issue that I unfortunately did not manage to get back to: NetTopologySuite/NetTopologySuite#267 The person who last commented also observed this behaviour of the 'V' flag. |
OK, I see -- based on some testing, MSSQL seems to think that a line string is invalid if there exists a segment (of nonzero length) that appears between more than one pair of consecutive points. I'm not sure if that's an OGC rule or not, which matters here because:
Even if it is an OGC thing that NTS + JTS are missing, it still might make sense to add a workaround here in the meantime. |
Sounds good! I wasn't sure if performing extra validation in this library would be OK, because I assume that speed is the focus of this library. |
Not at the expense of correctness. Some examples that we can use as test cases: -- intersects itself in 3 places, multiple times, with one segment intersecting the line multiple times
-- still valid, because the intersections are all at individual points
SELECT geometry::STGeomFromText('LINESTRING (0 0, 0 2, 1 1, -1 1, 2 2)', 0).IsValidDetailed()
-- topologically equal to the previous one, but with some points repeated
-- still valid, because it still describes each segment only once
SELECT geometry::STGeomFromText('LINESTRING (0 0, 0 1, 1 1, 0 2, 0 1, -1 1, 2 2)', 0).IsValidDetailed()
-- essentially the same line as the others, but it crosses over one of its segments
-- not valid, because the segment between (0, 0) and (0, 1) appears multiple times
SELECT geometry::STGeomFromText('LINESTRING (0 1, 1 1, 0 2, 0 0, 0 1, -1 1, 2 2)', 0).IsValidDetailed() |
This can also be the other way round, that NTS will flag the geometry as not valid but if imported into MSSQL through other means and validated inside MSSQL it doesn't see it is invalid. The case where I found this is for a polygon with self intersecting (touching) shell at a point (creating a "hole") which is an OGC invalid case detected by NTS. I find it hard to determine if this is by design or a bug in MSSQL as they carefully seem to avoid to be clear about what they mean with "well-formed" at https://docs.microsoft.com/en-us/sql/t-sql/spatial-geometry/stisvalid-geometry-data-type?view=sql-server-ver15. |
How about creating a |
@FObermaier are you sure? To me the definition of validity as per MSSQL is undefined, the case I found was just one example. |
And it lists |
Seriously, my point is that we cannot assume JTS/NTS validity is the same as MSSQL validity. |
That is why I suggested to create and use |
@FObermaier but you propose to derive it from IsValidOp which I'm saying is a bad idea, you will need Microsofts implementation. |
Last year I started writing examples for each validation rule in the OGC Simple Features standard, with the goal of then comparing NTS and MSSQL to see where they differ. 6.1.4.1 6.1.5 Valid Invalid 6.1.6.1 Valid Invalid 6.1.8.1 Valid 6.1.10.1 6.1.11.1 6.1.14 |
I was hit by this again very recently with the result of geometries in SQL Server flagged as invalid but not invalid according to SQL Server when checked with IsValidDetailed(). I agree with the initial assement in this issue that writing geometries should go through WKB to make SQL Server determine the validity. |
OP request served with bc17118 |
…n written to SQL. This allows to override the default IsValid of the NTS Geometry and provide an own strategy. This way you can use the IsValidOp with the option SelfTouchingRingFormingHoleValid flagged. Or just make them all valid following the JTS way. Either way the developer will have more control, and if we would manage to provide a IsValidSqlServerOp, it could be passed this way.
This allows to override the default IsValid of the NTS Geometry and provide an own strategy. This way you can use the IsValidOp with the option SelfTouchingRingFormingHoleValid flagged. Or just make them all valid following the NTS way. Either way the developer will have more control, and if we would manage to provide a IsValidSqlServerOp, it could be passed this way. relates to #12
There is an annoying behaviour regarding validation of SqlGeometry that may cause surprises. Validation of the data does not always happen, depending on the method of construction.
SqlGeometry.Deserialize
(as recommended in #10) is one method where validation does not happen.This is what I documented in our project, but it may need some rewording to explain it in a better way.
Users who are dealing with possibly invalid geometries and have
SqlGeometry
as their final output, should therefore avoid this module and use a different method like WKB:The text was updated successfully, but these errors were encountered: