概述
在一些特定的项目中,我们会遇到一些关于通视分析的需求,通视分析简单来说也可以叫做视线图分析,实质上属于对地形进行最优化处理的范畴。通视分析在航海、航空以及军事方面有重要的应用价值,比如设置雷达站、电视台的发射站、道路选择、航海导航等,在军事上如布设阵地、设置观察哨所、铺设通信线路等;有时还可能对不可见区域进行分析,如低空侦察飞机在飞行时,要尽可能避免敌方雷达的捕捉,飞机要选择雷达盲区飞行等等。
通视分析的基本内容有两个:
- 一个是两点或者多点之间的可视性分析;
- 另一个是可视域分析,即对于给定的观察点,分析观察所覆盖的区域。关于可视域分析,可以参考上一篇博客:插入地址
本博客,我们来重点分析第一种情况。下面就跟着小编一起来看看吧。
一样的,我们需要首先通过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);
分析结果:得到第一个障碍点后,可以根据观察点和目标点去构建两段先对象,然后将结果以不同的颜色显示在地图上,按照人们的使用习惯,绿色标识可见,红色表示不可见。
最后
以上就是爱笑鸭子为你收集整理的基于SuperMap iObjects C++之地形通视分析的全部内容,希望文章能够帮你解决基于SuperMap iObjects C++之地形通视分析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复