我正在QT应用程序中使用OSGWidget。我如何获取osg viewer中拾取对象的坐标,并将其传输到对话窗口中的QT textEdit中。你能否给出建议如何从查看器中提取选定对象的osg :: Vec3d将其转换为字符串并将其显示出来?例如。我有这些场景: 对象坐标
当我点击添加按钮,它会打开一个对话框窗口,我有一个textEdit对象。在此editText中传输坐标。这怎么可能完成?忘了补充一点,这个多维数据集是从广告文件导入的。可能它可以帮助在任何地方。
我正在QT应用程序中使用OSGWidget。我如何获取osg viewer中拾取对象的坐标,并将其传输到对话窗口中的QT textEdit中。你能否给出建议如何从查看器中提取选定对象的osg :: Vec3d将其转换为字符串并将其显示出来?例如。我有这些场景: 对象坐标
当我点击添加按钮,它会打开一个对话框窗口,我有一个textEdit对象。在此editText中传输坐标。这怎么可能完成?忘了补充一点,这个多维数据集是从广告文件导入的。可能它可以帮助在任何地方。
为了从您的场景中检索对象的坐标,您需要为您的查看器添加新的事件处理程序。我们称之为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的示例数据;只有很多点和使用LineIntersector
(最快)几乎是不可能的。 Polytope
将构建一个与任何指定区域中的任何物体(与构建Polytope
时的参数相交)。另外,您可能需要使用发送到选取功能的参数(如缓冲区大小)进行播放。我使用ea.getXNormalized()
和pick()
和osgUtil::Intersector::PROJECTION
值。
如果您使用的是osgUtil::Intersector::WINDOW
值,则无需对鼠标值进行归一化。如果您在视图中没有任何“奇怪”转换,那么很可能您所需的值就是PROJECTION
。
最后一件事,这段代码太旧了。随着更新的osg
版本,也许一些将被视为已弃用。我不确定,因为我还没有更新我的选择器代码。
现在,通过这段代码,当找到了一个itersection时,它会检索到第一个并通过发射发送点值。你只需要连接这个发射到你的SLOT并接收尖锐的点坐标。
最后,为了将某些东西转换为字符串,可以使用Qt字符串函数QString::number(...)
。
例如:
const QString x = QString::number(point[0], 'd', 6);
将字符串化使用定点格式与6个小数位点的x坐标。
哇!感谢你的例子。我会研究它,并尝试应用到我的项目 – 2014-12-06 18:16:36
好的。我想补充一点,你需要将'osg :: Viewer * viewer'改为'osg :: View * viewer',否则动态转换将不起作用。 – 2016-06-23 09:01:06
@DanielR。感谢您指出!我现在就改变它。 – 2016-06-23 09:35:14