SQL Server存儲多邊形,自相交處理-selfIntersection


      目前大多數數據庫已支持空間數據存儲,我本人用過mysql,Oracle,SqlServer三種數據庫,常見利用數據庫Geometry類型,存儲面狀圖形,但在繪制過程中會經常出現自相交的微小面,如下圖所示 ,在arcmap中打開這種微小面,會報自相交錯誤

經過一番查閱資料,發現網友有相似經歷,網上也有JAVA的解決方案,本人將其轉化為.net版,以方便以后遇到類似問題的同志們。大致過程如下,利用GeoAPI,NetTopologySuite 可以將GeoJson,轉化為oracle,sqlserver,mysql格式的Geometry,利用ORM保存。

GeoAPI,NetTopologySuite 網上有開源代碼,有興趣的可以自己下載來看。

引用的類庫:

using GeoAPI.Geometries;
using NetTopologySuite.Geometries;
using NetTopologySuite.Operation.Polygonize;

 public class GeometryRepair
    {
        /// <summary>
        /// 驗證圖形是否自相交
        /// </summary>
        /// <param name="geom"></param>
        /// <returns></returns>
        public static IGeometry validateGeometry(IGeometry geom)
        {
            if (geom is Polygon)
            {
                if (geom.IsValid)
                {
                    geom.Normalize();
                    return geom;
                }
                Polygonizer polygonizer = new Polygonizer();
                addPolygon((Polygon)geom, polygonizer);
                return toPolygonGeometry(polygonizer.GetPolygons(), geom.Factory as IGeometryFactory);
            }
            else if (geom is MultiPolygon)
            {
                if (geom.IsValid)
                {
                    geom.Normalize();
                    return geom;
                }
                Polygonizer polygonizer = new Polygonizer();
                for (int n = geom.NumGeometries; n-- > 0;)
                {
                    addPolygon((Polygon)geom.GetGeometryN(n), polygonizer);
                }
                return toPolygonGeometry(polygonizer.GetPolygons(), geom.Factory as IGeometryFactory);
            }
            else
            {
                return geom;
            }
        }

        /// <summary>
        /// 添加多邊形
        /// </summary>
        /// <param name="polygon"></param>
        /// <param name="polygonizer"></param>
        static void addPolygon(Polygon polygon, Polygonizer polygonizer)
        {
            addLineString(polygon.ExteriorRing as LineString, polygonizer);
            for (int n = polygon.NumInteriorRings; n-- > 0;)
            {
                var line = polygon.GetInteriorRingN(n) as LineString;
                addLineString(line, polygonizer);
            }
        }

        /// <summary>
        /// 添加線
        /// </summary>
        /// <param name="lineString"></param>
        /// <param name="polygonizer"></param>
        static void addLineString(LineString lineString, Polygonizer polygonizer)
        {
            if (lineString is LinearRing)
            {
                lineString = lineString.Factory.CreateLineString(lineString.CoordinateSequence) as LineString;
            }
            Point point = lineString.Factory.CreatePoint(lineString.GetCoordinateN(0)) as Point;
            IGeometry toAdd = lineString.Union(point);
            polygonizer.Add(toAdd);
        }

        /// <summary>
        /// 將面對象轉化為一個多面
        /// </summary>
        /// <param name="polygons"></param>
        /// <param name="factory"></param>
        /// <returns></returns>
        static IGeometry toPolygonGeometry(ICollection<IGeometry> polygons, IGeometryFactory factory)
        {
            switch (polygons.Count)
            {
                case 0:
                    return null;
                case 1:
                    return polygons.First();
                default:
                    List<IPolygon> mPolygons = new List<IPolygon>();
                    foreach (IGeometry g in polygons)
                    {
                        mPolygons.Add(g as IPolygon);
                    }
                    return factory.CreateMultiPolygon(mPolygons.ToArray()) as MultiPolygon;
            }
        }
    }

 

 更多GIS開發相關問題請加入 GIS開發學習QQ交流群 192251607 共同交流學習!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM