NetTopologySuite 工具类

  1 using System.Threading;
  2 using System.Collections.Generic;
  3 using GeoAPI.Geometries;
  4 using NetTopologySuite.Geometries;
  5 using NetTopologySuite.Operation.Polygonize;
  6 using System.Linq;
  7 
  8 namespace Test.Workspace
  9 {
 10     public static class NTSExpend
 11     {
 12         public static IGeometry Validate(this IGeometry geometry) => NTSUtils.Instance.Validate(geometry);
 13     }
 14     public class NTSUtils
 15     {
 16         private static NTSUtils _this = null;
 17         private static object lockObj = new object();
 18 
 19         /// <summary>
 20         /// 单例创建对象
 21         /// </summary>
 22         /// <returns></returns>
 23         public static NTSUtils Instance
 24         {
 25             get
 26             {
 27                 if (_this == null)
 28                 {
 29                     lock (lockObj)
 30                     {
 31                         if (_this == null)
 32                             _this = new NTSUtils();
 33                         return _this;
 34                     }
 35                 }
 36                 else
 37                     return _this;
 38             }
 39         }
 40 
 41         /// <summary>
 42         /// 处理图形自相交
 43         /// </summary>
 44         /// <returns></returns>
 45         public IGeometry Validate(IGeometry geometry)
 46         {
 47             Polygonizer polygonizer = null;
 48             if (geometry is Polygon)
 49             {
 50                 if (geometry.IsValid)
 51                 {
 52                     geometry.Normalize();
 53                     return geometry;
 54                 }
 55                 polygonizer = new Polygonizer();
 56 
 57                 AddPolygon((Polygon)geometry, polygonizer);
 58             }
 59             else if (geometry is MultiPolygon)
 60             {
 61                 if (geometry.IsValid)
 62                 {
 63                     geometry.Normalize();
 64                     return geometry;
 65                 }
 66                 polygonizer = new Polygonizer();
 67                 for (int n = geometry.NumGeometries; n-- > 0;)
 68                 {
 69                     AddPolygon((Polygon)geometry.GetGeometryN(n), polygonizer);
 70                 }
 71             }
 72             else if (geometry is GeometryCollection)
 73             {
 74                 if (geometry.IsValid)
 75                 {
 76                     geometry.Normalize();
 77                     return geometry;
 78                 }
 79                 polygonizer = new Polygonizer();
 80                 for (int n = geometry.NumGeometries; n-- > 0;)
 81                 {
 82                     IGeometry temp = geometry.GetGeometryN(n);
 83                     if (temp is Polygon)
 84                     {
 85                         AddPolygon((Polygon)temp, polygonizer);
 86                     }
 87                     else if (temp is MultiPolygon)
 88                     {
 89                         for (int m = temp.NumGeometries; m-- > 0;)
 90                         {
 91                             AddPolygon((Polygon)temp.GetGeometryN(m), polygonizer);
 92                         }
 93                     }
 94                 }
 95             }
 96             else
 97                 return geometry;
 98 
 99             return ToPolygonGeometry(polygonizer.GetPolygons(), geometry.Factory);
100         }
101 
102         void AddPolygon(Polygon polygon, Polygonizer polygonizer)
103         {
104             AddLineString(polygon.ExteriorRing, polygonizer);
105             for (int n = polygon.NumInteriorRings; n-- > 0;)
106             {
107                 AddLineString(polygon.GetInteriorRingN(n), polygonizer);
108             }
109         }
110 
111         void AddLineString(ILineString lineString, Polygonizer polygonizer)
112         {
113 
114             if (lineString is LinearRing)
115             { // LinearRings are treated differently to line strings : we need a LineString NOT a LinearRing
116                 lineString = lineString.Factory.CreateLineString(lineString.CoordinateSequence);
117             }
118 
119             // unioning the linestring with the point makes any self intersections explicit.
120 
121             IPoint point = lineString.Factory.CreatePoint(lineString.GetCoordinateN(0));
122             IGeometry toAdd = lineString.Union(point);
123 
124             //Add result to polygonizer
125             polygonizer.Add(toAdd);
126         }
127 
128         /**
129          * Get a geometry from a collection of polygons.
130          * 
131          * @param polygons collection
132          * @param factory factory to generate MultiPolygon if required
133          * @return null if there were no polygons, the polygon if there was only one, or a MultiPolygon containing all polygons otherwise
134          */
135         IGeometry ToPolygonGeometry(ICollection<IGeometry> polygons, IGeometryFactory factory)// geoSource.factory 可以创建多边形
136         {
137             switch (polygons.Count())
138             {
139                 case 0:
140                     return null; // No valid polygons!
141                 case 1:
142                     return polygons.FirstOrDefault(); // single polygon - no need to wrap
143                 default:
144                     //polygons may still overlap! Need to sym difference them
145                     List<IGeometry> ps = polygons.ToList();
146                     double maxArea = ps.Select(x => x.Envelope.Area).Max();
147                     IGeometry geometry = ps.FirstOrDefault(x => x.Envelope.Area == maxArea);
148                     IGeometry result = geometry;
149                     for (int i = 0; i < ps.Count; i++)
150                     {
151                         IGeometry currentGeo = ps[i];
152 
153                         //string testStr = currentGeo.ToString();
154                         //string res = GdalShapeOperate.Instance.GetPoints(OSGeo.OGR.Ogr.CreateGeometryFromWkt(ref testStr, null));
155                         if (currentGeo == null || currentGeo.Equals(geometry))
156                             continue;
157 
158                         //1. 判断当前图形是否是多环图形
159 
160                         //Covers 优于 Contains  
161                         // symDifference 并集去掉重合部分
162                         IPolygon p = result as IPolygon;
163                         if (p?.NumInteriorRings > 0)
164                         {
165                             //多环的话 需要把内部空环依次和当前图形比对 判断是否是重叠 (重叠取diff)
166                             Polygonizer polygonizer = new Polygonizer();
167                             for (int n = p.NumInteriorRings; n-- > 0;)
168                             {
169                                 AddLineString(p.GetInteriorRingN(n), polygonizer);
170                             }
171                             List<IGeometry> interPolygons = polygonizer.GetPolygons().ToList();
172                             //内环存在的话 需要和当前图形比对 如果基本匹配(重合面积>90) 取差集
173                             if (interPolygons.Count > 0)
174                             {
175                                 bool isIntersect = false;
176                                 foreach (var item in interPolygons)
177                                 {
178                                     if (item.Intersects(currentGeo) && item.Intersection(currentGeo).Area / currentGeo.Area > 0.9)
179                                     {
180                                         isIntersect = true;
181                                         break;
182                                     }
183                                 }
184                                 if (isIntersect)
185                                 {
186                                     result = result.Difference(currentGeo);
187                                     continue;
188                                 }
189                             }
190                         }
191 
192                         //不是多环图形, 如果重叠 且重叠面积>当前图形面积的90%则 交集, 否则并集
193                         if (geometry.Intersects(currentGeo) && geometry.Intersection(currentGeo).Area / currentGeo.Area > 0.9)
194                             result = result.Difference(currentGeo);
195                         else
196                             result = result.Union(currentGeo);
197 
198                     }
199                     return result;
200             }
201         }
202 
203         /// <summary>
204         /// wkt转geometry
205         /// </summary>
206         /// <param name="wkt"></param>
207         /// <returns></returns>
208         public IGeometry WktToGeometry(string wkt)
209         {
210             NetTopologySuite.IO.WKTReader reader = new NetTopologySuite.IO.WKTReader();
211             IGeometry geo = reader.Read(wkt);
212             return geo;
213         }
214 
215         /// <summary>
216         /// rings 转 geometry
217         /// </summary>
218         /// <param name="rings"></param>
219         /// <returns></returns>
220         public IGeometry RingsToGeometry(string rings)
221         {
222             OSGeo.OGR.Geometry geometry = GdalShapeOperate.Instance.GetGeometryFromShapeJson(rings);
223 
224             string wkt = string.Empty;
225             while (wkt == string.Empty)
226             {
227                 wkt = GdalShapeOperate.Instance.ExportToWkt(geometry);
228                 Thread.Sleep(50);
229             }
230             return WktToGeometry(wkt);
231         }
232 
233         public string WktToRings(string wkt) => GdalShapeOperate.Instance.GetPoints(OSGeo.OGR.Geometry.CreateFromWkt(wkt));
234 
235         public string GeometryToRings(Geometry geo) => GdalShapeOperate.Instance.GetPoints(OSGeo.OGR.Geometry.CreateFromWkt(geo.ToString()));
236     }
237 }

 

posted @ 2020-08-10 17:15  Jason's_Blog  阅读(2602)  评论(0编辑  收藏  举报