我正在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