当前位置: 首页 > news >正文

GIS开发笔记(7)结合osg及osgEarth实现不同高度下的三个圆形区域形成的三维覆盖轮廓区域绘制

一、实现效果
在这里插入图片描述
二、实现原理
输入四个坐标点,第一个点为中心点,第二三四个点分别以中心点与地面垂线所在线上的各自高度水平面的交点为圆心旋转360°进行圆形区域绘制,然后将三个不同高度上的圆形区域进行结合形成三维覆盖区域的轮廓面。
三、参考代码

void GlobeWidget::draw3dCoverageRegion(const osg::ref_ptr<osg::Vec3Array>& points)
{if (!points || points->size() < 4)return;const osg::Vec3d& centerGeo = (*points)[0];osgEarth::GeoPoint geoCenter(osgEarth::SpatialReference::get("wgs84"),centerGeo.x(), centerGeo.y(), centerGeo.z(),osgEarth::ALTMODE_ABSOLUTE);osg::Vec3d centerWorld;geoCenter.toWorld(centerWorld);osg::Vec3d axis = centerWorld;axis.normalize();// === 圆形 ===const int segments = 60;  // 保证每个圆的分段数量一致std::vector<osg::ref_ptr<osg::Vec3Array>> circles;std::vector<int> layerOffsets;int vertexOffset = 0;// 绘制每个圆for (int i = 1; i <= 3; ++i){const osg::Vec3d& ptGeo = (*points)[i];osgEarth::GeoPoint geoPt(osgEarth::SpatialReference::get("wgs84"),ptGeo.x(), ptGeo.y(), ptGeo.z(),osgEarth::ALTMODE_ABSOLUTE);osg::Vec3d ptWorld;geoPt.toWorld(ptWorld);osg::Vec3d radiusVec = ptWorld - centerWorld;osg::ref_ptr<osg::Vec3Array> circlePts = new osg::Vec3Array();// 使用相同的分段数,避免缺口for (int j = 0; j < segments; ++j){double angle = osg::DegreesToRadians(360.0 * j / segments);osg::Matrixd rot = osg::Matrixd::rotate(angle, axis);osg::Vec3d rotated = radiusVec * rot;circlePts->push_back(centerWorld + rotated);}// 绘制当前圆osg::ref_ptr<osg::Geometry> circleGeom = new osg::Geometry();circleGeom->setVertexArray(circlePts);circleGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP, 0, circlePts->size()));osg::ref_ptr<osg::Vec4Array> circleColor = new osg::Vec4Array();circleColor->push_back(osg::Vec4(0.0, 1.0, 0.0, 1.0));circleGeom->setColorArray(circleColor, osg::Array::BIND_OVERALL);osg::ref_ptr<osg::Geode> circleGeode = new osg::Geode();circleGeode->addDrawable(circleGeom);m_userDrawGroup->addChild(circleGeode);circles.push_back(circlePts);layerOffsets.push_back(vertexOffset);vertexOffset += circlePts->size();}// === 轮廓面 ===osg::ref_ptr<osg::Vec3Array> meshVerts = new osg::Vec3Array();osg::ref_ptr<osg::DrawElementsUInt> meshIndices = new osg::DrawElementsUInt(GL_TRIANGLES);// 合并所有圆的顶点for (auto& c : circles){for (auto& pt : *c)meshVerts->push_back(pt);}// 连接每一层圆之间的三角形for (size_t i = 0; i < circles.size() - 1; ++i){const int offset0 = layerOffsets[i];const int offset1 = layerOffsets[i + 1];// 确保每层圆的点数一致const int count = segments;for (int j = 0; j < count - 1; ++j){// 创建三角形meshIndices->push_back(offset0 + j);meshIndices->push_back(offset1 + j);meshIndices->push_back(offset0 + j + 1);meshIndices->push_back(offset0 + j + 1);meshIndices->push_back(offset1 + j);meshIndices->push_back(offset1 + j + 1);}// 最后一个三角形:补全圆的缺口meshIndices->push_back(offset0 + count - 1);meshIndices->push_back(offset1 + count - 1);meshIndices->push_back(offset0);meshIndices->push_back(offset0);meshIndices->push_back(offset1 + count - 1);meshIndices->push_back(offset1);}osg::ref_ptr<osg::Geometry> meshGeom = new osg::Geometry();meshGeom->setVertexArray(meshVerts);meshGeom->addPrimitiveSet(meshIndices);osg::ref_ptr<osg::Vec4Array> meshColor = new osg::Vec4Array();meshColor->push_back(osg::Vec4(1.0, 1.0, 0.0, 0.4));  // 半透明黄色meshGeom->setColorArray(meshColor, osg::Array::BIND_OVERALL);meshGeom->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);meshGeom->getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);meshGeom->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);osg::ref_ptr<osg::Geode> meshGeode = new osg::Geode();meshGeode->addDrawable(meshGeom);m_userDrawGroup->addChild(meshGeode);// === 视角聚焦 ===if (m_osgWidget && m_osgWidget->getOsgViewer()){osgViewer::Viewer* viewer = m_osgWidget->getOsgViewer();osgEarth::Util::EarthManipulator* manip =dynamic_cast<osgEarth::Util::EarthManipulator*>(viewer->getCameraManipulator());if (manip){osgEarth::Viewpoint vp("Focus", centerGeo.x(), centerGeo.y(), centerGeo.z() + 300,0.0, -90.0, 1500.0);manip->setViewpoint(vp, 2.0);}}
}

http://www.mrgr.cn/news/98611.html

相关文章:

  • **Microsoft Certified Professional(MCP)** 认证考试
  • argparse
  • 子函数嵌套的意义——以“颜色排序”为例(Python)
  • Python抽象基类
  • Function Calling是什么?
  • CS5346 - CHARTS: Chart with Point / Bar / Line / Box
  • 神经光子渲染:物理级真实感图像生成——从麦克斯韦方程到深度学习
  • Windows安装Ollama并指定安装路径(默认C盘)
  • Godot学习-创建简单动画
  • RK3568 更换显示logo
  • 人形机器人动作策略 ∼ 人类动作策略
  • 确保连接器后壳高性能互连的完整性
  • 从零到一:网站设计新手如何快速上手?
  • 关于系统架构思考,如何设计实现系统的高可用?
  • Spring Boot一次接口请求涉及的完整执行链路
  • 【Pandas】pandas DataFrame tail
  • 解决靶机分配的 IP 地址与 Kali 机器静态 IP 地址冲突的方法
  • MyBatis 如何使用
  • 实用类题目
  • 【软件工程大系】净室软件工程