internal List <Polygon> PolygonOperationWith(Polygon p, PolygonOperationType type) { if (!IsSimple || !p.IsSimple) { throw new PolygonException("Both polygons must be non-self-intersecting."); } Geometry resultPolys; switch (type) { case PolygonOperationType.Intersection: resultPolys = p.ToIPolygon().Intersection(ToIPolygon()); break; case PolygonOperationType.Union: resultPolys = p.ToIPolygon().Union(ToIPolygon()); break; case PolygonOperationType.Difference: resultPolys = p.ToIPolygon().Difference(ToIPolygon()); break; case PolygonOperationType.SymmetricDifference: resultPolys = p.ToIPolygon().SymmetricDifference(ToIPolygon()).Buffer(BufferDistance); break; default: throw new PolygonException("Unsupported operation type."); } var multiPolygon = resultPolys as MultiPolygon; var results = new List <Polygon>(); if (multiPolygon != null) { results.AddRange(multiPolygon.Geometries.Cast <NetTopologySuite.Geometries.Polygon>().SelectMany(poly => poly.ToElmaPolygons())); } if (resultPolys is NetTopologySuite.Geometries.Polygon polygon) { results.AddRange(polygon.ToElmaPolygons()); } foreach (var x in results) { x.UpdateDecomposition(); } return(results); }
public void KeyDown(KeyEventArgs key) { if (key.KeyCode != Keys.Space || FirstSelected) { return; } switch (_currentOpType) { case PolygonOperationType.Union: _currentOpType = PolygonOperationType.Difference; break; case PolygonOperationType.Intersection: break; case PolygonOperationType.Difference: _currentOpType = PolygonOperationType.Union; break; } UpdateHelp(); }
public static bool PolyOpSelected(PolygonOperationType opType, List <Polygon> polygons) { var polys = polygons.GetSelectedPolygons().ToList(); Geometry SymDiff(Geometry g, Geometry p) => p.SymmetricDifference(g); var selection = polygons.GetSelectedPolygonsAsMultiPolygon(); var touching = polygons.Where(p => { if (p.IsGrass) { return(false); } var ip = p.ToIPolygon(); return(!polys.Contains(p) && ip.Intersects(selection) && !ip.Contains(selection)); }).ToList(); if (!touching.Any()) { return(false); } var others = touching.ToIPolygons().Aggregate((Func <Geometry, Geometry, Geometry>)SymDiff); var remaining = polygons.Where(p => { if (p.IsGrass) { return(false); } var ipoly = p.ToIPolygon(); return(!touching.Contains(p) && !polys.Contains(p) && ipoly.Within(others)); }).ToList(); others = remaining.ToIPolygons().Aggregate(others, (Func <Geometry, Geometry, Geometry>)SymDiff); Geometry result; try { switch (opType) { case PolygonOperationType.Union: result = others.Union(selection); break; case PolygonOperationType.Difference: result = others.Difference(selection); break; case PolygonOperationType.Intersection: result = others.Intersection(selection); break; case PolygonOperationType.SymmetricDifference: result = others.SymmetricDifference(selection) .Buffer(Polygon.BufferDistance, new BufferParameters(0, EndCapStyle.Flat, JoinStyle.Bevel, 1)); break; default: throw new Exception("Unknown operation type."); } } catch (TopologyException) { Utils.ShowError( "Could not perform this operation. Make sure the polygons don't have self-intersections."); return(false); } touching.ForEach(p => polygons.Remove(p)); polys.ForEach(p => polygons.Remove(p)); remaining.ForEach(p => polygons.Remove(p)); switch (result) { case MultiPolygon polygon: { foreach (var geometry in polygon.Geometries.Cast <NetTopologySuite.Geometries.Polygon>().Where(p => !p.IsEmpty)) { var newPolys = geometry.ToElmaPolygons().ToList(); newPolys.ForEach(p => p.RemoveDuplicateVertices()); polygons.AddRange(newPolys); } break; } case NetTopologySuite.Geometries.Polygon polygon1 when !polygon1.IsEmpty: { var newPolys = polygon1.ToElmaPolygons().ToList(); newPolys.ForEach(p => p.RemoveDuplicateVertices()); polygons.AddRange(newPolys); break; } } if (!polygons.Any()) { Utils.ShowError("The level would become empty after this operation."); polygons.AddRange(polys); polygons.AddRange(touching); } return(true); }