查看: 1548|回复: 2

用osgEarth::Annotation::FeatureNode绘制多边形,经度跨度过大导致出错

[复制链接]

该用户从未签到

发表于 2015-1-16 17:32:53 | 显示全部楼层 |阅读模式
我用osgEarth::Annotation::FeatureNode在地球上绘制多边形,如果边长跨度过大,比如两点的经度在180度左右时,会导致渲染停止,我想这是否是由于计算量太大导致,是否有方法可避免此问题?尤其是当我在鼠标移动(osgGA::GUIEventAdapter::MOVE)中,实时更新,在两点的经度跨越180度时,基本必错。错误在调用osgEarth::Annotation::FeatureNode::init()时。

该用户从未签到

 楼主| 发表于 2015-1-16 17:35:29 | 显示全部楼层
另外我的osg版本是3.1.1,osgEarth版本是2.4.0

该用户从未签到

 楼主| 发表于 2015-1-16 18:13:47 | 显示全部楼层
本帖最后由 anlingbin 于 2015-1-16 18:24 编辑

代码大概是这样:


#include <osgGA/GUIEventHandler>
#include <osgUtil/LineSegmentIntersector>
#include <osgUtil/PolytopeIntersector>
#include <osgViewer/View>
#include <osgEarth/Pickers>
#include <osgEarth/MapNode>
#include <osgEarthAnnotation/FeatureNode>


class PolygonNodeHandler : public osgGA::GUIEventHandler
{
public:
        PolygonNodeHandler(void) {}

        virtual ~PolygonNodeHandler(void) {}

        // 事件处理
        virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
        {
                if (ea.getHandled()) {
                        return false;
                }

                if (!_view.valid()) {
                        _view = dynamic_cast<osgViewer::View*>(&aa);
                        _mapNode = osgEarth::MapNode::findMapNode(_view->getSceneData());
                }

                bool handled = false;

                switch (ea.getEventType())
                {
                case osgGA::GUIEventAdapter:USH:
                        if (ea.getButtonMask() == osgGA::GUIEventAdapter:EFT_MOUSE_BUTTON)
                        {
                                xMouse = ea.getX();
                                yMouse = ea.getY();
                        }
                        break;
                case osgGA::GUIEventAdapter::RELEASE:
                        {
                                if (xMouse == ea.getX() && yMouse == ea.getY())
                                {
                                        osg::Vec3d world;
                                        if (_mapNode->getTerrain()->getWorldCoordsUnderMouse(_view.get(), xMouse, yMouse, world)) {
                                                osgEarth::GeoPoint coordinate;
                                                coordinate.fromWorld(_mapNode->getMapSRS(), world);
                                                addPosition(coordinate);
                                                return true;
                                        }
                                }

                        }
                        break;
                case osgGA::GUIEventAdapter::MOVE:
                        {
                                osg::Vec3d world;
                                if (_mapNode->getTerrain()->getWorldCoordsUnderMouse(_view.get(), ea.getX(), ea.getY(), world)) {
                                        osgEarth::GeoPoint coordinate;
                                        coordinate.fromWorld(_mapNode->getMapSRS(), world);
                                        setPosition(coordinate);
                                        return true;
                                }
                        }
                        break;
                }

                return handled;
        }

        void addPosition(const osgEarth::GeoPoint& pos)
        {
                if (!_polygon.valid()) {
                        _polygon = new osgEarth::Symbology::Polygon();
                        _polygon->push_back(pos.vec3d());
                        _polygon->push_back(pos.vec3d()); // 以两点相同的面模拟一条线段
                }
               
                _polygon->push_back(pos.vec3d());

                if (_polygonNode.valid()) {
                        _polygonNode->init();
                } else {
                        osgEarth::Symbology::Style style;

                        style.getOrCreate<LineSymbol>()->stroke()->color() = Color(Color::Green, 1.0);
                        style.getOrCreate<LineSymbol>()->stroke()->width() = 2.0;
                        style.getOrCreate<olygonSymbol>()->fill()->color()  = Color(Color::Yellow, 0.5);
                        style.getOrCreate<AltitudeSymbol>()->clamping() = AltitudeSymbol::CLAMP_NONE;
                        //style.getOrCreate<AltitudeSymbol>()->technique() = AltitudeSymbol::TECHNIQUE_GPU;

                        _polygonFeature = new osgEarth::Features::Feature(_polygon.get(), _mapNode->getMapSRS(), style);
                        _polygonNode = new osgEarth::Annotation::FeatureNode(_mapNode.get(), _polygonFeature.get(), true);
                        _polygonNode->getOrCreateStateSet()->setRenderBinDetails(11, "RenderBin");
                        _polygonNode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
                        _polygonNode->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
                        //_polygonNode->setDynamic(true);
                        osg::Group* root = dynamic_cast<osg::Group*>(_view->getSceneData());
                        root->addChild(_polygonNode.get());
                }

        }
        void setPosition(const osgEarth::GeoPoint& pos)
        {
                if (_polygon.valid() && _polygon->size() > 1) {

                        _polygon->back() = pos.vec3d();

                        if (_polygonNode.valid()) {
                                // 如果多边形的点距离太远,例如相聚经度180度,可能由于计算量太大,导致渲染停滞,但主要发生在跨越180度时,是否代码问题
                                // 解决方法1、先将节点从其父节点删除,然后另起线程计算,完成后再把该节点添加到其原父节点
                                // 解决方法2、是否可以修改计算代码,加快速度?
                                // 当前采用方法1
                                _polygonNode->init();
                        }
                }

        }


protected:
        float xMouse;
        float yMouse;

        osg::ref_ptr<osgEarth::Symbology::Polygon> _polygon;
        osg::ref_ptr<osgEarth::Features::Feature> _polygonFeature;
        osg::ref_ptr<osgEarth::Annotation::FeatureNode> _polygonNode;

        osg:bserver_ptr<osgEarth::MapNode> _mapNode;
        osg::observer_ptr<osgViewer::View> _view;
};


您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表