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

目录

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可以根据需要任意指定

            YSortedPointList = SrcPointList.OrderBy(o => o.Y).ToList();   //坐标点按Y值升序排序(Y值从小到大的排序)
 
            //二维平面坐标点排序
            for (int i = 0; i < YSortedPointList.Count - 1; i++)
            {
                //通过Y值之间的差值大小来判断坐标点是否属于同一行
                if (Math.Abs(YSortedPointList[i].Y - YSortedPointList[i + 1].Y) < LineSpacing)
                {
                    RowPointList.Add(YSortedPointList[i]);
 
                    //如果最后一个点不是单独一行的情况
                    if (YSortedPointList.Count - 2 == i)
                    {
                        RowPointList.Add(YSortedPointList[i + 1]);      //将最后一个坐标元素添加进来
                        RowPointList = RowPointList.OrderBy(o => o.X).ToList();
                        SortedPointList = SortedPointList.Concat(RowPointList).ToList();
                        RowPointList.Clear();
                    }
                }
                else
                {
                    //如果第一个点是单独一行的情况
                    if (0 == i)
                    {
                        SortedPointList.Add(YSortedPointList[i]);
                        continue;
                    }
 
                    RowPointList.Add(YSortedPointList[i]);
                    RowPointList = RowPointList.OrderBy(o => o.X).ToList();                  //坐标点按X值升序排序
                    SortedPointList = SortedPointList.Concat(RowPointList).ToList();
                    RowPointList.Clear();
 
                    //如果最后一个点是单独一行的情况
                    if (YSortedPointList.Count - 2 == i)
                    {
                        SortedPointList.Add(YSortedPointList[i + 1]);
                    }
                }             
            }

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

2.1 获取面的四至范围:Evelope

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

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

常见GeometryType类型图示:

2.2 获取面心点

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

代码:

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

2.3 点集连接成线

IPointCollection ptColl = new PolylineClass();
//加点
ptColl.AddPoint(pt);
//连线
Polyline line = ptColl as Polyline;

2.4 提取环

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

IGeometry --> ExteriorRingBag --> InteriorRingBag

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

publicstaticvoid PolygonToString(IPolygon4 polygon)
{
    IGeometryBag exteriorRingGeometryBag = polygon.ExteriorRingBag;
    IGeometryCollection exteriorRingGeometryCollection = exteriorRingGeometryBag as IGeometryCollection ;
    Trace .WriteLine("polygon.ExteriorRingCount = " + exteriorRingGeometryCollection.GeometryCount);
    for (int i = 0; i < exteriorRingGeometryCollection.GeometryCount; i++)
    {
        Trace .WriteLine("polygon.ExteriorRing[" + i +"]" );
        IGeometry exteriorRingGeometry = exteriorRingGeometryCollection.get_Geometry(i);
        IPointCollection exteriorRingPointCollection = exteriorRingGeometryasIPointCollection ;
        for (int j = 0; j < exteriorRingPointCollection.PointCount; j++)
        {
            Trace .WriteLine("Point[" + j +"] = " + PointToString(exteriorRingPointCollection.get_Point(j)));
        }
        IGeometryBag interiorRingGeometryBag = polygon.get_InteriorRingBag(exteriorRingGeometryasIRing );
        IGeometryCollection interiorRingGeometryCollection = interiorRingGeometryBagasIGeometryCollection ;
        Trace .WriteLine("polygon.InteriorRingCount[exteriorRing" + i +"] = " + interiorRingGeometryCollection.GeometryCount);
        for (int k = 0; k < interiorRingGeometryCollection.GeometryCount; k++)
        {
            Trace .WriteLine("polygon.InteriorRing[" + k +"]" );
            IGeometry interiorRingGeometry = interiorRingGeometryCollection.get_Geometry(k);
            IPointCollection interiorRingPointCollection = interiorRingGeometryasIPointCollection ;
            for (int m = 0; m < interiorRingPointCollection.PointCount; m++)
            {
                Trace .WriteLine("Point[" + m +"] = " + PointToString(interiorRingPointCollection.get_Point(m)));
            }
        }
   }
}

privates tatic string PointToString(IPoint point)
{
    return (point.X +", " + point.Y +", " + point.Z);
}

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

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 基于C#ArcEngine二次开发是一种利用ArcGIS Engine开发工具和C#编程语言来实现GIS应用程序的方法。ArcEngine是一种基于组件的GIS开发平台,它提供了一系列的API和工具,可以帮助开发人员快速构建高效、灵活、可定制的GIS应用程序。C#是一种向对象的编程语言,它具有简单易学、语法清晰、可读性强等特点,非常适合用于GIS应用程序的开发。基于C#ArcEngine二次开发可以实现各种功能,如地图显示、数据查询、空间分析、地图制图等,可以广泛应用于各种领域,如城市规划、土地利用、环境保护、资源管理等。 ### 回答2: ++的编程语言,它有什么优点? C++ 是一种功能强大的编程语言,它几乎拥有 C 语言所有的优点,还可以在向对象编程方提供更高效和灵活的方式。下是 C++ 的几个主要优点: 1. 高效性:C++ 是一种高效的编程语言。与其他编程语言相比,C++ 的执行速度更快,它使用了更少的内存和 CPU 周期,因此可以为需要高性能的应用程序提供更好的支持。 2. 跨平台性:C++ 的编译器可以运行在许多平台上,包括 Windows、MacOS、Linux、Android 和 iOS 等。这使得 C++ 成为一种支持跨平台开发的编程语言,具有极高的灵活性和可扩展性。 3. 向对象编程:C++ 的向对象编程能力非常强大。它支持多态、继承和封装等特性,使得向对象编程更加容易和灵活。 4. 库管理:C++ 提供了许多强大的库,使得开发人员可以轻松地访问各种常用功能,例如文件 I/O、字符串处理、图形界等。这些库可以大大提高开发人员的效率,减少重复劳动。 5. 可扩展性:C++ 还具有很高的可扩展性。开发人员可以使用 C++ 来编写模块、插件和扩展程序,以满足特定的需求。此外,C++ 还提供了丰富的 API,使得开发人员可以在其程序中使用其他编程语言和技术。 总的来说,C++ 是一种功能强大、高效、跨平台、向对象、可扩展的编程语言。它在许多行业和领域中都有广泛的应用,例如游戏开发、嵌入式系统、图形界等。对于需要高性能和高可靠性的应用程序开发来说,C++ 是一种不错的选择。 ### 回答3: 语言的网络编程的特点是什么? C语言作为一种高效、简洁、可移植的编程语言,在网络编程中也有一定的应用。C语言基于网络编程的特点主要有以下几个方: 1.底层控制:C语言网络编程的一个重要特点是可以对网络协议的底层进行直接控制,比如可以进行原始套接字编程。这种方式可以对网络数据包进行非常细致的处理和控制,使网络程序能够更好地适应各种各样的网络环境。 2.高效性:C语言是一种高效的编程语言,它可以为网络应用程序提供高效的性能。C语言可以通过优化算法和数据结构,降低网络应用程序的延迟和响应时间,提高网络应用程序的吞吐量,保证网络的快速响应。 3.可移植性:C语言是一种可移植的编程语言,可以在多种平台上进行开发和编译。因此,使用C语言开发网络应用程序能够保证程序在不同的操作系统和硬件平台上都能够正常运行。 4.丰富的库函数:C语言提供了丰富的库函数,可以在网络编程中提供各种功能的支持。比如可以通过各种库函数实现TCP/UDP套接字编程、服务器端编程、客户端编程、线程编程等各种网络编程功能。 总之,C语言在网络编程中具有非常重要的地位。C语言网络编程的特点主要包括底层控制、高效性、可移植性和丰富的库函数。这些特点使得C语言成为网络编程开发者的首选语言之一。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小薛引路

喜欢的读者,可以打赏鼓励一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值