osgearth仿真平台之测量工具(2)

发布于:2022-12-02 ⋅ 阅读:(5819) ⋅ 点赞:(5)

测量工具主要是用于测量地球上两点之间的表面距离,空间距离,表面积可空间面积,以及两点之间的可视等。

表面距离测量:

核心代码:

bool GeoGlobe::DistanceMeasureHandler::handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
{    
    if (_Finished)
        return false;

    osgViewer::View* view = static_cast<osgViewer::View*>(aa.asView());                
    if (ea.getEventType() == osgGA::GUIEventAdapter::PUSH && ea.getButton() == _mouseButton)
    {        
        _mouseDown = true;
        _mouseDownX = ea.getX();
        _mouseDownY = ea.getY();

    }
    else if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE && ea.getButton() == _mouseButton)
    {        
        float eps = 1.0f;
        _mouseDown = false;
        if (osg::equivalent(ea.getX(), _mouseDownX, eps) && osg::equivalent(ea.getY(), _mouseDownY, eps))
        {
            double lon, lat;
            if (getLocationAt(view, ea.getX(), ea.getY(), lon, lat))
            {
                if (!_gotFirstLocation)
                {
                    _Finished = false;
                  //  clear();                    
                    _gotFirstLocation = true;
                    _feature->getGeometry()->push_back( osg::Vec3d( lon, lat, 0 ) );
                }
                else
                {
                    if (_lastPointTemporary)
                    {
                        _feature->getGeometry()->back() = osg::Vec3d( lon, lat, 0 );
                        _lastPointTemporary = false;
                    }
                    else
                    {                     
                        _feature->getGeometry()->push_back( osg::Vec3d( lon, lat, 0 ) );
                    }

                    _start = GeoPoint(getMapNode()->getMapSRS(), lon, lat, ALTMODE_ABSOLUTE);

                    _featureNode->init();


                    if (_geoInterpolation == GEOINTERP_GREAT_CIRCLE)
                    {
                        distance = GeoMath::distance(_feature->getGeometry()->asVector());
                    }

                    for (MeasureToolEventHandlerList::const_iterator i = _eventHandlers.begin(); i != _eventHandlers.end(); ++i)
                    {
                        i->get()->onDistanceChanged(this, distance);
                    }

                    std::ostringstream s1;
                    std::ostringstream osm;
                    osm.precision(2);           // 浮点数转换限制  
                    osm.setf(std::ios::fixed); // 将浮点数的位数限定为小数点之后的位数  
                    if (distance > 1000)
                    {
                        osm << distance / 1e3;
                        s1  << osm.str() << "km" << "\n";
                    }
                    else
                    {
                        osm << distance;
                        s1 << osm.str() << "m" << "\n";
                    }

                    std::string na = s1.str();
                    m_SymStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->size() = 18.0f;
                    m_SymStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->fill()->color() = Color::White;
                    m_SymStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->font() = "msyh.ttc";
                    m_SymStyle.getOrCreate<osgEarth::Symbology::TextSymbol>()->encoding() = osgEarth::Symbology::TextSymbol::ENCODING_UTF8;
                    m_ptrLabelNode = new GeoGlobe::Annotation::PlaceNode(_start, na, m_SymStyle);
                    m_ptrLabelNode->setDynamic(true);
                    m_ptrLabelNode->setCullingActive(true);
                    m_ptrGroup->addChild(m_ptrLabelNode);

                    if (_Finished || !_isPath) {
                        _gotFirstLocation = false;
                    }

                    fireDistanceChanged();
                    aa.requestRedraw();
                }
            }
        }
    }  
    else if (ea.getEventType() == osgGA::GUIEventAdapter::DOUBLECLICK) {        
        if (_gotFirstLocation)
        {
            _Finished = true;    
            aa.requestRedraw();

            return true;
        }
    }
    else if (ea.getEventType() == osgGA::GUIEventAdapter::MOVE)
    {
        if (_gotFirstLocation)
        {
            double lon, lat;
            if (getLocationAt(view, ea.getX(), ea.getY(), lon, lat))
            {
                if (!_lastPointTemporary)
                {
                    _feature->getGeometry()->push_back( osg::Vec3d( lon, lat, 0 ) );                 
                    _lastPointTemporary = true;
                }                        
                else
                {
                    _feature->getGeometry()->back() = osg::Vec3d( lon, lat, 0 );
                }
                _featureNode->init();
                fireDistanceChanged();

                aa.requestRedraw();

            }
        }
    }    
    return false;
}

 空间距离测量:

 核心代码:

bool Distance3DTrakerElement::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
    if (m_bIsFinished)
        return false;

    osgViewer::View* view = static_cast<osgViewer::View*>(aa.asView());
    
    int size;
    std::ostringstream s1;
    osgEarth::GeoPoint mapPoint;

    if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE && ea.getButton()== osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
    {
        if (m_isDrag)
        {
            m_isDrag = false;
            return true;
        }

        if (!pick(view, ea, world))
        {
            return false;
            m_isDrag = false;
        }

        //线的起点
        if (m_bIsFirst)
        {        
            m_PickPoints.push_back(world);
            size = m_PickPoints.size();

            RubberBand = createLine(m_PickPoints[m_PickPoints.size() - 1], world, m_PickPoints[0]);
            displayGroup->addChild(RubberBand);

            std::string strText = "start";
            mapPoint.fromWorld(m_mapNode->getTerrain()->getSRS(), world);
            displayGroup->addChild(CreateLabel(m_mapNode, mapPoint, strText));

            m_isDrag = false;
            m_bIsFirst = false;
            return false;
        }
        else
        {
            m_PickPoints.push_back(world);
            size = m_PickPoints.size();
                
            //画线,使用相对位置,再偏移至绝对位置,数值小,线不抖
            osg::Node* ptrLine3D = createLine(m_PickPoints[size - 2], m_PickPoints[size - 1], m_PickPoints[0]);
            displayGroup->addChild(ptrLine3D);

            //计算三维距离
            m_Distance3D += (m_PickPoints[size - 2]- m_PickPoints[size - 1]).length();

            //添加标签,设置有效位        
            s1 << setiosflags(ios::fixed) << setprecision(2) << m_Distance3D << "m" << "\n";
            std::string strText = s1.str();
            mapPoint.fromWorld(m_mapNode->getTerrain()->getSRS(), world);
            displayGroup->addChild(CreateLabel(m_mapNode, mapPoint, strText));

            //删除橡皮筋对象
            displayGroup->removeChild(RubberBand);
            m_isDrag = false;
        }        
        m_isDrag = false;
    }
    else if(ea.getEventType() == osgGA::GUIEventAdapter::MOVE)
    {
        if (!m_bIsFirst)
        {
            if (!pick(view, ea, world))
                return false;
            
            displayGroup->removeChild(RubberBand);
            RubberBand = createLine(m_PickPoints[m_PickPoints.size() - 1], world, m_PickPoints[0]);
            displayGroup->addChild(RubberBand);
        }
    }
    else if(ea.getEventType() == osgGA::GUIEventAdapter::DOUBLECLICK)
    {
        m_isDrag = false;
        m_bIsFinished = true;
        displayGroup->removeChild(RubberBand);
    }
    else if (ea.getEventType() == osgGA::GUIEventAdapter::DRAG)
    {
        m_isDrag = true;
    }
    return false;
}

表面面积:

核心代码:

    bool AreaTrakerElement::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa, osg::Object* object, osg::NodeVisitor* visitor)
    {
        if (m_bFinished)
            return false;

        osgViewer::View* view = static_cast<osgViewer::View*>(aa.asView());
        if (ea.getEventType() == osgGA::GUIEventAdapter::PUSH && ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
        {

        }
        else if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE && ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
        {
            if (m_bIsDrag)
            {
                m_bIsDrag = false;
                return false;
            }

            osg::Vec3d vecWord;
            m_ptrMapNode->getTerrain()->getWorldCoordsUnderMouse(aa.asView(), ea.getX(), ea.getY(), vecWord);
            m_vecWorld.push_back(vecWord);
            osgEarth::GeoPoint mapPoint;
            mapPoint.fromWorld(m_ptrMapNode->getMapSRS(), vecWord);
            m_vecWgs84.push_back(mapPoint.vec3d());
            if (mapPoint.x() < -180 || mapPoint.x() > 180 || mapPoint.y() < -90 || mapPoint.y() > 90 || fabs(mapPoint.z()) > 1000000)
                return false;

            osgEarth::Features::Feature* ptrFeature = m_ptrFeartureNode->getFeature();
            ptrFeature->getGeometry()->push_back(mapPoint.vec3d());
            m_ptrFeartureNode->dirty();

        }
        else if (ea.getEventType() == osgGA::GUIEventAdapter::DOUBLECLICK && ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
        {
            m_bFinished = true;
            Calcuate();
        }
        else if (ea.getEventType() == osgGA::GUIEventAdapter::MOVE)
        {
            osgEarth::Features::Feature* ptrFeature = m_ptrFeartureNode->getFeature();

            if (ptrFeature->getGeometry()->size() == 0)
                return false;

            osg::Vec3d vecWord;
            m_ptrMapNode->getTerrain()->getWorldCoordsUnderMouse(aa.asView(), ea.getX(), ea.getY(), vecWord);
            osgEarth::GeoPoint mapPoint;
            mapPoint.fromWorld(m_ptrMapNode->getMapSRS(), vecWord);

            if (mapPoint.x() < -180 || mapPoint.x() > 180 || mapPoint.y() < -90 || mapPoint.y() > 90 || fabs(mapPoint.z()) > 1000000)
                return false;

            if (ptrFeature->getGeometry()->size() == 1)
                ptrFeature->getGeometry()->push_back(mapPoint.vec3d());
            else
                ptrFeature->getGeometry()->back() = mapPoint.vec3d();

            m_ptrFeartureNode->dirty();
        }
        else if (ea.getEventType() == osgGA::GUIEventAdapter::DRAG)
        {
            m_bIsDrag = true;
        }

        return false;
    }

 空间面积:

核心代码:

bool Area3DTrakerElement::handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
{
    if (m_bIsFinished)
        return false;

    osgViewer::View* view = static_cast<osgViewer::View*>(aa.asView());
    osg::Group* root = static_cast<osg::Group*>(view->getSceneData());
    int size;
    std::ostringstream s1;
    osgEarth::GeoPoint mapPoint;

    if (ea.getEventType() == osgGA::GUIEventAdapter::RELEASE && ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON)
    {
        if (m_isDrag)
        {
            m_isDrag = false;
            return true;
        }

        //线的起点
        if (m_bIsFirst)
        {
            if (!pick(view, ea, world))
                return false;

            m_PickPoints.push_back(world);
            size = m_PickPoints.size();

            /*    
            std::string strText = CodeHelp::String_To_UTF8("起点");
            mapPoint.fromWorld(m_mapNode->getTerrain()->getSRS(), world);
            displayGroup->addChild(CreateLabel(m_mapNode, mapPoint, strText));        
            */

            m_bIsFirst = false;
            m_isDrag = false;
            return false;
        }
        else
        {
            m_PickPoints.push_back(world);
            size = m_PickPoints.size();
            //画线,使用相对位置,再偏移至绝对位置,数值小,线不抖
            osg::Node* ptrLine3D = createLine(m_PickPoints[size - 2], m_PickPoints[size - 1], m_PickPoints[0]);
            displayGroup->addChild(ptrLine3D);
            
            //删除橡皮筋对象
            displayGroup->removeChild(RubberBand);
            displayGroup->removeChild(m_closeRubberBand);
        }
        m_isDrag = false;
    }
    else if (ea.getEventType() == osgGA::GUIEventAdapter::MOVE)
    {
        if (!m_bIsFirst)
        {
            if (!pick(view, ea, world))
                return false;

            displayGroup->removeChild(RubberBand);
            displayGroup->removeChild(m_closeRubberBand);
            RubberBand = createLine(m_PickPoints[m_PickPoints.size() - 1], world, m_PickPoints[0]);

            m_closeRubberBand = createLine(m_PickPoints[0], world, m_PickPoints[0]);
            displayGroup->addChild(RubberBand);
            displayGroup->addChild(m_closeRubberBand);
        }
    }
    else if (ea.getEventType() == osgGA::GUIEventAdapter::DOUBLECLICK)
    {
        //面积闭合
        osg::Node* ptrLine3D = createLine(m_PickPoints[0], m_PickPoints[m_PickPoints.size() - 1], m_PickPoints[0]);
        displayGroup->addChild(ptrLine3D);

        m_isDrag = false;

        //计算三维距离
        //1 三角形剖分
        if (!AreaMeasurement(m_PickPoints, m_Area3D))
            return false;
        2 平面拟合
        //double Area;
        //calArea3D(m_PickPoints,Area);

        //3 直接去掉Z值
        std::vector<osg::Vec2d> Points;
        double area;

        //添加标签,设置有效位
        if (m_Area3D > 100000)
        {
            double showValue = m_Area3D / 1000000;
            s1 << setiosflags(ios::fixed) << setprecision(2) << showValue << "km^2" << "\n";
        }
        else
            s1 << setiosflags(ios::fixed) << setprecision(2) << m_Area3D << "m^2" << "\n";

        osg::Vec3d labelPos;
        for (int i = 0;i<m_PickPoints.size();i++)
        {
            labelPos += m_PickPoints[i];
        }
        labelPos = labelPos / m_PickPoints.size();
        mapPoint.fromWorld(m_mapNode->getTerrain()->getSRS(),labelPos);

        std::string strText = s1.str();
        osgEarth::Symbology::Style style;
        style.getOrCreate<osgEarth::Symbology::TextSymbol>()->size() = 18.0f;
        style.getOrCreate<osgEarth::Symbology::TextSymbol>()->fill()->color() = osgEarth::Symbology::Color::White;
        style.getOrCreate<osgEarth::Symbology::TextSymbol>()->font() = "msyh.ttc";
        style.getOrCreate<osgEarth::Symbology::TextSymbol>()->encoding() = osgEarth::Symbology::TextSymbol::ENCODING_UTF8;
        osg::ref_ptr<GeoGlobe::PlaceName::GeoBillboard> billboard = new GeoGlobe::PlaceName::GeoBillboard(osgEarth::GeoPoint(m_mapNode->getMapSRS(), mapPoint), strText, style, true);
        billboard->setCullingActive(false);

        displayGroup->addChild(/*CreateLabel(m_mapNode, mapPoint, strText)*/billboard);

        m_bIsFinished = true;
        displayGroup->removeChild(RubberBand);
        displayGroup->removeChild(m_closeRubberBand);
    }
    else if (ea.getEventType() == osgGA::GUIEventAdapter::DRAG)
    {
        m_isDrag = true;
    }

    return false;
}

 

本文含有隐藏内容,请 开通VIP 后查看