• 基于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数据和参与分析的点判断两点之间可见的路线和不可见的路线;

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

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

    实现代码参考:

    1. void QMapControlExtend::getInterVisibilityTest()
    2. {
    3.     //设置观察点与被观察点
    4.     SituPoint ptView, ptObject;
    5.     ptView.x = 123.69874095387996;
    6.     ptView.y = 41.40071348875932;
    7.     ptObject.x = 123.75503296342102;
    8.     ptObject.y = 41.418647226312224;
    9.     //通过下面的方法首先判断点所在的位置是否存在高程数据;
    10.     UGDatasetRaster* viewPtDataset = getDemDataSet(ptView);
    11.     UGDatasetRaster* objectPtDataset = getDemDataSet(ptObject);
    12.     if(viewPtDataset == NULL || objectPtDataset == NULL)
    13.     {
    14.        QMessageBox::about(NULL,"提示","无高程数据");
    15.        return;//-1
    16.     }
    17.     if(viewPtDataset != objectPtDataset)
    18.     {
    19.       QMessageBox::about(NULL,"提示","观测点与被观测点不属于同一个高程数据集");
    20.        return;//-1
    21.     }
    22.     UGDatasetRaster* datasetvec = viewPtDataset;
    23.     //3D分析分析实例对象
    24.     UG3DAnalyst visAnalsyt;
    25.     UGPoint3D pntView3D,pntObject3D;
    26.     ///高程值需根据x,y查询数据集得到
    27.     ///得到当前测量点的高程值
    28.     /// 1.首先将坐标点转换为栅格数据集对应的行和列
    29.     UGPoint2D ptview2D(ptView.x,ptView.y);
    30.     UGPoint pntviewImg;
    31.     datasetvec->XYToImg(ptview2D,pntviewImg);
    32.     ptView.z = datasetvec->GetValue(pntviewImg.x,pntviewImg.y);
    33.     pntView3D.x = ptView.x;
    34.     pntView3D.y = ptView.y;
    35.     pntView3D.z = ptView.z;
    36.     UGPoint2D ptObject2D(ptObject.x,ptObject.y);
    37.     UGPoint pntObjectImg;
    38.     //坐标点转换为栅格数据集对应的行和列
    39.     datasetvec->XYToImg(ptObject2D,pntObjectImg);
    40.     ptObject.z = datasetvec->GetValue(pntObjectImg.x,pntObjectImg.y);
    41.     pntObject3D.x = ptObject.x;
    42.     pntObject3D.y = ptObject.y;
    43.     pntObject3D.z = ptObject.z;
    44. //进行通视分析查询;
    45.     int ret =  visAnalsyt.InterVisibility(datasetvec,pntView3D,pntObject3D);
    46.     if(ret == true)
    47.          QMessageBox::about(NULL,"analysis","visible");
    48.     else if(ret == false)
    49.          QMessageBox::about(NULL,"analysis","invisible");
    50.     qDebug()<<"InterVisibility test success!"<<endl;
    51.     return ;
    52. }

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

    1. UGDatasetRaster *QMapControlExtend::getDemDataSet(SituPoint pt)
    2.  {
    3.      QList<QString> rasterLayers;
    4.      //得到Layers当前子图层个数,不包括所有子图层的数量
    5.      UGLayers* layers = &(m_pMapEditorWnd->m_mapWnd.m_Map.m_Layers);
    6.      int count = layers->GetTopLevelCount();
    7.      //首先判断是否存在高程数据
    8.      for(int i = 0; i < count; i++){
    9.          //获取指定索引图层
    10.          UGLayer* layer = layers->GetLayerAt(i);
    11.          //获取当前联接的数据集
    12.          UGDataset* pdataset = layer->GetDataset();
    13.          if(pdataset == NULL)
    14.              continue;
    15.          //数据集类型
    16.          UGDataset::DatasetType type = layer->GetDataset()->GetType();
    17.          if(UGDataset::DEM == type || UGDataset::Grid == type)
    18.              rasterLayers.append(Translator::UGStr2QStr(layer->GetName ()));
    19.      }
    20.      if(rasterLayers.isEmpty())
    21.      {
    22.          QMessageBox::about(NULL,"提示","当前地图无高层数据");
    23.          return NULL;
    24.      }
    25.      //annotate by chenx 20220805
    26.      ///判断出当前测量点所属的栅格图层
    27.      UGPoint2D pntView2D(pt.x,pt.y);
    28.      UGDatasetRaster* datasetvec = NULL;
    29.      for(int i = 0; i < rasterLayers.size();i++)
    30.      {
    31.          UGDataset* dataset;
    32.          QString  name = rasterLayers.at(i).split('@').at(0);
    33.          UGString uname = Translator::QStr2UGStr(name);
    34.          UGMap *pMap = &(m_pMapEditorWnd->m_mapWnd.m_Map);
    35.          dataset = pMap->GetWorkspace()->GetDataSource(0)->GetDataset(uname);//获取指定索引处的数据源
    36.          datasetvec = dynamic_cast<UGDatasetRaster*>(dataset);
    37.          if(datasetvec == NULL)
    38.          {
    39.              continue;
    40.          }
    41.          //判断数据集是否已经打开
    42.          if(!datasetvec->IsOpen())
    43.              datasetvec->Open();
    44.          UGRect2D rectBound = datasetvec->GetBounds();
    45.          //若点在矩形中或在矩形边界上,则返回true,否则返回false
    46.          if(!rectBound.PtInRect(pntView2D) /*|| !rectBound.PtInRect(pntObject2D)*/)
    47.          {
    48.              datasetvec = NULL;
    49.              continue;
    50.          }
    51.      }
    52.      return datasetvec;
    53.  }

    关键类: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);

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

     

  • 相关阅读:
    Linux:进程控制
    什么是跨域?跨域问题如何解决?看完豁然开朗。
    精品基于JAVA的医院挂号系统的设计与实现SSM
    Speedoffice(excel)如何快捷隐藏表格内所有空行
    mysql设置主从数据同步(5.7版本)
    Gin vs Beego: Golang的Web框架之争
    Unity 使用Sqlite
    rust学习(手动写一个线程池)
    解决:el-select,el-cascader或el-date-picker的下拉框不随滚动条滚动。
    centos搭建http服务器
  • 原文地址:https://blog.csdn.net/supermapsupport/article/details/127750135