首页 文章

对象坐标

提问于
浏览
1

我正在使用具有OSGWidget的QT应用程序 . 如何在osg查看器中获取拾取对象的坐标并将其传输到对话窗口中的QT textEdit . 你能给出一些建议,如何从查看器中提取所选对象的osg :: Vec3d,将其转换为字符串并显示出来吗?例如 . 我有这样的场景:
Scene

当我点击添加按钮时,它会打开一个对话框窗口,其中我有一个textEdit对象 . 在此editText中传输coords . 怎么可能这样呢?忘记添加此多维数据集是从广告文件导入的 . 可能它可以在任何地方提供帮助 .

1 回答

  • 2

    为了检索对象's coordinates from your scene, you' ll需要向查看器添加新的事件处理程序 . 我们称之为 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 ,因为我没有_1074209的示例数据;只有很多分数并且使用 LineIntersector (最快)几乎不可能获得成功 . Polytope 将构建一个与您指定区域中的任何内容相交的截头体积(在构造 Polytope 时使用参数) .

    此外,您可能需要使用发送到pick功能的参数,例如缓冲区大小 . 我使用 ea.getXNormalized() 并在 pick() 中使用 osgUtil::Intersector::PROJECTION 值 .

    如果你使用_比如 osgUtil::Intersector::WINDOW 值,你在视图中没有"strange"转换,很可能 PROJECTION 值就是你需要的 .

    最后,这段代码相当陈旧 . 对于较新的 osg 版本,可能会有一些版本被视为已弃用 . 我'm not sure as I haven' t更新了我的选择器代码 .

    现在,使用此代码,当找到itersection时,它将检索FIRST并通过emit发送点值 . 你只需将这个 Launcher 连接到你的SLOT并接收cliked point coords .

    最后,为了将某些东西转换为字符串,您可以使用Qt String函数 QString::number(...) .

    例如:

    const QString x = QString::number( point[0], 'd', 6 );
    

    将使用带有6位小数的定点格式对点的x-coord进行字符串化 .

相关问题