NetTopologySuite said that geometry is not valid, but Sql Server said that it's valid
Asked Answered
C

2

5

I have polygon:

polygon((0 0, 1 0.1, 1 1, 0.5 1, 0.5 1.5, 1 1, 1.5 1.5, 1.5 1, 1 1, 1.5 0.5, 1 0.1, 2 0, 2 2,0 2, 0 0))

enter image description here

For sure it's not looks normal, but Sql Server 2017 said that it's valid.
But when i tried to read it with NTE it's say that it is not valid. Here is simple code:

var wkt = @"polygon((0 0, 1 0.1, 1 1, 0.5 1, 0.5 1.5, 1 1, 1.5 1.5, 1.5 1, 1 1, 1.5 0.5, 1 0.1, 2 0, 2 2,0 2, 0 0))";
var wktReader2 = new WKTReader();
var initialGeometry = wktReader2.Read(wkt);
var t = initialGeometry.IsValid;

I tried to 'play' with PrecisionModels but no result. Any advise?

Cockahoop answered 15/11, 2021 at 10:51 Comment(0)
P
4

You need to use IsValidOp explicitly and set SelfTouchingRingFormingHoleValid = true:

var ivo = new NetTopologySuite.Operation.Valid.IsValidOp(initialGeometry);
ivo.SelfTouchingRingFormingHoleValid = true;
bool t = ivo.IsValid;

Your polygon only has one ring defining shell and holes, not seperate. To have it valid in NTS the polygon's WKT would be

POLYGON ((0 0, 0 2, 2 2, 2 0, 1 0.1, 0 0), (1 0.1, 1.5 0.5, 1 1, 1 0.1), 
         (1 1, 1.5 1, 1.5 1.5, 1 1), (1 1, 0.5 1.5, 0.5 1, 1 1))
Pompon answered 16/11, 2021 at 7:23 Comment(0)
S
2

Have you tried the "Buffer0" hack, as per https://github.com/NetTopologySuite/NetTopologySuite/wiki/GettingStarted. I encountered a similar issue this evening, and found this question just as I solved it for my case.

Note: Sometimes you will meet invalid geometries (Geometry.IsValid == false). These will cause issues while further processing them. In most cases you will be able to fix this using the Buffer0 trick:

geom = geom.Buffer(0);

var wkt = @"polygon((0 0, 1 0.1, 1 1, 0.5 1, 0.5 1.5, 1 1, 1.5 1.5, 1.5 1, 1 1, 1.5 0.5, 1 0.1, 2 0, 2 2,0 2, 0 0))";
var wktReader2 = new NetTopologySuite.IO.WKTReader();
var initialGeometry = wktReader2.Read(wkt);
var t = initialGeometry.IsValid;
_logger.LogInformation(t.ToString());        // False

var t2 = initialGeometry.Buffer(0).IsValid;
_logger.LogInformation(t2.ToString());       // True
Shulock answered 19/11, 2021 at 8:5 Comment(3)
Nowadays you should use NetTopologySuite.Geometries.Utilities.GeometryFixer.Fix(invalidGeometry) to fix invalid geometries.Pompon
@Pompon I am getting GeometryFixer does not exist in the current context when attempting to fix geometry with the above, despite adding NetTopologySuite.Geometries.Utilities as a dependency.Sioux
@NickyLarson, you need to update to NTS v2.4Pompon

© 2022 - 2024 — McMap. All rights reserved.