OSG获取鼠标点选事件的位置

原创 2015年07月08日 22:13:36

OSG点选操作的思路是从osgGA::GUIEventHandler继承,并重新实现虚函数virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa);。获取到点选信息后,此处我们不进行处理,而是单一的传出去,由外部需要此点选信息的地方进行处理。对于传出信息,我选择了Qt的信号槽操作,因而,在继承osgGA::GUIEventHandler的同时,我们还需要继承QObject。
代码如下:pickhandle.h

class PickHandle : public QObject, public osgGA::GUIEventHandler
{
    Q_OBJECT
public:
    PickHandle(const osgEarth::SpatialReference* srs);
    ~PickHandle();

protected:
    virtual bool handle(const osgGA::GUIEventAdapter& ea,
        osgGA::GUIActionAdapter& aa);

private:
    osg::Vec3d getPos(const osgGA::GUIEventAdapter& ea,
        osgGA::GUIActionAdapter& aa, osg::Vec3d& pos);

signals:
    // 经纬度信息
    void signalPicked(osg::Vec3d pos);
    void signalMoving(osg::Vec3d pos);

    // 世界坐标信息
    void signalPickedXYZ(osg::Vec3d pos);
    void signalMovingXYZ(osg::Vec3d pos);

    void signalRightPicked();

private:
    osg::Vec3d m_vecPostion;
    const osg::EllipsoidModel* m_pEllipsoid;
};

此处提供了世界坐标和经纬度坐标两套信息供外部选择。
实现代码:pickhandle.cpp

PickHandle::PickHandle(const osgEarth::SpatialReference* srs)
{
    m_pEllipsoid = srs->getGeodeticSRS()->getEllipsoid();
}

PickHandle::~PickHandle()
{

}

bool PickHandle::handle(const osgGA::GUIEventAdapter& ea,
    osgGA::GUIActionAdapter& aa)
{
    // 存储经纬度信息
    osg::Vec3d vecPos;
    switch (ea.getEventType())
    {
        // 点击事件
        case osgGA::GUIEventAdapter::PUSH:
        {
            osg::Vec3d pos = getPos(ea, aa, vecPos);
            // 鼠标左键
            if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
            {
                m_vecPostion = pos;
            }
            break;
        }

        // 鼠标移动事件
        case osgGA::GUIEventAdapter::MOVE:
        {
            osg::Vec3d pos = getPos(ea, aa, vecPos);
            emit signalMoving(vecPos);
            emit signalMovingXYZ(pos);
            break;
        }

        // 鼠标释放事件
        case osgGA::GUIEventAdapter::RELEASE:
        {
            osg::Vec3d pos = getPos(ea, aa, vecPos);
            // 鼠标左键
            if (ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
            {
                // 如果释放的点和点击的点同一,则发送单击事件发生的位置
                if (m_vecPostion == pos && m_vecPostion != osg::Vec3d(0, 0, 0))
                {
                    emit signalPicked(vecPos);
                    emit signalPickedXYZ(pos);
                }
            }
            else if (ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON)
            {
                emit signalRightPicked();
            }
            break;
        }
    }

    return false;
}

osg::Vec3d PickHandle::getPos(const osgGA::GUIEventAdapter& ea,
    osgGA::GUIActionAdapter& aa, osg::Vec3d& pos)
{
    pos = osg::Vec3d(0, 0, 0);
    osgViewer::Viewer* pViewer = dynamic_cast<osgViewer::Viewer*>(&aa);
    if (pViewer == NULL)
    {
        return osg::Vec3d(0, 0, 0);
    }
    // 获取当前点
    osgUtil::LineSegmentIntersector::Intersections intersection;
    double x = ea.getX();
    double y = ea.getY();
    pViewer->computeIntersections(ea.getX(), ea.getY(), intersection);
    osgUtil::LineSegmentIntersector::Intersections::iterator iter
        = intersection.begin();
    if (iter != intersection.end())
    {
        m_pEllipsoid->convertXYZToLatLongHeight(
            iter->getWorldIntersectPoint().x(), iter->getWorldIntersectPoint().y(), iter->getWorldIntersectPoint().z(),
            pos.y(), pos.x(), pos.z());
        pos.x() = osg::RadiansToDegrees(pos.x());
        pos.y() = osg::RadiansToDegrees(pos.y());
        return iter->getWorldIntersectPoint();
    }
    return osg::Vec3d(0, 0, 0);
}

我在处理PUSH和RELEASE事件时,只有两者的点完全一致,我才认为发生了点选操作,否则则忽略此事件。

版权声明:本文为博主原创文章,未经博主允许不得转载。

7、osg中响应键盘鼠标事件以及鼠标和键盘编码表

1、首先定义一个类,该类继承与osgGA::GUIEventHandler,在此类中存在一个handle函数,所有的事件都在此函数中进行处理,如下类的代码: //声明类UseEventHandler,...

OSG学习笔记9-处理键盘事件

//处理键盘事件 #include"stdafx.h" #include #include #include #include class KeyboardHandler :public osg...

OSG学习笔记16 - 对点选物体平移(鼠标点选物体)(物体随鼠标移动)(屏幕坐标转世界坐标)

之前的一篇博文是有一篇对点选物体进行平移、缩放旋转。那一篇是很简单的调用了OSG中定义的一些dragger,但这些dragger都有坐标轴或者tapbox等在模型上,与我最近要做的事情的需求不同。网上...

OSG中屏幕坐标和世界坐标的转化

屏幕-------->世界 可以使用osgUtil::SceneView::ProjectWindowIntoObject()来计算 bool SceneView::projectWindowInto...

OSG鼠标选择求交

OSG鼠标选择求交 ////求交方法一:(用WINDOW坐标值,在相机下求交)            //osg::ref_ptr picker = new osgUtil::LineSegmen...

osgEarth坐标转换

oe中的世界坐标系原点在地球中心,x轴向右(指向本初子午面),y轴向屏幕里,z向上,也就是说这里的世界坐标系就是地球空间直角坐标系。所以地球初始显示的时候,正对屏幕的是西半球。 ...

OSG学习笔记24——根据鼠标平移的位置正确设置物体平移量

一直以来都没有将这个平移量设置正确,也没有考虑清楚这个视景体的问题。今天终于弄明白啦。先看图,其实归根结底都是透视投影的原理。 之前计算平移量的时候总是得不到正确的平移,也没有理解到为什么,经过实践...

osgEarth获取经纬度和高程的几种方法

转载自:http://blog.csdn.net/xiaol_deng/article/details/23555249 做osgEarth也有段时间,一直没时间静下心来写些东西,今天就把我...
  • luffv
  • luffv
  • 2014年07月01日 10:40
  • 2104

OSG 与QT 结合

#include #include #include #include #include #include #include #include #include #include...

osg用qt做界面的经验总结。

我编译的OpenSceneGraph的版本是3.0.0,osg关于Qt的样例共有三个:osgQtBrowser,osgQtWidgets,osgviewerQt。前两个是在osg里加qt窗口,显然不符...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:OSG获取鼠标点选事件的位置
举报原因:
原因补充:

(最多只允许输入30个字)