Why does NetTopologySuite GetPolygons return zero results?

228 Views Asked by At

I am trying to take a bunch of arbitrary line segments and convert them to polygons using NetTopology GetPolygons method. I have written below based on examples I have seen using this package. My lines are clearly intersecting, and clearly form polygons but I get no results, and all of the lines are in the "dangles" section.

NetTopologySuite.Geometries.GeometryFactory geometryFactory = new NetTopologySuite.Geometries.GeometryFactory();
List<NetTopologySuite.Geometries.Geometry> lines = new List<NetTopologySuite.Geometries.Geometry>();            

foreach(var line in segments)
{
    List<NetTopologySuite.Geometries.Coordinate> coords = new List<NetTopologySuite.Geometries.Coordinate>();

    NetTopologySuite.Geometries.Coordinate lineStart = new NetTopologySuite.Geometries.Coordinate(line.X1, line.Y1);
    NetTopologySuite.Geometries.Coordinate lineEnd = new NetTopologySuite.Geometries.Coordinate(line.X2, line.Y2);
                
    coords.Add(lineStart);
    coords.Add(lineEnd);
                
    var lineGeometry = geometryFactory.CreateLineString(coords.ToArray());

    Console.WriteLine("L=" + lineGeometry.ToString());

    lines.Add(lineGeometry);
}
            
Polygonizer polygonizer = new Polygonizer();
polygonizer.Add(lines);
var polys = polygonizer.GetPolygons();
// Return zero
var dangles = polygonizer.GetDangles();
// Returns zero      

Perhaps im not using it correctly, or its not designed to do what I expect?

Input

Image with intersecting lines fed to polygonizer

Expected (Closed lines form polygons, other lines (red x) are dangles?):

enter image description here

I include a serialized list of my lines

string ls = @"[{"Start":{"X":326.7043151855469,"Y":72.9458999633789,"ShapeType":0,"Stroke":null,"Fill":null,"StrokeThickness":0,"Visible":false,"ID":0,"Tag":null,"Opacity":0},"End":{"X":948.3546752929688,"Y":77.146240234375,"ShapeType":0,"Stroke":null,"Fill":null,"StrokeThickness":0,"Visible":false,"ID":0,"Tag":null,"Opacity":0},"X1":326.7043151855469,"Y1":72.9458999633789,"X2":948.3546752929688,"Y2":77.146240234375,"ShapeType":1,"Stroke":"#FFFFFF","Fill":null,"StrokeThickness":3,"Visible":false,"ID":100001,"Tag":"temp","Opacity":0},{"Start":{"X":452.7145080566406,"Y":35.14283752441406,"ShapeType":0,"Stroke":null,"Fill":null,"StrokeThickness":1,"Visible":true,"ID":0,"Tag":null,"Opacity":1},"End":{"X":446.41400146484375,"Y":215.75747680664062,"ShapeType":0,"Stroke":null,"Fill":null,"StrokeThickness":1,"Visible":true,"ID":0,"Tag":null,"Opacity":1},"X1":452.7145080566406,"Y1":35.14283752441406,"X2":446.41400146484375,"Y2":215.75747680664062,"ShapeType":1,"Stroke":"#FFFFFF","Fill":null,"StrokeThickness":3,"Visible":true,"ID":100002,"Tag":"temp","Opacity":1},{"Start":{"X":654.3308715820312,"Y":35.14283752441406,"ShapeType":0,"Stroke":null,"Fill":null,"StrokeThickness":1,"Visible":true,"ID":0,"Tag":null,"Opacity":1},"End":{"X":643.8300170898438,"Y":209.4569549560547,"ShapeType":0,"Stroke":null,"Fill":null,"StrokeThickness":1,"Visible":true,"ID":0,"Tag":null,"Opacity":1},"X1":654.3308715820312,"Y1":35.14283752441406,"X2":643.8300170898438,"Y2":209.4569549560547,"ShapeType":1,"Stroke":"#FFFFFF","Fill":null,"StrokeThickness":3,"Visible":true,"ID":100003,"Tag":"temp","Opacity":1},{"Start":{"X":792.9420776367188,"Y":35.14283752441406,"ShapeType":0,"Stroke":null,"Fill":null,"StrokeThickness":1,"Visible":true,"ID":0,"Tag":null,"Opacity":1},"End":{"X":795.042236328125,"Y":213.6573028564453,"ShapeType":0,"Stroke":null,"Fill":null,"StrokeThickness":1,"Visible":true,"ID":0,"Tag":null,"Opacity":1},"X1":792.9420776367188,"Y1":35.14283752441406,"X2":795.042236328125,"Y2":213.6573028564453,"ShapeType":1,"Stroke":"#FFFFFF","Fill":null,"StrokeThickness":3,"Visible":true,"ID":100004,"Tag":"temp","Opacity":1},{"Start":{"X":330.9046325683594,"Y":165.3533935546875,"ShapeType":0,"Stroke":null,"Fill":null,"StrokeThickness":1,"Visible":true,"ID":0,"Tag":null,"Opacity":1},"End":{"X":918.9522705078125,"Y":169.55372619628906,"ShapeType":0,"Stroke":null,"Fill":null,"StrokeThickness":1,"Visible":true,"ID":0,"Tag":null,"Opacity":1},"X1":330.9046325683594,"Y1":165.3533935546875,"X2":918.9522705078125,"Y2":169.55372619628906,"ShapeType":1,"Stroke":"#FFFFFF","Fill":null,"StrokeThickness":3,"Visible":true,"ID":100005,"Tag":"temp","Opacity":1},{"Start":{"X":547.22216796875,"Y":49.84402847290039,"ShapeType":0,"Stroke":null,"Fill":null,"StrokeThickness":1,"Visible":true,"ID":0,"Tag":null,"Opacity":1},"End":{"X":549.3223266601562,"Y":117.04946899414062,"ShapeType":0,"Stroke":null,"Fill":null,"StrokeThickness":1,"Visible":true,"ID":0,"Tag":null,"Opacity":1},"X1":547.22216796875,"Y1":49.84402847290039,"X2":549.3223266601562,"Y2":117.04946899414062,"ShapeType":1,"Stroke":"#FFFFFF","Fill":null,"StrokeThickness":3,"Visible":true,"ID":100006,"Tag":"temp","Opacity":1},{"Start":{"X":549.3223266601562,"Y":117.04946899414062,"ShapeType":0,"Stroke":null,"Fill":null,"StrokeThickness":1,"Visible":true,"ID":0,"Tag":null,"Opacity":1},"End":{"X":685.8333740234375,"Y":127.55032348632812,"ShapeType":0,"Stroke":null,"Fill":null,"StrokeThickness":1,"Visible":true,"ID":0,"Tag":null,"Opacity":1},"X1":549.3223266601562,"Y1":117.04946899414062,"X2":685.8333740234375,"Y2":127.55032348632812,"ShapeType":1,"Stroke":"#FFFFFF","Fill":null,"StrokeThickness":3,"Visible":true,"ID":100007,"Tag":"temp","Opacity":1},{"Start":{"X":549.3223266601562,"Y":112.84913635253906,"ShapeType":0,"Stroke":null,"Fill":null,"StrokeThickness":1,"Visible":true,"ID":0,"Tag":null,"Opacity":1},"End":{"X":551.4224853515625,"Y":192.6555938720703,"ShapeType":0,"Stroke":null,"Fill":null,"StrokeThickness":1,"Visible":true,"ID":0,"Tag":null,"Opacity":1},"X1":549.3223266601562,"Y1":112.84913635253906,"X2":551.4224853515625,"Y2":192.6555938720703,"ShapeType":1,"Stroke":"#FFFFFF","Fill":null,"StrokeThickness":3,"Visible":true,"ID":100008,"Tag":"temp","Opacity":1}]";
            
var lines = JsonSerializer.Deserialize<List<Line>>(ls);
1

There are 1 best solutions below

1
On BEST ANSWER

Yeah, NTS doesn't do that. The thing is that Polygonizer only joins lines from their ends. It does not break them first. You need to do that yourself. It can be easy if horizontal and vertical lines are distinguishable. Otherwise, you need to check all lines two by two and break them from their intersections.

WKTReader reader = new WKTReader();
var vLines = reader.Read("MULTILINESTRING ((124.5 309, 117.5 151.5), (229.5 316, 214.5 152.5), (330 320, 320 155.5), (430 320, 418 163))");
var hLines = reader.Read("MULTILINESTRING ((96.5 284.5, 469.5 276.5), (95.5 172.5, 464.5 187), (195.5 237.5, 361 226.5))");

var hLinesBreaked = hLines.Difference(vLines);
var vLinesBreaked = vLines.Difference(hLines);
var allLines = vLinesBreaked.Union(hLinesBreaked);

Polygonizer polygonizer = new Polygonizer();
polygonizer.Add(allLines);
ICollection<Geometry> polys = polygonizer.GetPolygons(); // count: 4
ICollection<LineString> dangles = polygonizer.GetDangles(); // count: 14

enter image description here