基于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的博客-优快云博客

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

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

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

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

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

第一步:

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

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

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

完整实现步骤:

传入参数:

demDataset:栅格数据集;

Geoline:待分析的路线;

Interval:分析系数;

实现代码参考:

UGPoint2Ds* MMapControl::FindHeightPoint(UGDatasetRaster *demDataset, UGGeoLine *geoline, UGdouble interval)

{

    try {

        UGPoint2Ds *heightPoints=new UGPoint2Ds();

        if(interval==0.0)

        {

            interval=demDataset->GetBounds().Width()/demDataset->GetWidth();

        }

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

        for (int i=1;i<num-1;i++) {



            UGdouble distanceBack = num * (i-1);

            UGdouble distanceNow = num * i;

            UGdouble distanceNext = num * (i+1);



            UGPoint2D point2dBack = geoline->FindPointOnLineByDistance(distanceBack);

            UGPoint2D point2dNow = geoline->FindPointOnLineByDistance(distanceNow);

            UGPoint2D point2dNext = geoline->FindPointOnLineByDistance(distanceNext);



            UGPoint pointBack;

            demDataset->XYToGrid(point2dBack,pointBack);

            UGPoint pointNow;

            demDataset->XYToGrid(point2dNow,pointNow);

            UGPoint pointNext;

            demDataset->XYToGrid(point2dNext,pointNext);



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

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

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



            double BN = heightBack - heightNow;

            double NN = heightNow - heightNext;



            if (BN * NN < 0)

            {

                if (BN < 0)

                {

                    heightPoints->Add(point2dNow);

                }

            }

        }

        return heightPoints;

    } catch (double d) {



    }

}

关键代码分析:

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.youkuaiyun.com/supermapsupport/article/details/111913924

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值