我在拥有OSGWidget的QT应用程序中工作。如何在osg查看器中获取拾取对象的坐标并将其传输到对话窗口中的QT textEdit。你能给出一些建议,如何从查看器中提取所选对象的osg :: Vec3d,将其转换为字符串并显示出来吗?例如。我有这些场景:
当我点击添加按钮时,它会打开一个对话框窗口,其中我有一个textEdit对象。在此editText中传输coords。怎么可能这样呢?忘记添加此多维数据集是从广告文件导入的。可能它可以在任何地方提供帮助。
答案 0 :(得分:2)
为了从场景中检索对象的坐标,您需要向查看器添加新的事件处理程序。我们称之为PickHandler
。
这是一个可以帮助您入门的基本代码。您需要添加“包含”并对其进行修改以满足您的需求。 (请注意,我没有测试过。我是通过“内存”编写的,但如果有任何错误,应该很容易修复。)
<强> PickHandler.h 强>
class PickHandler: public QObject, public osgGA::GUIEventHandler {
Q_OBJECT
public:
PickHandler();
virtual bool handle( const osgGA::GUIEventAdapter& ea,
osgGA::GUIActionAdapter& aa );
signals:
void query( osg::Vec3f );
protected:
virtual ~PickHandler()
{
}
bool pick( const double x, const double y, osgViewer::Viewer* viewer );
private:
bool getPickedPoint( const double x, const double y, float buffer,
osgViewer::Viewer* viewer, osg::Vec3f& point );
};
<强> PickHandler.cpp 强>
PickHandler::PickHandler() : osgGA::GUIEventHandler()
{
}
bool PickHandler::handle( const osgGA::GUIEventAdapter &ea,
osgGA::GUIActionAdapter &aa )
{
osgViewer::View* viewer = dynamic_cast<osgViewer::Viewer*>( &aa );
if( !viewer ) {
return false;
}
switch( ea.getEventType() ) {
default:
break;
case osgGA::GUIEventAdapter::RELEASE: {
if( pick(ea.getXnormalized(), ea.getYnormalized(),
viewer ) )
{
return true;
}
break;
}
}
return false;
}
bool PickHandler::pick( const double x, const double y,
osgViewer::Viewer* viewer )
{
if( !viewer->getSceneData() ) {
return false;
}
osg::Vec3f point;
float buffer = 0.005f;
if( getPickedPoint( x, y, buffer, viewer, point ) ) {
emit query( point );
}
return false;
}
bool PickHandler::getPickedPoint( const double x, const double y, float buffer,
osgViewer::Viewer* viewer,
osg::Vec3f& point )
{
osg::ref_ptr<osgUtil::PolytopeIntersector> intersector( 0 );
try {
intersector = new osgUtil::PolytopeIntersector(
osgUtil::Intersector::PROJECTION,
x - buffer, y - buffer, x + buffer,
y + buffer )
;
} catch( const std::bad_alloc& ) {
return false;
}
// DimZero = check only for points
intersector->setDimensionMask( osgUtil:: PolytopeIntersector::DimZero );
//
intersector->setIntersectionLimit( osgUtil::Intersector::LIMIT_NEAREST );
osgUtil::IntersectionVisitor iv( intersector );
viewer->getCamera()->accept( iv );
if( intersector->containsIntersections() ) {
osgUtil::PolytopeIntersector::Intersection intersection =
*( intersector->getIntersections().begin() )
;
const osg::Vec3f& P = intersection.intersectionPoints[ 0 ];
if( P.isNaN() ) {
return false;
}
point.set( P[ 0 ], P[ 1 ], P[ 2 ] );
return true;
}
return false;
}
我正在使用PolytopeIntersector
,因为我没有任何可靠的模型,比如OSG示例数据中的cessna;只有很多分数并使用LineIntersector
(最快)几乎不可能获得成功。 Polytope
将构建一个与您指定区域中的任何内容相交的截头体积(在构造Polytope
时使用参数)。
此外,您可能需要使用发送到pick功能的参数,例如缓冲区大小。我使用ea.getXNormalized()
和pick()
内osgUtil::Intersector::PROJECTION
值。
如果使用,例如osgUtil::Intersector::WINDOW
值,则无需标准化鼠标值。如果您的视图中没有任何“奇怪”的转换,很可能PROJECTION
值就是您所需要的。
最后,这段代码相当陈旧。对于较新的osg
版本,可能会有一些版本被视为已弃用。我不确定,因为我还没有更新我的选择器代码。
现在,使用此代码,当找到itersection时,它会检索FIRST并通过emit发送点值。你只需要将这个发射器连接到你的SLOT并接收cliked point coords。
最后,要将某些内容转换为字符串,您可以使用Qt字符串函数QString::number(...)
。
例如:
const QString x = QString::number( point[0], 'd', 6 );
将使用带有6位小数的定点格式对点的x-coord进行字符串化。