前言

osgearth_los示例,创建了模型动画路径、透视的用法。透视的顾名思义:两个点连线,从A到B,视线不被遮挡,则绘制绿色,视线被遮挡的部分,则设置为红色。此示例,加载earth文件时,需要加载地形文件。

执行命令:osgearth_losd.exe earth_image\world.earth

效果

圆形内的飞机,整个圆形,如果被遮挡,则绘制红色,不被遮挡,则绘制绿色。直线连接的两个飞机,从左下角的飞机点向右上角的飞机点看去,当被遮挡后,则后面的线都绘制红色。最下面的两个扫描圆形也是如此。

代码分析

#include <osg/Notify>
#include <osgGA/StateSetManipulator>
#include <osgGA/GUIEventHandler>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgEarth/MapNode>
#include <osgEarth/XmlUtils>
#include <osgEarthUtil/EarthManipulator>
#include <osgEarthUtil/AutoClipPlaneHandler>
#include <osgEarthUtil/LinearLineOfSight>
#include <osgEarthUtil/RadialLineOfSight>
#include <osg/io_utils>
#include <osg/MatrixTransform>
#include <osg/Depth>
#include <osgEarth/TerrainTileNode>
#include <osgEarth/FileUtils>using namespace osgEarth;
using namespace osgEarth::Util;// 运动路径
osg::AnimationPath* createAnimationPath(const GeoPoint& pos, const SpatialReference* mapSRS, float radius, double looptime)
{// set up the animation path osg::AnimationPath* animationPath = new osg::AnimationPath;// 设置动画路径对象animationPath->setLoopMode(osg::AnimationPath::LOOP);// 循环播放模式int numSamples = 40;// 采样点数double delta = osg::PI * 2.0 / (double)numSamples;//Get the center point in geocentric 获取大地测量坐标系下的中心点GeoPoint mapPos = pos.transform(mapSRS);osg::Vec3d centerWorld;mapPos.toWorld( centerWorld );// 是否为投影坐标系bool isProjected = mapSRS->isProjected();// 设置向上向量osg::Vec3d up = isProjected ? osg::Vec3d(0,0,1) : centerWorld;up.normalize();//Get the "side" vector 获取side向量osg::Vec3d side = isProjected ? osg::Vec3d(1,0,0) : up ^ osg::Vec3d(0,0,1);// 时间间隔double time=0.0f;double time_delta = looptime/(double)numSamples;// 第一个位置、第一个旋转矩阵osg::Vec3d firstPosition;osg::Quat firstRotation;for (unsigned int i = 0; i < (unsigned int)numSamples; i++){double angle = delta * (double)i;osg::Quat quat(angle, up );osg::Vec3d spoke = quat * (side * radius);osg::Vec3d end = centerWorld + spoke;                osg::Quat makeUp;makeUp.makeRotate(osg::Vec3d(0,0,1), up);osg::Quat rot = makeUp;animationPath->insert(time,osg::AnimationPath::ControlPoint(end,rot));// 插入时间和控制点if (i == 0){firstPosition = end;firstRotation = rot;}time += time_delta;            }animationPath->insert(time, osg::AnimationPath::ControlPoint(firstPosition, firstRotation));// 插入最后一个点return animationPath;    // 返回路径动画
}// 调用 创建路径动画方法,且将路径动画对象放入 位置矩阵,并为 位置矩阵 设置更新回调
osg::Node* createPlane(osg::Node* node, const GeoPoint& pos, const SpatialReference* mapSRS, double radius, double time)
{osg::MatrixTransform* positioner = new osg::MatrixTransform;positioner->addChild( node );osg::AnimationPath* animationPath = createAnimationPath(pos, mapSRS, radius, time);positioner->setUpdateCallback( new osg::AnimationPathCallback(animationPath, 0.0, 1.0));return positioner;
}// 存储ExtentNode访问器??
class CacheExtentNodeVisitor : public osg::NodeVisitor
{
public:CacheExtentNodeVisitor(GeoExtent& extent):osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN ),_extent(extent){}void apply(osg::Node& node){TerrainTileNode* tile = dynamic_cast<TerrainTileNode*>(&node);if (tile && tile->getKey().valid()){              if (tile->getKey().getExtent().intersects(_extent) && tile->getKey().getLevelOfDetail() < 11){// Set this tile to not expire.tile->setMinimumExpirationTime(DBL_MAX);OE_NOTICE << "Preloading children for " << tile->getKey().str() << std::endl;tile->loadChildren();}}          traverse(node);}GeoExtent _extent;
};int
main(int argc, char** argv)
{osg::ArgumentParser arguments(&argc,argv);osgViewer::Viewer viewer(arguments);// load the .earth file from the command line.osg::ref_ptr<osg::Node> earthNode = osgDB::readNodeFiles( arguments );if (!earthNode.valid()){OE_NOTICE << "Unable to load earth model" << std::endl;return 1;}osg::Group* root = new osg::Group();osgEarth::MapNode * mapNode = osgEarth::MapNode::findMapNode( earthNode.get() );if (!mapNode){OE_NOTICE << "Could not find MapNode " << std::endl;return 1;}osgEarth::Util::EarthManipulator* manip = new EarthManipulator();viewer.setCameraManipulator( manip );root->addChild( earthNode );    //viewer.getCamera()->addCullCallback( new AutoClipPlaneCullCallback(mapNode));osg::Group* losGroup = new osg::Group();losGroup->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);// 渲染方式:透明losGroup->getOrCreateStateSet()->setAttributeAndModes(new osg::Depth(osg::Depth::ALWAYS, 0, 1, false));root->addChild(losGroup);// so we can speak lat/long:const SpatialReference* mapSRS = mapNode->getMapSRS();const SpatialReference* geoSRS = mapSRS->getGeographicSRS();// 地理坐标系//Create a point to point LineOfSightNode.// 创建 可用于显示点对点视线计算的节点losLinearLineOfSightNode* los = new LinearLineOfSightNode(mapNode, GeoPoint(geoSRS, -121.665, 46.0878, 1258.00, ALTMODE_ABSOLUTE),GeoPoint(geoSRS, -121.488, 46.2054, 3620.11, ALTMODE_ABSOLUTE) );losGroup->addChild( los );//Create an editor for the point to point line of sight that allows you to drag the beginning and end points around.//This is just one way that you could manipulator the LineOfSightNode.// 为los添加编辑器LinearLineOfSightEditor* p2peditor = new LinearLineOfSightEditor( los );root->addChild( p2peditor );//Create a relative point to point LineOfSightNode.// 再创建一个比los低一些的 relativeLOSLinearLineOfSightNode* relativeLOS = new LinearLineOfSightNode( mapNode, GeoPoint(geoSRS, -121.2, 46.1, 10, ALTMODE_RELATIVE),GeoPoint(geoSRS, -121.488, 46.2054, 10, ALTMODE_RELATIVE) );losGroup->addChild( relativeLOS );// 为 relativeLOS 添加编辑器LinearLineOfSightEditor* relEditor = new LinearLineOfSightEditor( relativeLOS );root->addChild( relEditor );//Create a RadialLineOfSightNode that allows you to do a 360 degree line of sight analysis.// 可用于显示径向视线计算的节点 radial// radial 允许进行360度视线分析。RadialLineOfSightNode* radial = new RadialLineOfSightNode( mapNode );radial->setCenter( GeoPoint(geoSRS, -121.515, 46.054, 847.604, ALTMODE_ABSOLUTE) );radial->setRadius( 2000 );radial->setNumSpokes( 100 );    // 设置径向视线计算中的轮辐数。losGroup->addChild( radial );// 为 radial 添加编辑器RadialLineOfSightEditor* radialEditor = new RadialLineOfSightEditor( radial );losGroup->addChild( radialEditor );//Create a relative RadialLineOfSightNode that allows you to do a 360 degree line of sight analysis.RadialLineOfSightNode* radialRelative = new RadialLineOfSightNode( mapNode );radialRelative->setCenter( GeoPoint(geoSRS, -121.2, 46.054, 10, ALTMODE_RELATIVE) );radialRelative->setRadius( 3000 );radialRelative->setNumSpokes(60);losGroup->addChild( radialRelative );RadialLineOfSightEditor* radialRelEditor = new RadialLineOfSightEditor( radialRelative );losGroup->addChild( radialRelEditor );//Load a plane model.  添加一个飞机模型 cessna赛斯纳,飞行器公司osg::ref_ptr< osg::Node >  plane = osgDB::readRefNodeFile("../data/cessna.osgb.50,50,50.scale");//Create 2 moving planes 创建两个移动飞机osg::Node* plane1 = createPlane(plane.get(), GeoPoint(geoSRS, -121.656, 46.0935, 4133.06, ALTMODE_ABSOLUTE), mapSRS, 5000, 40);osg::Node* plane2 = createPlane(plane.get(), GeoPoint(geoSRS, -121.321, 46.2589, 1390.09, ALTMODE_ABSOLUTE), mapSRS, 3000, 25);root->addChild( plane1 );root->addChild( plane2 );//Create a LineOfSightNode that will use a LineOfSightTether callback to monitor//the two plane's positions and recompute the LOS when they moveLinearLineOfSightNode* tetheredLOS = new LinearLineOfSightNode( mapNode);losGroup->addChild( tetheredLOS );tetheredLOS->setUpdateCallback( new LineOfSightTether( plane1, plane2 ) );//Create another plane and attach a RadialLineOfSightNode to it using the RadialLineOfSightTetherosg::Node* plane3 = createPlane(plane.get(), GeoPoint(geoSRS, -121.463, 46.3548, 1348.71, ALTMODE_ABSOLUTE), mapSRS, 10000, 5);losGroup->addChild( plane3 );RadialLineOfSightNode* tetheredRadial = new RadialLineOfSightNode( mapNode );tetheredRadial->setRadius( 5000 );//This RadialLineOfSightNode is going to be filled, so set some alpha values for the colors so it's partially transparenttetheredRadial->setFill( true );tetheredRadial->setGoodColor( osg::Vec4(0,1,0,0.3) );tetheredRadial->setBadColor( osg::Vec4(1,0,0,0.3) );tetheredRadial->setNumSpokes( 100 );losGroup->addChild( tetheredRadial );tetheredRadial->setUpdateCallback( new RadialLineOfSightTether( plane3 ) );// 设置视角信息osgEarth::Viewpoint vp;vp.name() = "Mt Ranier";vp.focalPoint()->set(geoSRS, -121.488, 46.2054, 0, ALTMODE_ABSOLUTE);vp.pitch() = -50.0;vp.range() = 100000;manip->setHomeViewpoint( vp );// 设置home视角viewer.setSceneData( root );    // add some stock OSG handlers:viewer.addEventHandler(new osgViewer::StatsHandler());viewer.addEventHandler(new osgViewer::WindowSizeHandler());viewer.addEventHandler(new osgViewer::ThreadingHandler());viewer.addEventHandler(new osgViewer::LODScaleHandler());viewer.addEventHandler(new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()));/*TerrainTileNodeVisitor v;root->accept(v);*/// 下面的节点遍历代码,导致程序容易崩溃,暂时没看出这段代码有什么用,所以先注释掉// GeoPoint center(geoSRS, -121.656, 46.0935, 4133.06, ALTMODE_ABSOLUTE);//GeoExtent extent(geoSRS, center.x() - 0.5, center.y() - 0.5, center.x() + 0.5, center.y() + 0.5);//CacheExtentNodeVisitor v(extent);//root->accept(v);while (!viewer.done()){        viewer.frame();}return 0;
}

osgEarth示例分析——osgearth_los相关推荐

  1. osgEarth示例分析——osgearth_annotation

    前言 本章为osgearth_annotation示例分析,示例中采用osgEarth提供的类,绘制标签.线.billboard.遮盖图.墙等内容. 运行时,在生成的可执行路径下,打开命令框,输入: ...

  2. osgEarth示例分析——osgearth_skyview

    前言 本示例分析osgearth操作深空场景,或者是银河系场景,可以想象人拿着相机站在地球表面上观看天空/银河系的场景. 重点是相机操作器的使用. 在命令框输入执行程序,在data路径下有加载的图,且 ...

  3. osgEarth示例分析——osgearth_manip

    前言 本示例主要演示osgEarth的事件处理的用法,内容比较多,这部分功能也很重要. 输入命令依然采用china-simple.earth的示例,加上了模型,但是模型并没有看到,可能是因为模型没有放 ...

  4. osgEarth示例分析——osgearth_elevation

    前言 osgearth_elevation示例,展示了如何通过点击地球获取不同定义下的高程数据.包括:MSL高程.HAE高程.EGM96高程.点击按钮,可以移除高程图层. MSL高程:是mean se ...

  5. osgEarth示例分析——osgearth_graticule

    前言 本示例最具有借鉴的功能:绘制网格.网格上的文字显示.拾取地球的坐标.在地球网格示例中,可以设置4种网格.执行命令如下: // --geodetic osgearth_graticuled.exe ...

  6. osgEarth示例分析——osgearth_srstest

    前言 osgearth_srstest示例,主要涉及到两个坐标系转换,wgs84→egm96  wgs84→plate-carre wgs84:World Geodetic System 1984,是 ...

  7. osgEarth示例分析——osgearth_eci

    前言 osgearth_eci示例,展示了J2000的天体坐标系和ECEF地固系的转换,绘制坐标系,以及读取卫星参数绘制卫星的功能.绘制卫星轨迹,添加差值效果和未添加差值的效果. 关于卫星两行根数的数 ...

  8. osgEarth示例分析——osgearth_terrainprofile

    前言 osgearth_terrainprofile示例,涉及到一个新的类 TerrainProfileCalculator(地形轮廓计算器类),用来计算两个点连线之间的地形数据.左下角会根据点击的起 ...

  9. osgEarth示例分析——osgearth_features

    前言 osgearth_features示例,主要演示如何通过代码方式加载shp文件,并设置其样式.在执行时,通过不同 的命令,得到不一样的效果. cmd执行命令: // rasterize 光栅化, ...

最新文章

  1. 详细讲解SQL Server索引的性能问题
  2. swoole 1.79 websocket 聊天室 基于swoole_server
  3. TPS(薄板样条) 2D 插值
  4. Java---中国有句俗语叫“三天打鱼两天晒网”。某人从2010年1月1日起开始“三天打鱼两天晒网”,问这个人在以后的某一天中是“打鱼”还是“晒网”。
  5. 进大厂必须掌握的50个微服务面试问题!
  6. MySQL规格列表(硬件优化上限)
  7. python字典_Python 字典
  8. c语言里面你不知道的break与switch,contiune的用法
  9. 进销存库存管理软件哪个好用
  10. 文献检索--系统综述与meta分析
  11. 哈佛结构和冯诺伊曼结构
  12. python 列表根据汉字拼音进行排序 / 查询结果集(列表嵌套字典)根据特定key字段拼音进行整体排序
  13. 新买的硬盘怎么装系统
  14. AndroidStudio简单代码实现BMI计算
  15. 通过js获取PHP设置的cookie(全实例讲解)
  16. AtCoder Beginner Contest 203(Sponsored by Panasonic) D.Pond(二分+二维前缀和)
  17. 手机app测试用例怎么写?手机app测试点有哪些?没有水分,错过绝对后悔
  18. MQ-2烟雾浓度传感器
  19. \begin{itemize} \item如何让每个item顶格
  20. Drawio使用介绍(画图工具)

热门文章

  1. Linux各版本内核下载地址
  2. 最详细的Java入门完整教程,学Java先收藏了
  3. 30.PCIe扫盲——TLP Header详解(一)
  4. 原理 一篇文章通透理解序列号实现原理
  5. 自动化(四)appium真机远程控制和远程群控
  6. Github使用秘籍
  7. cmd 更新 pip版本指令
  8. pycocotools报错 if type(resFile) == str or type(resFile) == unicode: NameError: name ‘unicode‘ is
  9. 统计学中数据分析方法大全
  10. 安卓手机手电筒不见了?