osgEarth改变投影方式(2D/3D互转),实现二三维数据同步

这篇具有很好参考价值的文章主要介绍了osgEarth改变投影方式(2D/3D互转),实现二三维数据同步。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

项目场景:

想通过osgViewer::CompositeViewer添加同一个.earth文件实现两个View一边显示二维一边显示三维,并且加载的shp之类的数据完全同步。

osgEarth有两种方式构建MapNode,一是通过.earth文件,二是通过代码。

通过代码方式示例如下(官方例子Example osgearth_minimap):

MapNode* makeMiniMapNode( )
{
    Map* map = new Map();
    map->setProfile(Profile::create(Profile::SPHERICAL_MERCATOR));

    // add a semi-transparent XYZ layer:
    XYZImageLayer* osm = new XYZImageLayer();
    //osm->setURL("http://[abc].tile.openstreetmap.org/{z}/{x}/{y}.png");
    osm->setURL("https://gac-geo.googlecnapps.cn/maps/vt?lyrs=y&gl=cn&x={x}&y={y}&z={z}");
    osm->setProfile(Profile::create(Profile::SPHERICAL_MERCATOR));
    map->addLayer(osm);

    TerrainOptions terrainOptions;
    terrainOptions.lodMethod() = TerrainLODMethod::SCREEN_SPACE;

    MapNode::Options mapNodeOptions;
    mapNodeOptions.terrain() = terrainOptions;

    MapNode* mapNode = new MapNode(map, mapNodeOptions);
    mapNode->setEnableLighting(false);

    return mapNode;
}

 通过.earth文件示例如下:

方式1:

通过VS属性管理里调试菜单指定命令参数。

osgearth 2d,osgearth,c++,学习总结,经验分享,c++,3d

//官方示例    
auto node = MapNodeHelper().load( arguments, &viewer );
if (node.valid())
{
    MapNode* mapNode = MapNode::get(node);
        if (!mapNode)
            return -1;
}

 方式2:

直接使用osgDB::readNodeFile()方法进行动态转换。

m_p2DMapNode = dynamic_cast<osgEarth::MapNode*>(osgDB::readNodeFile(strEarthFile));

问题描述

osgearth 2d,osgearth,c++,学习总结,经验分享,c++,3d

通过代码不难看出,通过Map和Layer各自的setProfile方法分别为地图和图层指定投影,不难想象,如果地图和图层的投影方式不一致时会将图层进行重投影。

osgearth 2d,osgearth,c++,学习总结,经验分享,c++,3d

通过.earth文件也是类似,通过<options>参数里的<profile>指定Map的投影,通过<XYZImage name="osm_mapnik">类似节点里的<profile>指定Layer的投影,如果地图和图层的投影方式不一致时会将图层进行重投影。

但是本文要解决的问题,是无论是通过代码还是.earth文件构建MapNode,并且已经构建成功后,如何修改投影,例如MapNode原本是三维现在转换为二维。或者原本是二维转换为三维。

通过代码加载方式的提示可以进行如下操作:

注:原本的MapNode是三维的球

m_p2DMapNode = dynamic_cast<osgEarth::MapNode*>(osgDB::readNodeFile(strEarthFile));
if (m_p2DMapNode)
{
    m_p2DMapNode->getMap()->setProfile(osgEarth::Profile::create(osgEarth::Profile::PLATE_CARREE));
}

结果如下: 

 osgearth 2d,osgearth,c++,学习总结,经验分享,c++,3d

不难看出,代码确实可行,但是其实还有潜藏的问题 。

.earth文件:

<map name="locgis" type="geocentric" version="2" encoding="UTF-8">

    <image driver="gdal">
    <url>./data/world.tif</url>
    <profile>global-geodetic</profile>
    <visible>true</visible>
  </image>
  
<ArcGISServerImage name="World Imagery">
        <url>https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/</url>
        <nodata_image>https://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/100/0/0.jpeg</nodata_image>
    </ArcGISServerImage>

    <ArcGISServerImage name="Transportation" enabled="false">
        <url>https://services.arcgisonline.com/ArcGIS/rest/services/Reference/World_Transportation/MapServer</url>
    </ArcGISServerImage>

    <ArcGISServerImage name="Shaded Relief" enabled="false">
        <url>https://services.arcgisonline.com/arcgis/rest/services/World_Shaded_Relief/MapServer</url>
    </ArcGISServerImage>

    <ArcGISServerElevation name="Elevation layer" max_data_level="13" enabled="true">
        <url>https://services.arcgisonline.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer</url>
    </ArcGISServerElevation>
  
 <model name="buildings" driver="feature_geom">
             
        <features name="buildings" driver="ogr">
            <url>./data/chengdu.shp</url>
            <build_spatial_index>true</build_spatial_index>
        </features>
        
        <layout>
            <tile_size_factor>45</tile_size_factor>
            <level name="default" max_range="20000">
                <selector class="buildings"/>
            </level>
        </layout>
        
        <styles>            
            
            <style type="text/css">
                buildings {
                    extrusion-height:      3.5 * max([Floor], 1);
                    extrusion-flatten:     true;
                    extrusion-wall-style:  building-wall;
					extrusion-wall-gradient: 0.5;
                    extrusion-roof-style:  building-rooftop;
                    altitude-clamping:     terrain;
					altitude-technique:      map;
                    altitude-binding:        vertex;
                }            
                <!-- building-wall { -->
                    <!-- skin-library:     none; -->
                    <!-- skin-tags:        building; -->
                    <!-- skin-random-seed: 1; -->
                    <!-- fill:             #ffffff; -->
                <!-- } -->
                <!-- building-rooftop { -->
                    <!-- skin-library:     none; -->
                    <!-- skin-tags:        rooftop; -->
                    <!-- skin-tiled:       true; -->
                    <!-- skin-random-seed: 1; -->
                    <!-- fill:             #ffffff; -->
                <!-- } -->
            </style>
			
						
		    <!--Exclude certain buildings from being rendered b/c they will be replaced with geospecific buildings -->
			<!-- <selector class="buildings"> -->
                <!-- <query> -->
                    <!-- <expr><![CDATA[ OBJECTID_1 <> 91506 and OBJECTID_1 <> 12921 and OBJECTID_1 <> 11460 and OBJECTID_1 <> 11474 and OBJECTID_1 <> 11471 and OBJECTID_1 <> 11439 and OBJECTID_1 <> 11432 and  OBJECTID_1 <> 91499 and OBJECTID_1 <> 10878 ]]> </expr> -->
                <!-- </query> -->
            <!-- </selector>			 -->
			
        </styles>

        <lighting>false</lighting>        
    </model>
  
  <!-- <elevation driver="tms"> -->
    <!-- <url>./data/12/</url> -->
    <!-- <profile>global-geodetic</profile> -->
	<!-- <visible>true</visible> -->
  <!-- </elevation> -->
  
  <options>
    <!--cache_policy usage="cache_only"/-->
    <cache_policy usage="read_write"/>
    <elevation_tile_size>15</elevation_tile_size>
    
    <terrain>
      <first_lod>2</first_lod>
      <mind_lod>19</mind_lod>
      <min_tile_range_factor>7</min_tile_range_factor>
    </terrain>
    
  </options>
  
</map>

 三维效果:

osgearth 2d,osgearth,c++,学习总结,经验分享,c++,3d

二维效果:

osgearth 2d,osgearth,c++,学习总结,经验分享,c++,3d 使用osgViewer::CompositeViewer同时添加二三维做个对比:

osgearth 2d,osgearth,c++,学习总结,经验分享,c++,3d

 将三维转为二维后.earth下添加的shp文件并没有渲染出来。


原因分析:

Map下添加的Layer的投影并没有改变,即Map的setProfile方法虽然可以改变Map的投影方式但并不会改变其下Layer的投影方式。

 osgEarth源码:

void
Map::setProfile(const Profile* value)
{
    bool notifyLayers = !_profile.valid();

    if (value)
    {
        _profile = value;

        // create a "proxy" profile to use when querying elevation layers with a vertical datum
        if (_profile.valid() && _profile->getSRS()->getVerticalDatum() != 0L )
        {
            ProfileOptions po = _profile->toProfileOptions();
            po.vsrsString().unset();
            _profileNoVDatum = Profile::create(po);
        }
        else
        {
            _profileNoVDatum = _profile;
        }

        // finally, fire an event if the profile has been set.
        OE_INFO << LC << "Map profile is: " << _profile->toString() << std::endl;
    }

    // If we just set the profile, tell all our layers they are now added
    // to a valid map.
    if (_profile.valid() && notifyLayers)
    {
        for(LayerVector::iterator i = _layers.begin(); i != _layers.end(); ++i)
        {
            Layer* layer = i->get();
            if (layer->isOpen())
            {
                layer->addedToMap(this);
            }
        }
    }
}

解决方案:

还是通过代码添加MapNode的提示,把图层重新添加一次,通过添加图层时会对图层重投影来改变Layer的投影。

代码如下:

osgEarth::MapNode* p2DMapNode = dynamic_cast<osgEarth::MapNode*>(osgDB::readNodeFile(strEarthFile));

p2DMapNode->getMap()->setProfile(osgEarth::Profile::create(osgEarth::Profile::PLATE_CARREE));
osgEarth::LayerVector layers;
p2DMapNode->getMap()->getLayers(layers);
for (auto itr : layers)
{
	p2DMapNode->getMap()->removeLayer(itr);
}
p2DMapNode->getMap()->addLayers(layers);

结果展示: 

osgearth 2d,osgearth,c++,学习总结,经验分享,c++,3d

 这样有什么作用呢?就是可以实现二三维加载同一个.earth文件,实现二三维数据同步。

完整代码:

#include <osgDB/ReadFile>
#include <osgEarth/Common>
#include <osgEarth/EarthManipulator>
#include <osgViewer/CompositeViewer>
#include <osgEarth/GLUtils>
#include <osgEarth/Registry>
#include <osgEarth/GeoTransform>

#include <windows.h>

namespace osgEarth
{
	class ImageLayer;
}

const std::string strEarthFile = R"(E:\OSGEarth\osgearth\tests\chengdu_building.earth)";

int main()
{
	osgEarth::initialize();

	osgViewer::CompositeViewer viewer;
	viewer.setThreadingModel(viewer.SingleThreaded);// 设置单线程

	osgViewer::View* p3DView = new osgViewer::View();
	p3DView->getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true, false);
	p3DView->getCamera()->setNearFarRatio(0.00002);

	osgEarth::EarthManipulator* p3DEarthManipulator = new osgEarth::EarthManipulator();
	p3DView->setCameraManipulator(p3DEarthManipulator);
	p3DView->setUpViewInWindow(50, 50, 1600, 800, 0);

	p3DView->getCamera()->setViewport(800, 0, 800, 800);
	p3DView->getCamera()->setProjectionMatrixAsOrtho2D(osgEarth::MERC_MINX, osgEarth::MERC_MAXX, osgEarth::MERC_MINY, osgEarth::MERC_MAXY);

	viewer.addView(p3DView);

	osgViewer::View* p2DView = new osgViewer::View();
	p2DView->getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true, false);
	p2DView->getCamera()->setNearFarRatio(0.00002);
	osgEarth::EarthManipulator* p2DEarthManipulator = new osgEarth::EarthManipulator();
	p2DEarthManipulator->getSettings()->bindMouse(osgEarth::Util::EarthManipulator::ACTION_NULL, osgGA::GUIEventAdapter::MIDDLE_MOUSE_BUTTON, 0);
	p2DView->setCameraManipulator(p2DEarthManipulator);

	p2DView->getCamera()->setViewport(0, 0, 800, 800);
	p2DView->getCamera()->setProjectionMatrixAsOrtho2D(osgEarth::MERC_MINX, osgEarth::MERC_MAXX, osgEarth::MERC_MINY, osgEarth::MERC_MAXY);
	p2DView->getCamera()->setGraphicsContext(p3DView->getCamera()->getGraphicsContext());
	osgEarth::GLUtils::setGlobalDefaults(p3DView->getCamera()->getOrCreateStateSet());
	viewer.addView(p2DView);

	osgEarth::MapNode* p3DMapNode = dynamic_cast<osgEarth::MapNode*>(osgDB::readNodeFile(strEarthFile));
	p3DMapNode->setEnableLighting(false);
	osg::Group* p3MapGroup = new osg::Group;
	p3MapGroup->addChild(p3DMapNode);
	p3DView->setSceneData(p3MapGroup);

	osgEarth::MapNode* p2DMapNode = dynamic_cast<osgEarth::MapNode*>(osgDB::readNodeFile(strEarthFile));

	p2DMapNode->getMap()->setProfile(osgEarth::Profile::create(osgEarth::Profile::PLATE_CARREE));
	osgEarth::LayerVector layers;
	p2DMapNode->getMap()->getLayers(layers);
	for (auto itr : layers)
	{
		p2DMapNode->getMap()->removeLayer(itr);
	}
	p2DMapNode->getMap()->addLayers(layers);

	osg::Group* p2DMapGroup = new osg::Group;
	p2DMapGroup->addChild(p2DMapNode);
	p2DView->setSceneData(p2DMapGroup);

	viewer.run();
}

运行结果:

osgearth 2d,osgearth,c++,学习总结,经验分享,c++,3d

osgearth 2d,osgearth,c++,学习总结,经验分享,c++,3d文章来源地址https://www.toymoban.com/news/detail-838683.html

到了这里,关于osgEarth改变投影方式(2D/3D互转),实现二三维数据同步的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [深入理解NAND Flash (架构篇) ] 3D(三维)NAND图文详解_2D NAND 和 3D NAND 横向对比_VNAND 技术详解

      传送门   总目录  所在专栏   《深入理解SSD》 个人辛苦整理,付费内容,禁止转载。 内容摘要 前言 2.1.4.1. 何为 3D NAND? 2.1.4.2. 3D NAND 技术 2.1.4.

    2024年02月14日
    浏览(37)
  • 【Android App】三维投影OpenGL ES的讲解及着色器实现(附源码和演示 超详细)

    需要源码请点赞关注收藏后评论区留言私信~~~ 虽然OpenGL的三维制图功能非常强大,但是它主要为计算机设计的,对于嵌入式设备和移动端设备来说显得比较臃肿,所以业界又设计了专供嵌入式设备的OpenGL ES 它相当于OpenGL的精简版,因为嵌入式设备追求性价比,所以能不做的

    2024年02月04日
    浏览(49)
  • 探索艺术的新领域——3D线上艺术馆如何改变艺术作品的传播方式

    nbsp;nbsp;nbsp;nbsp;在数字化时代的浪潮下,3D线上艺术馆成为艺术家们展示和传播自己作品的新平台。不仅突破了地域和物理空间的限制,还提供了全新的互动体验。 nbsp;nbsp;nbsp;nbsp;一、无界限的展示空间:艺术家的新展示平台 nbsp;nbsp;nbsp;nbsp;3D线上艺术馆通过数字化技术,为艺

    2024年04月11日
    浏览(47)
  • 2D、3D机器视觉各有优势与局限,融合应用将成工业领域生产新方式

    在智能制造的浪潮中,制造行业生产线亟需转型升级,为国内机器视觉市场释放出了惊人的机器视觉技术及产品需求。在自动化工业质量控制和在线检测领域,2D机器视觉与3D机器视觉都具有重要的作用。那在机器视觉自动化场景中该如何选择合适的机器视觉检测系统进行应用

    2024年02月16日
    浏览(69)
  • Nuscenes——实现世界坐标3D点投影到像素坐标系中

    首先在 mmdetection3d/tools/data_converter/nuscenes_converter.py 中, get_2d_boxes() 可以直接从nuscenes原始sample数据中获取已标注的3D box信息,因此该函数就可以实现整体投影过程。 投影原理 投影过程分为以下几步: 世界坐标系 —— Ego坐标系(自身) 这里需要世界坐标系原点变换到自身的

    2024年02月11日
    浏览(46)
  • 小孔相机模型:世界坐标投影到2D平面

                 

    2024年02月16日
    浏览(37)
  • Open3D 点云投影到拟合平面:Python 实现详解

    Open3D 点云投影到拟合平面:Python 实现详解 点云是指由大量离散的 3D 点组成的几何图形,常常用于工业检测、三维建模等领域。而拟合平面是指在点云数据中找到一个最适合的平面,该平面能够近似地拟合这些点云数据。将点云投影到拟合平面可以方便地进行分析和处理。本

    2024年02月07日
    浏览(49)
  • 三维形体投影面积

    🎈 算法并不一定都是很难的题目,也有很多只是一些代码技巧,多进行一些算法题目的练习,可以帮助我们开阔解题思路,提升我们的逻辑思维能力,也可以将一些算法思维结合到业务代码的编写思考中。简而言之,平时进行的算法习题练习带给我们的好处一定是不少的,

    2024年02月10日
    浏览(40)
  • 使用open3d实现点云在指定视角下的投影

    1.首先获取 点云 : 2.读取外参并生成open3d形式的 相机外参 (我这里读的外参是c2w的) : 3.生成open3d形式的 相机内参 PinholeCameraIntrinsic: 4.初始化PinholeCameraParameters并 赋值 : 5.显示该视角下的点云并 保存图片(手动把窗口关了才会执行下一步) :

    2024年02月07日
    浏览(42)
  • 三维重建之条纹投影结构光(一)

            该系列为条纹投影结构光学习笔记,一共分为四篇。 第一篇记录文献阅读的笔记,对重要知识点进行摘录介绍;第二篇为相位求解和相位展开;第三篇为相高模型的标定;第四篇为重构篇。         本篇以理论知识为主,主要从以下三个方面进行介绍,首先介

    2024年02月02日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包