GIS开发笔记(5)结合osg及osgEarth实现虚线环形区域绘制

一、实现效果:输入中点坐标点、内圆半径、外圆半径,绘制坐标点所在高度的水平面的两个圆形形成环形区域。

二、实现原理:

创建中心点所在平面的圆形几何体,将其分别挂接到同一个节点上,再将该节点挂接到用户绘制组节点,用户绘制组节点挂接到地球节点。

三、参考代码:

cpp 复制代码
void GlobeWidget::drawAnnularRegion(osg::Vec3d point, double innerRadius, double outerRadius)
{
    osgViewer::Viewer* viewer = m_osgWidget->getOsgViewer();
    if (!viewer) return;

    // 使用 osgEarth 转换经纬度到地球坐标
    osgEarth::GeoPoint geoPoint(osgEarth::SpatialReference::get("wgs84"),
                                point.x(), point.y(), point.z(), osgEarth::ALTMODE_ABSOLUTE);
    osg::Vec3d cartesianCenter;
    geoPoint.toWorld(cartesianCenter);  // 转换为地球坐标系

    // 计算地表法线(从地心指向圆心)
    osg::Vec3d surfaceNormal = cartesianCenter;
    surfaceNormal.normalize();

    // 找到一个与地表法线垂直的向量
    osg::Vec3d rightVector;
    if (std::abs(surfaceNormal.x()) < 0.9) {
        rightVector = osg::Vec3d(1.0, 0.0, 0.0);
    } else {
        rightVector = osg::Vec3d(0.0, 1.0, 0.0);
    }
    rightVector = rightVector - surfaceNormal * (rightVector * surfaceNormal);
    rightVector.normalize();

    // 计算另一个垂直向量
    osg::Vec3d forwardVector = surfaceNormal ^ rightVector;
    forwardVector.normalize();

    // 创建环形区域的几何体
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    osg::ref_ptr<osg::Geometry> geometry = new osg::Geometry;

    // 创建顶点数组
    osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;

    const int numSegments = 36;
    // 存储外圆顶点数量
    int outerVertexCount = 0;
    for (int i = 0; i <= numSegments; ++i) {
        double angle = 2.0 * osg::PI * static_cast<double>(i) / static_cast<double>(numSegments);

        // 计算外圆上的点
        osg::Vec3d outerOffset = rightVector * cos(angle) * outerRadius + forwardVector * sin(angle) * outerRadius;
        osg::Vec3d outerPoint = cartesianCenter + outerOffset;
        vertices->push_back(outerPoint);
        outerVertexCount++;
    }

    for (int i = numSegments; i >= 0; --i) {
        double angle = 2.0 * osg::PI * static_cast<double>(i) / static_cast<double>(numSegments);

        // 计算内圆上的点
        osg::Vec3d innerOffset = rightVector * cos(angle) * innerRadius + forwardVector * sin(angle) * innerRadius;
        osg::Vec3d innerPoint = cartesianCenter + innerOffset;
        vertices->push_back(innerPoint);
    }

    geometry->setVertexArray(vertices.get());

    // 设置颜色(透明填充,仅显示边框)
    osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;
    colors->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 0.0f));
    geometry->setColorArray(colors.get());
    geometry->setColorBinding(osg::Geometry::BIND_OVERALL);

    // 设置外圆图元为线带
    geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, outerVertexCount));
    // 设置内圆图元为线带
    geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, outerVertexCount, vertices->size() - outerVertexCount));

    // 设置虚线样式
    osg::ref_ptr<osg::LineStipple> lineStipple = new osg::LineStipple;
    lineStipple->setFactor(1);
    lineStipple->setPattern(0xAAAA);

    osg::ref_ptr<osg::StateSet> stateSet = geometry->getOrCreateStateSet();
    stateSet->setAttributeAndModes(lineStipple.get(), osg::StateAttribute::ON);
    stateSet->setMode(GL_LINE_STIPPLE, osg::StateAttribute::ON);

    geode->addDrawable(geometry.get());

    // 将 Geode 添加到根节点
    m_userDrawGroup->addChild(geode.get());

    // 强制刷新场景
    viewer->requestRedraw();
}```
相关推荐
Dovis(誓平步青云)9 分钟前
C++ Vector算法精讲与底层探秘:从经典例题到性能优化全解析
开发语言·c++·经验分享·笔记·算法
学游戏开发的2 小时前
Lyra学习笔记 Experience流程梳理
笔记·unreal engine
保持学习ing7 小时前
黑马Java面试笔记之框架篇(Spring、SpringMvc、Springboot)
java·笔记·spring·面试·mvc·mybatis·springboot
超级韩逗逗8 小时前
正则表达式笔记
笔记·正则表达式
love530love8 小时前
【笔记】2025 年 Windows 系统下 abu 量化交易库部署与适配指南
大数据·运维·人工智能·windows·笔记·python·conda
love530love8 小时前
【笔记】为 Python 项目安装图像处理与科学计算依赖(MINGW64 环境)
开发语言·图像处理·人工智能·windows·笔记·python·numpy
子正9 小时前
振动分析师(ISO18436-2)四级能力矩阵 - 简介
笔记·预防性维护·phm·振动分析
·心猿意码·11 小时前
《深度探索C++对象模型》阅读笔记(完整版)
c++·笔记
草莓熊Lotso13 小时前
【C语言预处理详解(下)】--#和##运算符,命名约定,命令行定义 ,#undef,条件编译,头文件的包含,嵌套文件包含,其他预处理指令
c语言·开发语言·经验分享·笔记·其他
love530love13 小时前
【笔记】解决虚拟环境中找不到 chromedriver 的问题
前端·人工智能·笔记·后端·python