private MultiPolygon MergeInnerIntoOuterPolygon(List <Polygon> outerPolygons, List <Polygon> innerPolygons) { var newOuterPolygons = new List <Polygon>(); outerPolygons = MergePolygons(outerPolygons); foreach (var outerPolygon in outerPolygons) { // remove all inner holes from outer polygon var newOuterPolygon = _geometryFactory.CreatePolygon((LinearRing)outerPolygon.ExteriorRing.Copy()); // get inner polygons var currentInnerPolygons = innerPolygons.Where(p => p.Within(newOuterPolygon)).ToArray(); if (!currentInnerPolygons.Any()) { newOuterPolygons.Add(newOuterPolygon); continue; } var holesPolygons = currentInnerPolygons.Select(p => _geometryFactory.CreatePolygon(p.ExteriorRing.Copy() as LinearRing)).ToArray(); var holesUnifiedGeometry = CascadedPolygonUnion.Union(holesPolygons); // adding the difference between the outer polygon and all the holes inside it newOuterPolygons.Add(newOuterPolygon.Difference(holesUnifiedGeometry) as Polygon); // update list for next loop cycle innerPolygons = innerPolygons.Except(currentInnerPolygons).ToList(); } return(_geometryFactory.CreateMultiPolygon(newOuterPolygons.Union(innerPolygons).ToArray())); }
public void PerformCascadedPolygonUnion() { var reader = new ShapefileReader("tnp_pol.shp"); var collection = reader.ReadAll().Where(e => e is IPolygon).ToList(); var u1 = collection[0]; for (var i = 1; i < collection.Count; i++) { u1 = SnapIfNeededOverlayOp.Overlay(u1, collection[i], SpatialFunction.Union); } var u2 = CascadedPolygonUnion.Union(collection); if (!u1.Equals(u2)) { Assert.Fail("failure"); } }
private List <Polygon> MergePolygons(List <Polygon> polygons) { if (!polygons.Any()) { return(polygons); } try { var merged = CascadedPolygonUnion.Union(polygons.ToArray()); if (merged is MultiPolygon multipolygon) { return(multipolygon.Geometries.Cast <Polygon>().ToList()); } return(new List <Polygon> { merged as Polygon }); } catch { return(polygons); } }
/// <summary> /// Converts a flat path to a <see cref="IGeometry"/>. /// </summary> /// <param name="wpfGeometry">The geometry to convert</param> /// <returns>A Geometry representing the path</returns> public IGeometry Read(WpfGeometry wpfGeometry) { var pathGeometry = PathGeometry.CreateFromGeometry(wpfGeometry); /* * .Item1 ... Closed * .Item2 ... Filled * .Item3 ... List<Coordinate[]> */ var pathPtSeq = ToCoordinates(pathGeometry); var geoms = new List <IGeometry>(); var seqIndex = 0; while (seqIndex < pathPtSeq.Count) { // assume next seq is shell // TODO: test this var pts = pathPtSeq[seqIndex]; if (pts.Item3.Length == 1) { geoms.Add(_geometryFactory.CreatePoint(pts.Item3[0])); seqIndex++; } else if (!(pts.Item1 || pts.Item2)) // neither closed nor filled { geoms.Add(_geometryFactory.CreateLineString(pts.Item3)); seqIndex++; } else { if (!pts.Item2) { geoms.Add(_geometryFactory.CreateLineString(pts.Item3)); continue; } var ringPts = ClosedCoordinateRing(pts.Item3); var rings = new List <IGeometry>(new[] { _geometryFactory.CreateLinearRing(ringPts) }); seqIndex++; //if (seqIndex < pathPtSeq.Count) //{ // if (!(pathPtSeq[seqIndex].Item1 || pathPtSeq[seqIndex].Item2)) continue; Coordinate[] holePts; // add holes as long as rings are CCW while (seqIndex < pathPtSeq.Count && (pathPtSeq[seqIndex].Item1 || pathPtSeq[seqIndex].Item2) && IsHole(holePts = pathPtSeq[seqIndex].Item3)) { rings.Add(_geometryFactory.CreateLinearRing(holePts)); seqIndex++; } var noder = new NetTopologySuite.Noding.Snapround.GeometryNoder(new NetTopologySuite.Geometries.PrecisionModel(100000000.0)); var nodedLinework = noder.Node(rings); // Use the polygonizer var p = new Polygonizer(pathGeometry.FillRule == FillRule.EvenOdd); p.Add(nodedLinework.ToList <IGeometry>()); var tmpPolygons = p.GetPolygons(); if (pathGeometry.FillRule == FillRule.Nonzero) { var unionized = CascadedPolygonUnion.Union(NetTopologySuite.Geometries.GeometryFactory.ToPolygonArray(tmpPolygons)); tmpPolygons = new List <IGeometry>(new[] { unionized }); } geoms.AddRange(tmpPolygons); //} } } return(BuildGeometry(geoms)); }
public Geometry UnionCascaded(IList <Geometry> geoms) { return(CascadedPolygonUnion.Union(geoms)); }
public static ObjectId UnionPolygonCascaded(ObjectId[] plineIds) { if (plineIds.Count() == 0) { return(ObjectId.Null); } var deletePolyIds = new List <ObjectId>(); var database = plineIds[0].Database; var geometries = new List <IGeometry>(); ObjectId polygonId = ObjectId.Null; using (var tr = database.TransactionManager.StartTransaction()) { var reader = new DwgReader() { PrecisionScale = 100000 }; foreach (var plineId in plineIds) { var pline = tr.GetObject(plineId, OpenMode.ForRead) as Curve; if (pline != null && pline.Closed) { var geomerty = reader.ReadCurveAsPolygon(tr, pline); geomerty.Buffer(0); geometries.Add(geomerty); deletePolyIds.Add(plineId); } } // 合并 var resultPolygon = CascadedPolygonUnion.Union(geometries); var writer = new DwgWriter() { PrecisionScale = 100000 }; var polygon = resultPolygon as Polygon; if (polygon != null) { var polyline = writer.WritePolyline(polygon.Shell); var modelspaceId = SymbolUtilityServices.GetBlockModelSpaceId(database); var modelspace = (BlockTableRecord)tr.GetObject(modelspaceId, OpenMode.ForWrite); polygonId = modelspace.AppendEntity(polyline); tr.AddNewlyCreatedDBObject(polyline, true); // 删除已经形成多边形的地块 foreach (var plineId in deletePolyIds) { var pline = tr.GetObject(plineId, OpenMode.ForWrite) as Curve; var geomerty = reader.ReadCurveAsPolygon(tr, pline); if (pline != null && geomerty != null && polygon.Contains(geomerty)) { pline.Erase(true); } } } tr.Commit(); } return(polygonId); }