愿你出走半生,归来仍是少年!
在人机交互中,最常用的就是鼠标。获取鼠标在三维场景中的空间位置是保证交互结果正确的保障。
1.LabelControl
文本标签控件,可方便的添加在场景顶层。
设置编码及字体可正确的显示出中文。
setFont(osgText::readFontFile("Fonts/simhei.ttf"));
setEncoding(osgText::String::ENCODING_UTF8);
	bottomStateLabel = new osgEarth::Util::Controls::LabelControl("底部状态栏", osg::Vec4f(1, 1, 1, 1), 14);
	 
	bottomStateLabel->setHorizAlign(osgEarth::Util::Controls::Control::ALIGN_CENTER);
	bottomStateLabel->setVertAlign(osgEarth::Util::Controls::Control::ALIGN_BOTTOM);
	bottomStateLabel->setBackColor(0, 0, 0, 0.8);
	 
	bottomStateLabel->setFont(osgText::readFontFile("Fonts/simhei.ttf"));
 
	bottomStateLabel->setEncoding(osgText::String::ENCODING_UTF8);
	bottomStateLabel->setPadding(5);
	 
	   
	ref_ptr<osgEarth::Util::Controls::ControlCanvas> canvas = osgEarth::Util::Controls::ControlCanvas::get(this);
	 
	canvas->addControl(bottomStateLabel);2.MousePositionEvenHandler
通过继承osgGA::GUIEventHandler进行实现,仅用于鼠标移动时进行鼠标的空间位置解算。分别解算了鼠标所在的地形位置以及空间位置。
#include "MousePositionEvenHandler.h"
Cv::EventHandlers::MousePositionEvenHandler::MousePositionEvenHandler(MapNode* node, osgEarth::Util::Controls::LabelControl* control)
{
	this->mapNode = node;
	this->label = control;
}
bool Cv::EventHandlers::MousePositionEvenHandler::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
	osgViewer::Viewer* viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
	if (viewer)
	{
		std::string positionStr;
		//鼠标移动
		if (ea.getEventType()==ea.MOVE)
		{
  
			osg::Vec3d world;
			 
			if (mapNode->getTerrain()->getWorldCoordsUnderMouse(aa.asView(), ea.getX(), ea.getY(), world))
			{
				GeoPoint pt;
				pt.fromWorld(mapNode->getMapSRS(), world);
				  
				positionStr.append("  经度:"); 
				positionStr.append(boost::lexical_cast<std::string>(pt.x()));
				positionStr.append("  纬度:"); 
				positionStr.append(boost::lexical_cast<std::string>(pt.y()));
				positionStr.append("  地形高程:");
				positionStr.append(boost::lexical_cast<std::string>(pt.z())); 
			}
			  
			osgUtil::LineSegmentIntersector::Intersections hits;
			if (viewer->computeIntersections(ea.getX(),ea.getY(),hits))
			{
				auto first = hits.begin()->getWorldIntersectPoint();
				GeoPoint pt;
				pt.fromWorld(mapNode->getMapSRS(), first);
				positionStr.append("  交点经度:");
				positionStr.append(boost::lexical_cast<std::string>(pt.x()));
				positionStr.append("  交点纬度:");
				positionStr.append(boost::lexical_cast<std::string>(pt.y()));
				positionStr.append("  交点高程:");
				positionStr.append(boost::lexical_cast<std::string>(pt.z()));
			}
			this->label->setText(positionStr);
		}
		 
		 
	}
	return false;   
}
3.坐标获取原理
一个屏幕坐标通过两种方式获取到的平面位置相差不大,主要集中在高程上。
3.1.地形坐标
通过mapNode->getTerrain()->getWorldCoordsUnderMouse获取屏幕位置在地形中的世界位置,然后转换为空间位置。当场景中有倾斜等地物时,无法捕捉到在倾斜表面作为鼠标的位置。
3.2.空间位置
通过viewer->computeIntersections计算交点位置,当场景中有倾斜等地物时,可捕捉到在倾斜表面的交点作为鼠标的位置。
4.效果
 
 
  下图为地面无地物情况的情况下,两种方式获取的坐标、高程相差很小。
 
 
  下图为地面存在地物(模型)的情况下。两种方式获取的坐标相差很小,但是高程相差很大。一种只是获取到地形高度,一种获取到了模型的顶面高度。
 
 
  



















