当前位置:   article > 正文

基于C#的ArcEngine二次开发50:生成面空洞连接线_c# shp 坐标 空洞

c# shp 坐标 空洞

目录

1 由无序点集生成不相交路径的算法

1.1 算法原理介绍与示意图

1.2 代码实现

2 面要素外环内环获取相关说明

2.1 获取面的四至范围:Evelope

2.2 获取面心点

2.3 点集连接成线

2.4 提取环


现有一个面,里边包含若干空洞,也即内环,需要生成一条连接线,将所有的内环连接,而且保证连接线不存在自相交现象。处理思路:

  1. 首先获取面的外环,之后针对每个外环,捕捉其面心点,将其面心点链接。
  2. 获取面心点后,需要根据面心点集构造一条过所有面心点的多段线;这个问题本质上以上运筹学中的基本最短路问题(ESPP),但是我们这里不要求那么精确;只需要生成一条不相交的多段线即可。一个最简单的处理为根据X和Y坐标排序,生成有序点集,再将有序点集转化为多段线即可。
  3. 此外还有一种思路是调用ArcGIS的VRP工具处理,但是流程相对较为复杂,暂不考虑。

1 由无序点集生成不相交路径的算法

1.1 算法原理介绍与示意图

来自知乎的一个回答

  1. 对所有点按照x坐标(x相同时按y)从小到大排序,把最左边的点记为A(若有多个取最下方的点),最右边的点记为B(若有多个取最上方的点)。
  2. 构造上链: 把所有在直线AB上方的点按x坐标(x相同时按y)从小到大连接起来
  3. 构造下链:对位于直线AB下方的点同样处理。

最后输出的时候注意把下链颠倒一下(连的时候是从A连到B的,输出的时候从B到A输出)就行。正确性显而易见:上链内部是边不交的(因为边的端点的x坐标从小到大排列),下链同理,上下链之间也不交(因为分处直线AB两侧,没法交)。然后就完了!时间复杂度O(NlgN),而且非常好写!示意图如下:

1.2 代码实现

下面是一段C#代码,吸收了上面算法的思想,主要思路为:

  1. 将原始点集线按照Y坐标递增排序
  2. 通过Y值判断坐标点是否属于同一行,再对同一行的坐标点按X值从小到大进行排序

注意,代码中的lineSpacing可以根据需要任意指定

  1. YSortedPointList = SrcPointList.OrderBy(o => o.Y).ToList(); //坐标点按Y值升序排序(Y值从小到大的排序)
  2. //二维平面坐标点排序
  3. for (int i = 0; i < YSortedPointList.Count - 1; i++)
  4. {
  5. //通过Y值之间的差值大小来判断坐标点是否属于同一行
  6. if (Math.Abs(YSortedPointList[i].Y - YSortedPointList[i + 1].Y) < LineSpacing)
  7. {
  8. RowPointList.Add(YSortedPointList[i]);
  9. //如果最后一个点不是单独一行的情况
  10. if (YSortedPointList.Count - 2 == i)
  11. {
  12. RowPointList.Add(YSortedPointList[i + 1]); //将最后一个坐标元素添加进来
  13. RowPointList = RowPointList.OrderBy(o => o.X).ToList();
  14. SortedPointList = SortedPointList.Concat(RowPointList).ToList();
  15. RowPointList.Clear();
  16. }
  17. }
  18. else
  19. {
  20. //如果第一个点是单独一行的情况
  21. if (0 == i)
  22. {
  23. SortedPointList.Add(YSortedPointList[i]);
  24. continue;
  25. }
  26. RowPointList.Add(YSortedPointList[i]);
  27. RowPointList = RowPointList.OrderBy(o => o.X).ToList(); //坐标点按X值升序排序
  28. SortedPointList = SortedPointList.Concat(RowPointList).ToList();
  29. RowPointList.Clear();
  30. //如果最后一个点是单独一行的情况
  31. if (YSortedPointList.Count - 2 == i)
  32. {
  33. SortedPointList.Add(YSortedPointList[i + 1]);
  34. }
  35. }
  36. }

2 面要素外环内环获取相关说明

2.1 获取面的四至范围:Evelope

可以通过已下属性和方法,获取四至范围信息:

属性或方法描述
UpperLeft左上点坐标
UpperRight右上角坐标
LowerLeft左下角坐标
LowerRight右下角坐标
XMin/XMaxX的最小最大值
YMin/YMaxY的最小最大值
ZMin/ZMaxZ的最小最大值
Project投影到指定的坐标系中
GeometryType 
  1. esriGeometryNull = 0
  2. esriGeometryPoint = 1
  3. esriGeometryMultipoint = 2
  4. esriGeometryPolyline = 3
  5. esriGeometryPolygon = 4
  6. esriGeometryEnvelope = 5
  7. esriGeometryPath = 6
  8. esriGeometryAny = 7
  9. esriGeometryMultiPatch = 9
  10. esriGeometryRing = 11
  11. esriGeometryLine = 13
  12. esriGeometryCircularArc = 14
  13. esriGeometryBezier3Curve = 15
  14. esriGeometryEllipticArc = 16
  15. esriGeometryBag = 17
  16. esriGeometryTriangleStrip = 18
  17. esriGeometryTriangleFan = 19
  18. esriGeometryRay = 20
  19. esriGeometrySphere = 21

常见GeometryType类型图示:

2.2 获取面心点

面心点,即为一个面的中心点,示意图如下:

代码:

  1. IPoint pt = new PointClass();
  2. (myGeo as IArea).QueryCentroid(pt);

2.3 点集连接成线

  1. IPointCollection ptColl = new PolylineClass();
  2. //加点
  3. ptColl.AddPoint(pt);
  4. //连线
  5. Polyline line = ptColl as Polyline;

2.4 提取环

环分内环和外环,对于普通的几个要素,只有一个图形;但是对于multipart要素,可能包含多个图形,图形个数等于外环个数;每个外环内部有多个内环。

IGeometry --> ExteriorRingBag --> InteriorRingBag

下面是官方帮助提供的用法示例:

  1. publicstaticvoid PolygonToString(IPolygon4 polygon)
  2. {
  3. IGeometryBag exteriorRingGeometryBag = polygon.ExteriorRingBag;
  4. IGeometryCollection exteriorRingGeometryCollection = exteriorRingGeometryBag as IGeometryCollection ;
  5. Trace .WriteLine("polygon.ExteriorRingCount = " + exteriorRingGeometryCollection.GeometryCount);
  6. for (int i = 0; i < exteriorRingGeometryCollection.GeometryCount; i++)
  7. {
  8. Trace .WriteLine("polygon.ExteriorRing[" + i +"]" );
  9. IGeometry exteriorRingGeometry = exteriorRingGeometryCollection.get_Geometry(i);
  10. IPointCollection exteriorRingPointCollection = exteriorRingGeometryasIPointCollection ;
  11. for (int j = 0; j < exteriorRingPointCollection.PointCount; j++)
  12. {
  13. Trace .WriteLine("Point[" + j +"] = " + PointToString(exteriorRingPointCollection.get_Point(j)));
  14. }
  15. IGeometryBag interiorRingGeometryBag = polygon.get_InteriorRingBag(exteriorRingGeometryasIRing );
  16. IGeometryCollection interiorRingGeometryCollection = interiorRingGeometryBagasIGeometryCollection ;
  17. Trace .WriteLine("polygon.InteriorRingCount[exteriorRing" + i +"] = " + interiorRingGeometryCollection.GeometryCount);
  18. for (int k = 0; k < interiorRingGeometryCollection.GeometryCount; k++)
  19. {
  20. Trace .WriteLine("polygon.InteriorRing[" + k +"]" );
  21. IGeometry interiorRingGeometry = interiorRingGeometryCollection.get_Geometry(k);
  22. IPointCollection interiorRingPointCollection = interiorRingGeometryasIPointCollection ;
  23. for (int m = 0; m < interiorRingPointCollection.PointCount; m++)
  24. {
  25. Trace .WriteLine("Point[" + m +"] = " + PointToString(interiorRingPointCollection.get_Point(m)));
  26. }
  27. }
  28. }
  29. }
  30. privates tatic string PointToString(IPoint point)
  31. {
  32. return (point.X +", " + point.Y +", " + point.Z);
  33. }

欢迎关注个人公众账号,一起学习,聪明的努力!

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/310398
推荐阅读
相关标签
  

闽ICP备14008679号