NetTopologySuite 说几何无效,但是 Sql 服务器说它有效

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

我有多边形:

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))

确实看起来不正常,但是 Sql Server 2017 说它是有效的。
但是当我试图用 NTE 阅读它时,它说它是无效的。这是简单的代码:

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;

我尝试 'play' 使用 PrecisionModels 但没有结果。有什么建议吗?

您需要明确使用 IsValidOp 并设置 SelfTouchingRingFormingHoleValid = true:

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

您的多边形只有一个环定义 shell 和洞,不是分开的。要使其在 NTS 中有效,多边形的 WKT 将为

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))

您是否按照 https://github.com/NetTopologySuite/NetTopologySuite/wiki/GettingStarted 尝试过“Buffer0”黑客攻击?我今天晚上遇到了类似的问题,并且在我为我的案例解决它时发现了这个问题。

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