• 基于SuperMap iObjects C++之地形凹凸点提取


            在实际项目中,有时候会遇到这样的需求,根据DEM地形数据,我们需要根据某两点的连线,找到经过的所有山顶点凹陷点

            山顶点指哪些在特定邻域分析范围内,该点都比周围点高的区域。凹陷点指哪些在特定邻域分析范围内,该点都比周围点低的区域区域。DEM数据提供了丰富的地形信息,基于DEM数据如何正确有效的提取这些地形特征信息,在数字地形分析中具有重要意义。

            对于客户所遇到的这种需求,下面跟着我一起来看看在SuperMap iObjects c++中,是如何实现吧。

            首先,我们还是需要明确的一点,前期的数据处理,在这里包括dem数据的入库,在程序开发中不是每一次都要进行的操作,也不是具体的业务需求,所以所以我们通常都是使用SuperMap提供的专门用于前期处理数据的iDesktop软件工作进行数据的入库,处理。先在桌面软件中,将数据制作完成,地图配图,保存为工作空间文件(*.smwu),组件开发直接打开数据即可,程序开发只实现业务需求。

    数据准备

    这里,我们首先需要将拿到的DEM地形数据先导入到SuperMap的数据源(*.udb或者*.udbx)中,不管是tif还是其他格式的数据都一样.

    注意:导入的时候,数据类型需要修改为“栅格”,不能按照默认的影像方式导入。     

            关于如何SuperMap iObjects c++环境的部署,以及如何打开数据不清楚的小伙伴,这里可以参考之前的博客:

    环境配置(windows环境VS + Qt):SuperMap iObjects for C++ 入门详解(VS + Qt)_supermapsupport的博客-CSDN博客

    环境配置(windows+MFC):SuperMap iObjects C++之MFC快速入门_supermapsupport的博客-CSDN博客_sumpermap c++配置

    环境配置(Qt Creator):https://blog.csdn.net/supermapsupport/article/details/52609945

    数据源管理:SuperMap iObjects C++之数据源管理_supermapsupport的博客-CSDN博客_supermap怎么打开udb数据源

    好了,程序也建好了,数据也准备好了,下面就一起来看看功能是如何实现的吧:

    1. 、计算山顶点凸点):

    第一步:

    拿到对应的栅格数据,在SuperMap iObjects c++中,栅格数据的对象类型为UGDatasetRaster ;

    第二步:确定需要分析的目标线,我们需要分析的就是从起点到终点的所有途径点,所以我们需要把这个起始点确定好。

    第三步:确定一个分析系数:想要结果的精细度是更精细还是略微粗糙,越精细,分析的点越多,得到的结果越密集,反之,这里,我们把这个分析系数命名为interval;

    完整实现步骤:

    传入参数:

    demDataset:栅格数据集;

    Geoline:待分析的路线;

    Interval:分析系数;

    实现代码参考:

    1. UGPoint2Ds* MMapControl::FindHeightPoint(UGDatasetRaster *demDataset, UGGeoLine *geoline, UGdouble interval)
    2. {
    3.     try {
    4.         UGPoint2Ds *heightPoints=new UGPoint2Ds();
    5.         if(interval==0.0)
    6.         {
    7.             interval=demDataset->GetBounds().Width()/demDataset->GetWidth();
    8.         }
    9.         UGdouble num=geoline->GetLength()/interval;
    10.         for (int i=1;i<num-1;i++) {
    11.             UGdouble distanceBack = num * (i-1);
    12.             UGdouble distanceNow = num * i;
    13.             UGdouble distanceNext = num * (i+1);
    14.             UGPoint2D point2dBack = geoline->FindPointOnLineByDistance(distanceBack);
    15.             UGPoint2D point2dNow = geoline->FindPointOnLineByDistance(distanceNow);
    16.             UGPoint2D point2dNext = geoline->FindPointOnLineByDistance(distanceNext);
    17.             UGPoint pointBack;
    18.             demDataset->XYToGrid(point2dBack,pointBack);
    19.             UGPoint pointNow;
    20.             demDataset->XYToGrid(point2dNow,pointNow);
    21.             UGPoint pointNext;
    22.             demDataset->XYToGrid(point2dNext,pointNext);
    23.             UGdouble heightBack = demDataset->GetValue(pointBack.x, pointBack.y);
    24.             UGdouble heightNow = demDataset->GetValue(pointNow.x, pointNow.y);
    25.             UGdouble heightNext = demDataset->GetValue(pointNext.x, pointNext.y);
    26.             double BN = heightBack - heightNow;
    27.             double NN = heightNow - heightNext;
    28.             if (BN * NN < 0)
    29.             {
    30.                 if (BN < 0)
    31.                 {
    32.                     heightPoints->Add(point2dNow);
    33.                 }
    34.             }
    35.         }
    36.         return heightPoints;
    37.     } catch (double d) {
    38.     }
    39. }

    关键代码分析:

    1、UGdouble num=geoline->GetLength()/interval;

    根据分析系数,求出我们将在线上等距离提取出多少个点进行分析,系数interval越小,分析精细越高,反之。

    2、根据在线上按照等距离查找,找到相连的三个点坐标;

    UGPoint2D point2dBack = geoline->FindPointOnLineByDistance(distanceBack);

    UGPoint2D point2dNow = geoline->FindPointOnLineByDistance(distanceNow);

    UGPoint2D point2dNext = geoline->FindPointOnLineByDistance(distanceNext);

    3、根据demDataset->XYToGrid拿到对应点位在栅格数据集中所处的行列号,结果UGPoint 的x就是所处的行号,y就是所处的列号;

    UGPoint pointBack;

    demDataset->XYToGrid(point2dBack,pointBack);

    UGPoint pointNow;

    demDataset->XYToGrid(point2dNow,pointNow);

    UGPoint pointNext;

    demDataset->XYToGrid(point2dNext,pointNext);

    4、根据栅格数据集GetValue的方法可以分别拿到相连三个点位的高程值;

    UGdouble heightBack = demDataset->GetValue(pointBack.x, pointBack.y);

    UGdouble heightNow = demDataset->GetValue(pointNow.x, pointNow.y);

    UGdouble heightNext = demDataset->GetValue(pointNext.x, pointNext.y);

    5、判断中间那个点是否是转折点;

    double BN = heightBack - heightNow;

    double NN = heightNow - heightNext;

    if (BN * NN < 0)

     {

        if (BN < 0)

         {

              heightPoints->Add(point2dNow);

          }    

    }

    通过简单的数学公式比较,如果三个点所构成的折线,两条线的方向是相反的,并且前面一条线的方向是朝上的(第一个点的高度比第二个点的高度小),那中间那个点就是山顶点,就可以添加到凸点的点集合里面,最后作为结果统一返回。

            2.、计算凹陷点凹点

    计算凹点的实现思路跟上面是一样的,只是最后的数学公式换一下

     if (BN * NN < 0)

    {

        if (BN > 0)

         {

            lowPoints->Add(point2dNow);

          }

    }

    如果三个点所构成的折线,两条线的方向是相反的,并且前面一条线的方向是朝下的(第一个点的高度比第二个点的高度大),那第二个点就是凹陷点,就可以添加到凹点的点集合里面,最后作为结果统一返回。

    下面是一份简单的结果展示,是将返回的结果点分布添加到跟踪图层进行临时展示,其中红色代表凸点,蓝色代表凹点:

    果结果数据需要存储起来,可以参考一下博客,将对象添加到数据集中进行保存,方便后续使用,SuperMap iObjects c++中对数据的增删改查都是通过UGRecordset,这也是一个非常重要,并且使用较多的一个关键类。具体的使用方法,参考之前的博客:

    https://blog.csdn.net/supermapsupport/article/details/111913924

  • 相关阅读:
    lodash源码
    2017 KDD | metapath2vec: Scalable Representation Learning for Heterogeneous
    Vue2 08 了解Vue-cli和Webpack
    django-vue系统报错解决记录
    海上风电应急救援vr模拟安全培训提高企业风险防范能力
    openGauss每日一练第1天 | openGauss数据库状态查看
    可燃气体报警器检定检验:江门工业安全新保障的实践与思考
    QT笔记——vs中的qt项目 可调试源码
    抖音矩阵系统,抖音矩阵系统源码。
    移植freertos到qemu上运行
  • 原文地址:https://blog.csdn.net/supermapsupport/article/details/127749825