基于SuperMap iObjects C++之地形通视分析

        在一些特定的项目中,我们会遇到一些关于通视分析的需求,通视分析简单来说也可以叫做视线图分析,实质上属于对地形进行最优化处理的范畴。通视分析在航海、航空以及军事方面有重要的应用价值,比如设置雷达站、电视台的发射站、道路选择、航海导航等,在军事上如布设阵地、设置观察哨所、铺设通信线路等;有时还可能对不可见区域进行分析,如低空侦察飞机在飞行时,要尽可能避免敌方雷达的捕捉,飞机要选择雷达盲区飞行等等

通视分析的基本内容有两个:

  1. 一个是两点或者多点之间的可视性分析;
  2. 另一个是可视域分析,即对于给定的观察点,分析观察所覆盖的区域。关于可视域分析,可以参考上一篇博客:插入地址

本博客,我们来重点分析第一种情况。下面就跟着小编一起来看看吧。

一样的,我们需要首先通过SuperMap iDesktop来提前准备好数据,首先明确通视分析视基于地形高程数据分析的,所有我们首先需要准备一份地形栅格数据。

数据准备

这里,我们首先需要将拿到的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)、根据DEM数据和参与分析的点判断两点之间是否可见;

(2)、 根据DEM数据和参与分析的点判断两点之间可见的路线和不可见的路线;

两种应用场景使用的接口方法不同,我们下面分开来看:

第一种方案:只返回两点之间是否可见:

实现代码参考:

void QMapControlExtend::getInterVisibilityTest()

{

    //设置观察点与被观察点

    SituPoint ptView, ptObject;

    ptView.x = 123.69874095387996;

    ptView.y = 41.40071348875932;



    ptObject.x = 123.75503296342102;

    ptObject.y = 41.418647226312224;



    //通过下面的方法首先判断点所在的位置是否存在高程数据;

    UGDatasetRaster* viewPtDataset = getDemDataSet(ptView);

    UGDatasetRaster* objectPtDataset = getDemDataSet(ptObject);



    if(viewPtDataset == NULL || objectPtDataset == NULL)

    {

       QMessageBox::about(NULL,"提示","无高程数据");

       return;//-1

    }

    if(viewPtDataset != objectPtDataset)

    {

      QMessageBox::about(NULL,"提示","观测点与被观测点不属于同一个高程数据集");

       return;//-1

    }

    UGDatasetRaster* datasetvec = viewPtDataset;

    //3D分析分析实例对象

    UG3DAnalyst visAnalsyt;

    UGPoint3D pntView3D,pntObject3D;

    ///高程值需根据x,y查询数据集得到

    ///得到当前测量点的高程值

    /// 1.首先将坐标点转换为栅格数据集对应的行和列

    UGPoint2D ptview2D(ptView.x,ptView.y);

    UGPoint pntviewImg;

    datasetvec->XYToImg(ptview2D,pntviewImg);

    ptView.z = datasetvec->GetValue(pntviewImg.x,pntviewImg.y);

    pntView3D.x = ptView.x;

    pntView3D.y = ptView.y;

    pntView3D.z = ptView.z;



    UGPoint2D ptObject2D(ptObject.x,ptObject.y);

    UGPoint pntObjectImg;

    //坐标点转换为栅格数据集对应的行和列

    datasetvec->XYToImg(ptObject2D,pntObjectImg);

    ptObject.z = datasetvec->GetValue(pntObjectImg.x,pntObjectImg.y);

    pntObject3D.x = ptObject.x;

    pntObject3D.y = ptObject.y;

    pntObject3D.z = ptObject.z;



//进行通视分析查询;

    int ret =  visAnalsyt.InterVisibility(datasetvec,pntView3D,pntObject3D);

    if(ret == true)

         QMessageBox::about(NULL,"analysis","visible");

    else if(ret == false)

         QMessageBox::about(NULL,"analysis","invisible");

    qDebug()<<"InterVisibility test success!"<<endl;

    return ;

}

分析之前判断:判断观测点所在位置是否有高程数据集;如果返回的结果不为空,则标识存在,既可以继续进行分析,如果结果为null,则标识点位所在的位置都没有高程数据,就没有分析的必要了。 

UGDatasetRaster *QMapControlExtend::getDemDataSet(SituPoint pt)

 {

     QList<QString> rasterLayers;

     //得到Layers当前子图层个数,不包括所有子图层的数量

     UGLayers* layers = &(m_pMapEditorWnd->m_mapWnd.m_Map.m_Layers);

     int count = layers->GetTopLevelCount();

     //首先判断是否存在高程数据

     for(int i = 0; i < count; i++){

         //获取指定索引图层

         UGLayer* layer = layers->GetLayerAt(i);

         //获取当前联接的数据集

         UGDataset* pdataset = layer->GetDataset();

         if(pdataset == NULL)

             continue;

         //数据集类型

         UGDataset::DatasetType type = layer->GetDataset()->GetType();

         if(UGDataset::DEM == type || UGDataset::Grid == type)

             rasterLayers.append(Translator::UGStr2QStr(layer->GetName ()));

     }

     if(rasterLayers.isEmpty())

     {

         QMessageBox::about(NULL,"提示","当前地图无高层数据");

         return NULL;

     }

     //annotate by chenx 20220805

     ///判断出当前测量点所属的栅格图层

     UGPoint2D pntView2D(pt.x,pt.y);

     UGDatasetRaster* datasetvec = NULL;

     for(int i = 0; i < rasterLayers.size();i++)

     {

         UGDataset* dataset;

         QString  name = rasterLayers.at(i).split('@').at(0);

         UGString uname = Translator::QStr2UGStr(name);

         UGMap *pMap = &(m_pMapEditorWnd->m_mapWnd.m_Map);

         dataset = pMap->GetWorkspace()->GetDataSource(0)->GetDataset(uname);//获取指定索引处的数据源

         datasetvec = dynamic_cast<UGDatasetRaster*>(dataset);

         if(datasetvec == NULL)

         {

             continue;

         }

         //判断数据集是否已经打开

         if(!datasetvec->IsOpen())

             datasetvec->Open();

         UGRect2D rectBound = datasetvec->GetBounds();

         //若点在矩形中或在矩形边界上,则返回true,否则返回false

         if(!rectBound.PtInRect(pntView2D) /*|| !rectBound.PtInRect(pntObject2D)*/)

         {

             datasetvec = NULL;

             continue;

         }

     }

     return datasetvec;

 }

关键类:UG3DAnalyst;

关键方法

int ret =  UG3DAnalyst.InterVisibility(datasetvec,pntView3D,pntObject3D);如果返回true则来表示可见,否则为不可见。

第二种方式:可以得到可见线段和不可见线段;

具体实现的逻辑和上面第一种是一样的,只是最后分析的调用方法不同;具体的就不再重复啰嗦了。

关键类:UG3DAnalyst

关键接口:IsVisible

//两点间的可视性

//! \parampDatasetRaster[in] dem数据

//! \param pntView[in] 观察点

//! \param pntObject[in] 目标点

//! \param dHeight[in] 附加地物高度

//! \return 返回可视性结果 如果可视 返回true,否则 还要返回中间的第一个障碍点

SingleResult* IsVisible(UGDatasetRaster* pDatasetRaster, UGPoint3D pntView, UGPoint3D pntObject, UGdouble dHeight = 0);

分析结果:得到第一个障碍点后,可以根据观察点和目标点去构建两段先对象,然后将结果以不同的颜色显示在地图上,按照人们的使用习惯,绿色标识可见,红色表示不可见。

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值