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事件时,只有两者的点完全一致,我才认为发生了点选操作,否则则忽略此事件。

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

相关文章推荐

OSGEarth嵌入Qt的QGraphicsView框架(二)

上一篇处理了QGraphicsView的鼠标、按键事件,本篇接着嵌入OSGEarth。 新建一继承自EventAdapter(一)的类GraphicsView,完成OSGEarth的嵌入工作。...

OSG 添加操作器及功能列表

本文参考osgChina官网及FreeSouth《OSG程序设计教程》相关信息 //添加一些操作器       osg::ref_ptr keyswitchManipulator = new o...

OSG第二代文件序列化存储分析

花了两天时间仔细研究了一下array贡献的第二代文件序列化存储,收益颇多。今后将得益于它的很强的可扩展性。通过自身的体验,感觉应该还有很多初学者可能需要花费几个小时才能看透,所以特将自己分析的流程发上...

OSGEarth绘制Geometry:绘圆(二)

功能描述如下: 1. 鼠标点击之处为圆心位置; 2. 以圆心到鼠标move的距离为半径绘圆; 3. 鼠标有点点击结束绘制; 4. 鼠标点击为新的圆心,继续下次绘制。 代码如下:draw...

OSG入门即osgEarth建立一个地球的详细步骤

最近在学习有关osg的知识,刚开始一头雾水,幸好在老师的指导下才茅塞顿开,同时又结合网上的多个资料总结 一下作为一个初学者入门的经验。希望广大初学者少走弯路!   开始osg编程之前要做osg的编...

osgearth介绍

介绍 osgEarth为开发osg应用提供了一个地理空间SDK和地形引擎. osgEarth的目标: 提供基于osg开发3D地理空间应用的支持;直接从数据源可视化地形模型和影像变得更加简单;提供对开...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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