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 共同交流学习!

 

转载于:https://www.cnblogs.com/hl137510705/p/8067404.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值