四、QT+OSG可视化——优化多窗口逻辑与可视化逻辑

TOSG_CVDCurveMWS项目说明

1 项目介绍

该项目是“三”这篇博客的优化,将多窗口与可视化逻辑进一步优化了,将所有osg窗口相关操作放入OSGWidget类中,所有可视化对象节点位置也清楚表明,给定规则了。
所有的后续手动添加的可绘制体全部放入GenerateDrawable类中,让读者更容易添加自己的可视化对象,同时代码整体逻辑也更清楚,每个类的分工也更容易理解。

该项目是QTOSG_CViewerDCurveMW的升级加精简版本,主要功能如下:

(1)该项目通过CompositeViewer,osg窗口中中间显示主要可视化对象,右下角加入了一个坐标轴,随主对象旋转而旋转,可以清晰的知道对象的旋转角度。

(2)在底部加入日志窗口,可以将后续操作在日志窗口中记录下来。

(3)加入了一个AddLinePointHandler : public osgGA::GUIEventHandler,具体功能是:双击可绘制体时,可以添加顶点和其坐标字体信息,且点之间可以自动连接成线。

(4)添加了可以手动显示与隐层点线字绘制体的操作,以及添加了手动清除点线字的操作。

(5)完善里面多窗口显示的逻辑,及精简优化了代码,更加清晰的知道如何使用,如下:

具体表现:

1)将osg代码全部放入了OSGWidget类中,完成osg窗口创建以及灯光、右下角坐标轴、事件处理器和可视化对象节点的初始化,结构也明确了标了出来,如下所示:

 /**
 * @brief The
 * 1 节点构成:首先场景的根节点是OSGWidget之中的_group,然后往group中添加组节点group(索引位置很重要,暂定这样)
 *  1)添加了双击生成节点的
 *  (前面是_group的索引)
     * _group:
     * {
     *      0-showGroup:(group节点,将所有需要手动添加的可视化物体节点(group或者geode,node)都加在这个下面,方便管理)
     *      1-pNodeLight:(Node,这是灯光节点,装了六个灯光)
     *      2-hudAxes:(Camera,这是右下角固定的三向坐标轴,这是添加的是一个相机节点)
     *      3-pointsgroup:(双击生成点和坐标的可视化对象放这里)
     *      {
     *
     *          0-points(geode,点的节点,其中添加点的绘制体对象)
     *          1-texts(geode,点的坐标文本节点,其中添加文本的可绘制对象)
     *      }
     *      4-linesgroup:(双击生成的线的可视化对象放这里)
     *      {
     *          0-lines(geode,线的节点,其中添加线的绘制体对象)
     *      }
     *
     * }
 *  2)没添加双击生成节点的
 *  (前面是_group的索引)
     * _group:
     * {
     *      0-showGroup:(group节点,将所有需要手动添加的可视化物体节点(group或者geode,node)都加在这个下面,方便管理)
     *      1-pNodeLight:(Node,这是灯光节点,装了六个灯光)
     *      2-hudAxes:(Camera,这是右下角固定的三向坐标轴,这是添加的是一个相机节点)
     * }
 *
 *  补充说明:上面结构顺序千万不能变,如果需要再_group添加新节点也可以,在上面的顺序的最后添加新节点就行。建议可视化对象节点都加在第一个节点下,方便管理
 */

2)完成QTab窗口与OSG窗口(osgWidgetList)之间的绑定,删除更改顺序后也能对应上,同时添加了QTab和osgWidgetList之间的映射,方便用户可以自由更改对应OSG窗口节点、更新绘制体

2 具体介绍

1)主界面搭建(不变)

按照这个框架设置界面,按钮加了两个事件,用来添加可绘制体的;不一定非要按照这个框架,选QWidget组件就行。

2)osg环境

vs MSVC2019+qt5.15+osg3.6.5 (osg是其他版本也可以)

在qt中的.pro文件中添加:

ROOT = D:\SWEnvironment\OSG
 FORMS    += mainwindow.ui
 INCLUDEPATH  += $${ROOT}\include
 LIBS += $${ROOT}\lib\OpenThreadsd.lib
 LIBS += $${ROOT}\lib\osgd.lib
 LIBS += $${ROOT}\lib\osgDBd.lib
 LIBS += $${ROOT}\lib\osgGAd.lib
 LIBS += $${ROOT}\lib\osgQt5d.lib
 LIBS += $${ROOT}\lib\osgTextd.lib
 LIBS += $${ROOT}\lib\osgUtild.lib
 LIBS += $${ROOT}\lib\osgViewerd.lib
 QT += opengl

3)OSGWidget类

所有关于osg的操作全部在这个类下面

OSGWidget类实现了几何对象的旋转、平移、缩放以及键盘事件(上下左右键可以恢复几何对象的上下左右视图),同时添加了双击事件,通过判断点击点处于绘制体之间存在交点与否,来增加点;代码如下:

OSGWidget.h
 
#ifndef OSGWIDGET_H
 #define OSGWIDGET_H
 ​
 #include <QWidget>
 #include <QTimer>
 #include <QTextCursor>
 #include <QTextEdit>
 #include <QString>
 #include <QDebug>
 ​
 #include <osgViewer/CompositeViewer>
 #include <osgQt/GraphicsWindowQt>
 #include <osgViewer/ViewerEventHandlers>
 #include <osgGA/TrackballManipulator>
 #include <osg/LineWidth>
 #include <osg/MatrixTransform>
 #include <osg/Group>
 #include <osgText/Text>
 #include <osg/ShapeDrawable>
 ​
 #include <vector>
 ​
 //qt控件需要在特定的类中初始化
 static QTextEdit* logRestore;//日志窗口
 ​
 //相机矩阵
 static osg::Vec3 position;//视点坐标
 static osg::Vec3 centero;
 static osg::Vec3 up;
 ​
 enum LinesType
 {
     ControlLines,
     BSpineLines
 };
 ​
 static void UpdateLog(QString text)
 {
 ​
     logRestore->insertPlainText(text);
     //保持log文本编辑器在光标的最后一行(自动滚屏)
     logRestore->moveCursor(QTextCursor::End);
 }
 ​
 //显示最佳区间[0.5,0.5,0.5]至[-0.5,-0.5,-0.5]
 /**
  * @brief The
  * 1 节点构成:首先场景的根节点是OSGWidget之中的_group,然后往group中添加组节点group(索引位置很重要,暂定这样)
  *  1)添加了双击生成节点的
  *  (前面是_group的索引)
      * _group:
      * {
      *      0-showGroup:(group节点,将所有需要手动添加的可视化物体节点(group或者geode,node)都加在这个下面,方便管理)
      *      1-pNodeLight:(Node,这是灯光节点,装了六个灯光)
      *      2-hudAxes:(Camera,这是右下角固定的三向坐标轴,这是添加的是一个相机节点)
      *      3-pointsgroup:(双击生成点和坐标的可视化对象放这里)
      *      {
      *
      *          0-points(geode,点的节点,其中添加点的绘制体对象)
      *          1-texts(geode,点的坐标文本节点,其中添加文本的可绘制对象)
      *          ...
      *      }
      *      4-linesgroup:(双击生成的线的可视化对象放这里)
      *      {
      *          0-lines(geode,线的节点,其中添加线的绘制体对象)
      *      }
      *
      * }
  *  2)没添加双击生成节点的
  *  (前面是_group的索引)
      * _group:
      * {
      *      0-showGroup:(group节点,将所有需要手动添加的可视化物体节点(group或者geode,node)都加在这个下面,方便管理)
      *      1-pNodeLight:(Node,这是灯光节点,装了六个灯光)
      *      2-hudAxes:(Camera,这是右下角固定的三向坐标轴,这是添加的是一个相机节点)
      * }
  *
  *  补充说明:上面结构顺序千万不能变,如果需要再_group添加新节点也可以,在上面的顺序的最后添加新节点就行。建议可视化对象节点都加在第一个节点下,方便管理
  */
 class OSGWidget : public QWidget, public osgViewer::CompositeViewer
 {
 public:
     osg::ref_ptr<osg::Group> _group;//根节点
     bool _showPLFlag;//点线字显示标志
 ​
     OSGWidget(QWidget* parent = 0, Qt::WindowFlags f = 0, osgViewer::ViewerBase::ThreadingModel threadingModel = osgViewer::CompositeViewer::SingleThreaded);
 ​
     QWidget* addViewWidget(osgQt::GraphicsWindowQt* gw);
 ​
     osgQt::GraphicsWindowQt* createGraphicsWindow(int x, int y, int w, int h, const std::string& name = "", bool windowDecoration = false);
 ​
     virtual void paintEvent(QPaintEvent* event);
 ​
     osgViewer::Viewer* view;
 ​
     osg::ref_ptr<osg::Geode> makeCoordinate();
     osg::ref_ptr<osg::Node> createLightSource(unsigned int num, const osg::Vec3d &trans, const osg::Vec3d &vecDir);
     void setOsgLight();//设置灯光节点
     void creatHud();//设置右下角坐标轴节点
 ​
     inline void updateShowPLFlag()
     {
         _showPLFlag=!_showPLFlag;
     }
 ​
 protected:
     QTimer _timer;
 };
 ​
 /*******************以下为视角控制函数***********************/
 class ViewSelect : public osgGA::TrackballManipulator
 {
 public:
     ViewSelect() :TrackballManipulator() {}
 ​
 protected:
     bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us){
         switch (ea.getEventType())
         {
         case osgGA::GUIEventAdapter::KEYDOWN:
             moveToView(ea);
             break;
         default:
             break;
         }
 ​
         if (ea.getHandled())
             return false;
 ​
         return   osgGA::StandardManipulator::handle(ea, us);
     }
 ​
 private:
     void moveToView(const osgGA::GUIEventAdapter& ea){
         _thrown = false;
 ​
         home(0.0);                 //this fuction does not trigger redraw
         switch (ea.getKey())
         {
         case osgGA::GUIEventAdapter::KEY_Down:                            //TOP_VIEW :
             this->setRotation(osg::Quat(1.0f, 0.0, 0.0, 0.0));
             UpdateLog("旋转至下视图\n");
             break;
         case osgGA::GUIEventAdapter::KEY_Up:                         //BOTTOM_VIEW :
             this->setRotation(osg::Quat(0.0f, 0.0f, 0.0f, 1.0f));
             UpdateLog("旋转至上视图\n");
             break;
         case osgGA::GUIEventAdapter::KEY_Left:                         // LEFT_VIEW :
             this->setRotation(osg::Quat(1.0f, -1.0, -1.0, 1.0f));
             UpdateLog("旋转至左视图\n");
             break;
         case osgGA::GUIEventAdapter::KEY_Right:                          //RIGHT_VIEW:
             this->setRotation(osg::Quat(1.0f, 1.0f, 1.0f, 1.0f));
             UpdateLog("旋转至右视图\n");
             break;
         case osgGA::GUIEventAdapter::KEY_1:
             this->setRotation(osg::Quat(0.0f,1.0f,1.0f,0.0f));
             UpdateLog("旋转至后视图\n");        // BACK_VIEW:
                 break;
         case osgGA::GUIEventAdapter::KEY_0:
             this->setRotation(osg::Quat(1.0f, 0.0f, 0.0f, 1.0f));
             UpdateLog("旋转至前视图\n");//FRONT_VIEW
             break;
         default:
             break;
         }
 ​
         ea.setHandled(true);           //been handled
     }
 ​
 };
 ​
 class HUDAxis :public osg::Camera
 {
 public:
     HUDAxis(){};
     HUDAxis(HUDAxis const& copy, osg::CopyOp copyOp = osg::CopyOp::SHALLOW_COPY):Camera(copy, copyOp),
         _mainCamera(copy._mainCamera){};
 ​
     META_Node(osg, HUDAxis);
     inline void setMainCamera(Camera* camera) { _mainCamera = camera; }
     virtual void traverse(osg::NodeVisitor& nv){
         double fovy, aspectRatio, vNear, vFar;
         _mainCamera->getProjectionMatrixAsPerspective(fovy, aspectRatio, vNear, vFar);
         //this->setProjectionMatrixAsOrtho(-10.0*aspectRatio, 10.0*aspectRatio, -10.0, 10.0, 2.0, -2.0); //设置投影矩阵,使缩放不起效果
         this->setProjectionMatrixAsOrtho2D(-10.0 * aspectRatio, 10.0 * aspectRatio, -10.0, 10.0);
         osg::Vec3 trans(8.5 * aspectRatio, -8.5, -8.0);
         if (_mainCamera.valid() && nv.getVisitorType() == osg::NodeVisitor::CULL_VISITOR)
         {
             osg::Matrix matrix = _mainCamera->getViewMatrix();//改变视图矩阵,让移动位置固定
             matrix.setTrans(trans);
             this->setViewMatrix(matrix);
         }//if
         osg::Camera::traverse(nv);
     }
 protected:
     virtual ~HUDAxis(){};
     osg::observer_ptr<Camera> _mainCamera;
 };
 ​
 ​
 static std::vector<std::unique_ptr<OSGWidget>> osgWidgetList;//osg显示窗口dynamic_cast<OSGWidget*>(
 ​
 /*******************以下为交互事件函数***********************/
 static osg::ref_ptr<osg::Geode> drawLines(osg::ref_ptr<osg::Vec3Array> a, int index, LinesType linestype = LinesType::BSpineLines)
 {
 ​
     osg::ref_ptr<osg::Group> linegroup = dynamic_cast<osg::Group*>(osgWidgetList[index].get()->_group->getChild(4));
     if (linestype == LinesType::ControlLines && linegroup != nullptr)
         linegroup->removeChild(0, 1U);
     int num = a->getNumElements();
     osg::ref_ptr<osg::Geometry> geomLineStrip = new osg::Geometry;
     geomLineStrip->setVertexArray(a.get());
     geomLineStrip->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, num));
     osg::ref_ptr<osg::Geode> geode = new osg::Geode;
     geode->addDrawable(geomLineStrip);
     return geode;
 }
 ​
 static void AddText(float x, float y, float z, int index)
 {
     osg::ref_ptr<osg::Group> pointsgroup = dynamic_cast<osg::Group*>(osgWidgetList[index].get()->_group->getChild(3));
     osg::ref_ptr<osgText::Text> tx = new  osgText::Text;
     tx->setText("Point: (" + std::to_string(x) + ", " + std::to_string(y) + ", " + std::to_string(z)+")");
     tx->setFont("Fonts/simhei.ttf");
     tx->setAxisAlignment(osgText::Text::SCREEN);
     tx->setCharacterSize(0.02);
     tx->setPosition(osg::Vec3(x + 0.03, y + 0.03, z + 0.03));
     pointsgroup->addChild(tx);
 }
 static void creatPoint(float x, float y, float z, int index)
 {
     osg::ref_ptr<osg::Group> pointsgroup = dynamic_cast<osg::Group*>(osgWidgetList[index].get()->_group->getChild(3));
     osg::ref_ptr<osg::Sphere> pSphereShape = new osg::Sphere(osg::Vec3(x, y, z), 0.003f);
     osg::ref_ptr<osg::ShapeDrawable> pShapeDrawable = new osg::ShapeDrawable(pSphereShape.get());
     pShapeDrawable->setColor(osg::Vec4(1.0, 0.0, 0.0, 1.0));
     osg::ref_ptr<osg::Geode> geode = new osg::Geode();
     geode->addDrawable(pShapeDrawable.get());
     pointsgroup->addChild(geode);
     //qDebug()<<pointsgroup->getNumChildren();
     AddText(x, y, z, index);
 }
 class AddLinePointHandler : public osgGA::GUIEventHandler
 {
 public:
     AddLinePointHandler(int index):_index(index) {
         osg::ref_ptr<osg::Group> points = new osg::Group();
         osg::ref_ptr<osg::Group> lines = new osg::Group();
 ​
         osgWidgetList[index].get()->_group->addChild(points);//是_group的第4个组节点
         osgWidgetList[index].get()->_group->addChild(lines);//是_group的第5个组节点
     }
     ~AddLinePointHandler() {};
     void setIndex(int index){
         _index=index;
     }
 ​
     static bool cmp(const osg::Vec3f& v1, const osg::Vec3f& v2)
     {
         float distance_v1 = (v1 - position).length();
         float distance_v2 = (v2 - position).length();
         return distance_v1 < distance_v2;
     }
 ​
     bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)
     {
         //获取要响应的viewer
         osg::ref_ptr<osgViewer::Viewer> viewer = dynamic_cast<osgViewer::Viewer*>(&aa);
 ​
         if (viewer == NULL)
             return false;
 ​
         //判断事件类型
         switch (ea.getEventType())
         {
         case osgGA::GUIEventAdapter::DOUBLECLICK://双击鼠标添加顶点
             if (ea.getButton() == 1)
             {
                 //创建一个线段交集检测对象
                 osgUtil::LineSegmentIntersector::Intersections intersections;
                 float x = ea.getX();
                 float y = ea.getY();
 ​
                 std::vector<osg::Vec3> pointsToChoose;
 ​
                 osgWidgetList[_index].get()->view->getCamera()->getViewMatrixAsLookAt(position, centero, up);
 ​
                 if (viewer->computeIntersections(x, y, intersections))//没有选中物体
                 {
                     //得到相交交集的交点
                     for (osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
                         hitr != intersections.end();
                         ++hitr)
                         //用emit传递数据
                     {
                         float x_Point = float(hitr->getWorldIntersectPoint().x());
                         float y_Point = float(hitr->getWorldIntersectPoint().y());
                         float z_Point = float(hitr->getWorldIntersectPoint().z());
 ​
                         pointsToChoose.push_back(osg::Vec3(x_Point, y_Point, z_Point));
 ​
                     }
                     //取线组节点及其下的geode的geometry的顶点数据
                     osg::ref_ptr<osg::Group> linesgroup = dynamic_cast<osg::Group*>(osgWidgetList[_index].get()->_group->getChild(4));
                     osg::Geode* childGeode;
                     osg::Geometry* geom;
                     osg::ref_ptr<osg::Vec3Array> linesVertices;
 ​
                     if(linesgroup->getNumChildren()>0){
                         childGeode = dynamic_cast<osg::Geode*>(linesgroup->getChild(0));
                         geom = dynamic_cast<osg::Geometry*>(childGeode->getDrawable(0));
                         linesVertices = dynamic_cast<osg::Vec3Array*>(geom->getVertexArray());
                     }else{//第一次进来并没有添加顶点数组,所以第一次需要单独生成,而不能获取
                         linesVertices = new osg::Vec3Array;
                     }
 ​
                     std::sort(pointsToChoose.begin(), pointsToChoose.end(), cmp);
                     creatPoint(pointsToChoose[0].x(), pointsToChoose[0].y(), pointsToChoose[0].z(), _index);
                     linesVertices->push_back(osg::Vec3f(pointsToChoose[0].x(), pointsToChoose[0].y(), pointsToChoose[0].z()));
                     linesgroup->addChild(drawLines(linesVertices, _index, LinesType::ControlLines));//这一句执行后,linesgroup的孩子数目一直是1,之前的孩子会自动释放,不用担心linesgroup里面添加了很多子节点
                     //qDebug()<<linesgroup->getNumChildren();
                     const QString text = QString("(%1, %2, %3)").arg(pointsToChoose[0].x()).arg(pointsToChoose[0].y()).arg(pointsToChoose[0].z());
                     UpdateLog(QString("添加控制顶点 (%1, %2, %3)\n").arg(pointsToChoose[0].x()).arg(pointsToChoose[0].y()).arg(pointsToChoose[0].z()));
                 }
             }
             break;
 ​
         default:
             break;
         }
 ​
         return false;
     }
 private:
     int _index;
 };
 //清除所有点和线、字体节点
 static void clearPointsAndLines(int index){
 ​
 }
 #endif // OSGWIDGET_H
 ​
OSGWidget.cpp
 
#include "OSGWidget.h"
 #include <QGridLayout>
 #include <QDebug>
 //OSGWidget窗口
 OSGWidget::OSGWidget(QWidget* parent, Qt::WindowFlags f, osgViewer::ViewerBase::ThreadingModel threadingModel) : _showPLFlag(true)
 {
     setThreadingModel(threadingModel);
     _group = new osg::Group;
 ​
     //creatHud();//添加右下角坐标轴节点,第二个节点//这一句放在这个位置会报错
     setKeyEventSetsDone(0);
     QWidget* popupWidget = addViewWidget(createGraphicsWindow(900, 100, 800, 600, "Popup window", true));
     QGridLayout* grid = new QGridLayout;
     grid->addWidget(popupWidget, 0, 0);
     setLayout(grid);
 ​
     connect(&_timer, SIGNAL(timeout()), this, SLOT(update()));
     _timer.start(10);
 ​
     osg::ref_ptr<osg::Group> showGroup = new osg::Group();
     _group->addChild(showGroup);
     setOsgLight();//添加灯光节点,第一个节点
     creatHud();//添加右下角坐标轴节点,第二个节点
 }
 ​
 QWidget* OSGWidget::addViewWidget(osgQt::GraphicsWindowQt* gw)
 {
     view = new osgViewer::Viewer;
     addView(view);
 ​
     osg::Camera* camera = view->getCamera();
     camera->setGraphicsContext(gw);
 ​
     const osg::GraphicsContext::Traits* traits = gw->getTraits();
 ​
     camera->setClearColor(osg::Vec4(0.2, 0.2, 0.4, 1.0));
     camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
     camera->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(traits->width) / static_cast<double>(traits->height), 1.0f, 10000.0f);
     view->addEventHandler(new osgViewer::StatsHandler);
     //view->addEventHandler(new AddLinePointHandler);//添加鼠标事件需要在viewer的run()和rellize()之前
     view->setCameraManipulator(new ViewSelect());
     gw->setTouchEventsEnabled(true);
 ​
     return gw->getGLWidget();
 }
 ​
 osgQt::GraphicsWindowQt* OSGWidget::createGraphicsWindow(int x, int y, int w, int h, const std::string& name, bool windowDecoration)
 {
     osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();
     osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;
     traits->windowName = name;
     traits->windowDecoration = windowDecoration;
     traits->x = x;
     traits->y = y;
     traits->width = w;
     traits->height = h;
     traits->doubleBuffer = true;
     traits->alpha = ds->getMinimumNumAlphaBits();
     traits->stencil = ds->getMinimumNumStencilBits();
     traits->sampleBuffers = ds->getMultiSamples();
     traits->samples = ds->getNumMultiSamples();
 ​
     return new osgQt::GraphicsWindowQt(traits.get());
 }
 ​
 void OSGWidget::paintEvent(QPaintEvent* event)
 {
     frame();
 }
 //创建三个坐标轴
 osg::ref_ptr<osg::Geode> OSGWidget::makeCoordinate()
 {
     osg::ref_ptr<osg::Sphere> pSphereShape = new osg::Sphere(osg::Vec3(0, 0, 0), 0.1f);
     osg::ref_ptr<osg::ShapeDrawable> pShapeDrawable = new osg::ShapeDrawable(pSphereShape.get());
     pShapeDrawable->setColor(osg::Vec4(0.0, 0.0, 0.0, 1.0));
 ​
     //创建保存几何信息的对象
     osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();
 ​
     //创建四个顶点
     osg::ref_ptr<osg::Vec3Array> v = new osg::Vec3Array();
     v->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));
     v->push_back(osg::Vec3(1.0f, 0.0f, 0.0f));
     v->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));
     v->push_back(osg::Vec3(0.0f, 1.0f, 0.0f));
     v->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));
     v->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));
     geom->setVertexArray(v.get());
 ​
 ​
     //为每个顶点指定一种颜色
     osg::ref_ptr<osg::Vec4Array> c = new osg::Vec4Array();
     c->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); //坐标原点为红色
     c->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); //x red
     c->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); //坐标原点为绿色
     c->push_back(osg::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); //y green
     c->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); //坐标原点为蓝色
     c->push_back(osg::Vec4(0.0f, 0.0f, 1.0f, 1.0f)); //z blue
     //如果没指定颜色则会变为黑色
     geom->setColorArray(c.get());
     geom->setColorBinding(osg::Geometry::BIND_PER_VERTEX);
 ​
     //三个轴
     geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 0, 2)); //X
     geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 2, 2)); //Y
     geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES, 4, 2)); //Z
 ​
     osg::ref_ptr<osg::Geode> geode = new osg::Geode();
     //geode->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::ON);
     geode->getOrCreateStateSet()->setAttribute(new osg::LineWidth(3.0), osg::StateAttribute::ON);
 ​
     geode->addDrawable(pShapeDrawable.get());
     geode->addDrawable(geom.get());
 ​
 ​
     return geode;
 }
 ​
 osg::ref_ptr<osg::Node> OSGWidget::createLightSource(unsigned int num, const osg::Vec3d &trans, const osg::Vec3d &vecDir)
 {
     osg::ref_ptr<osg::Light> light = new osg::Light;
     light->setLightNum(num);
     light->setDirection(vecDir);
     osg::ref_ptr<osg::LightSource> lightSource = new osg::LightSource;
     lightSource->setLight(light);
     osg::ref_ptr<osg::MatrixTransform> sourceTrans = new osg::MatrixTransform;
     sourceTrans->setMatrix(osg::Matrix::translate(trans));
     sourceTrans->addChild(lightSource.get());
     return sourceTrans.release();
 }
 ​
 void OSGWidget::setOsgLight()
 {
     /****************************设置上下左右近远六个光源,但是没写阴影*********************************/
     osg::ref_ptr<osg::StateSet> stateset = _group->getOrCreateStateSet();
     stateset->setMode(GL_LIGHTING, osg::StateAttribute::ON);
     stateset->setMode(GL_LIGHT6, osg::StateAttribute::ON);  // GL_LIGHT0是默认光源
     // 设置6个光源 解决光照问题
     osg::Vec3d ptLight;
     osg::Vec3d ptCenter = osg::Vec3d(0, 0, 0);
     double dDis = 200000.0;
     ptLight = ptCenter + osg::Z_AXIS * dDis;
     osg::ref_ptr<osg::Node> pNodeLight = createLightSource(6, ptLight, -osg::Z_AXIS);
     pNodeLight->setName("light0");
     _group->addChild(pNodeLight);//如果有双击加节点操作,这个是第三个节点(node),不然是第一个
 ​
 }
 ​
 void OSGWidget::creatHud()
 {
     osg::ref_ptr<HUDAxis> hudAxes = new HUDAxis;
     hudAxes->addChild(makeCoordinate());
     hudAxes->setMainCamera(view->getCamera());
     hudAxes->setRenderOrder(osg::Camera::POST_RENDER);
     hudAxes->setClearMask(GL_DEPTH_BUFFER_BIT);
     hudAxes->setAllowEventFocus(false);
     hudAxes->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
     hudAxes->setName("hudAxes");
     _group->addChild(hudAxes);//如果有双击加节点操作,这个是第四个节点(Camera),不然是第二个
 }

4)GenerateDrawable类

这是所有自己手动在osg窗口添加可绘制体对象的类,都在这个类中写,主类调用就行(可视化代码不写在主类中了)

GenerateDrawable.h
 
#ifndef GENERATEDRAWABLE_H
 #define GENERATEDRAWABLE_H
 ​
 #include <osg/Group>
 #include <osg/Geode>
 #include <osg/PrimitiveSet>
 #include <osg/Geometry>
 #include <osg/LineWidth>
 ​
 class GenerateDrawable
 {
 public:
     GenerateDrawable();
     osg::ref_ptr<osg::Group> creatDrawPlane();
 ​
     osg::ref_ptr<osg::Geode> createCubeEdgeWireframe();
     osg::ref_ptr<osg::Geode> createGradientPlane(int gridSize, std::vector<float>& attributeValues, osg::ref_ptr<osg::Vec4Array> colors);
 ​
 };
 #endif // GENERATEDRAWABLE_H
GenerateDrawable.cpp
 
#include "generatedrawable.h"
 ​
 GenerateDrawable::GenerateDrawable()
 {
 ​
 }
 ​
 osg::ref_ptr<osg::Group> GenerateDrawable::creatDrawPlane()
 {
     float length=0.5f;
     osg::ref_ptr<osg::Vec3Array> planeVertices = new osg::Vec3Array();
     planeVertices->push_back(osg::Vec3f(length, length, 0.0f));//0
     planeVertices->push_back(osg::Vec3f(length, -length, 0.0f));//1
     planeVertices->push_back(osg::Vec3f(-length, -length, 0.0f));//2
     planeVertices->push_back(osg::Vec3f(-length, length, 0.0f));//3
     planeVertices->push_back(osg::Vec3f(0.0f, length, length));//4
     planeVertices->push_back(osg::Vec3f(0.0f, length, -length));//5
     planeVertices->push_back(osg::Vec3f(0.0f, -length, -length));//6
     planeVertices->push_back(osg::Vec3f(0.0f, -length, length));//7
     planeVertices->push_back(osg::Vec3f(length, 0.0f, length));//8
     planeVertices->push_back(osg::Vec3f(length, 0.0f, -length));//9
     planeVertices->push_back(osg::Vec3f(-length, 0.0f, -length));//10
     planeVertices->push_back(osg::Vec3f(-length, 0.0f, length));//11
 ​
     planeVertices->push_back(osg::Vec3f(length, 0.0f, 0.0f));//12
     planeVertices->push_back(osg::Vec3f(-length, 0.0f, 0.0f));//13
     planeVertices->push_back(osg::Vec3f(0.0f, 0.0f, length));//14
     planeVertices->push_back(osg::Vec3f(0.0f, 0.0f, -length));//15
     planeVertices->push_back(osg::Vec3f(0.0f, length, 0.0f));//16
     planeVertices->push_back(osg::Vec3f(0.0f, -length, 0.0f));//17
 ​
     planeVertices->push_back(osg::Vec3f(0.0f, 0.0f, 0.0f));//18
 ​
     osg::ref_ptr<osg::DrawElementsUInt> planeIndices = new osg::DrawElementsUInt(GL_QUADS, 48);
     //xoy
     (*planeIndices)[0] = 18; (*planeIndices)[1] = 12; (*planeIndices)[2] = 0; (*planeIndices)[3] = 16;
     (*planeIndices)[4] = 18; (*planeIndices)[5] = 12; (*planeIndices)[6] = 1; (*planeIndices)[7] = 17;
     (*planeIndices)[8] = 18; (*planeIndices)[9] = 13; (*planeIndices)[10] = 2; (*planeIndices)[11] = 17;
     (*planeIndices)[12] = 18; (*planeIndices)[13] = 13; (*planeIndices)[14] = 3; (*planeIndices)[15] = 16;
 ​
     //xoz
     (*planeIndices)[16] = 18; (*planeIndices)[17] = 14; (*planeIndices)[18] = 8; (*planeIndices)[19] = 12;
     (*planeIndices)[20] = 18; (*planeIndices)[21] = 14; (*planeIndices)[22] = 11; (*planeIndices)[23] = 13;
     (*planeIndices)[24] = 18; (*planeIndices)[25] = 15; (*planeIndices)[26] = 9; (*planeIndices)[27] = 12;
     (*planeIndices)[28] = 18; (*planeIndices)[29] = 15; (*planeIndices)[30] = 10; (*planeIndices)[31] = 13;
 ​
     //yoz
     (*planeIndices)[32] = 18; (*planeIndices)[33] = 16; (*planeIndices)[34] = 4; (*planeIndices)[35] = 14;
     (*planeIndices)[36] = 18; (*planeIndices)[37] = 16; (*planeIndices)[38] = 5; (*planeIndices)[39] = 15;
     (*planeIndices)[40] = 18; (*planeIndices)[41] = 17; (*planeIndices)[42] = 6; (*planeIndices)[43] = 15;
     (*planeIndices)[44] = 18; (*planeIndices)[45] = 17; (*planeIndices)[46] = 7; (*planeIndices)[47] = 14;
 ​
     osg::ref_ptr<osg::Vec4Array> quadsColors = new osg::Vec4Array;
     quadsColors->push_back(osg::Vec4(0.2, 0.2, 0.2, 1));
     osg::ref_ptr<osg::Geometry> geom_QUADS = new osg::Geometry;
     geom_QUADS->setVertexArray(planeVertices.get());
     geom_QUADS->addPrimitiveSet(planeIndices.get());
     geom_QUADS->setColorArray(quadsColors);
     geom_QUADS->setColorBinding(osg::Geometry::BIND_OVERALL);
 ​
     osg::ref_ptr<osg::DrawElementsUInt> linesIndices = new osg::DrawElementsUInt(GL_LINES, 96);
     //xoy
     (*linesIndices)[0] = 18; (*linesIndices)[1] = 14;
     (*linesIndices)[2] = 14; (*linesIndices)[3] = 8;
     (*linesIndices)[4] = 8; (*linesIndices)[5] = 12;
     (*linesIndices)[6] = 12; (*linesIndices)[7] = 18;
 ​
     (*linesIndices)[8] = 18; (*linesIndices)[9] = 14;
     (*linesIndices)[10] = 14; (*linesIndices)[11] = 11;
     (*linesIndices)[12] = 11; (*linesIndices)[13] = 13;
     (*linesIndices)[14] = 13; (*linesIndices)[15] = 18;
 ​
     (*linesIndices)[16] = 18; (*linesIndices)[17] = 13;
     (*linesIndices)[18] = 13; (*linesIndices)[19] = 2;
     (*linesIndices)[20] = 2; (*linesIndices)[21] = 17;
     (*linesIndices)[22] = 17; (*linesIndices)[23] = 18;
 ​
     (*linesIndices)[24] = 18; (*linesIndices)[25] = 13;
     (*linesIndices)[26] = 13; (*linesIndices)[27] = 3;
     (*linesIndices)[28] = 3; (*linesIndices)[29] = 16;
     (*linesIndices)[30] = 16; (*linesIndices)[31] = 18;
 ​
     //xoz
     (*linesIndices)[32] = 18; (*linesIndices)[33] = 12;
     (*linesIndices)[34] = 12; (*linesIndices)[35] = 0;
     (*linesIndices)[36] = 0; (*linesIndices)[37] = 16;
     (*linesIndices)[38] = 16; (*linesIndices)[39] = 18;
 ​
     (*linesIndices)[40] = 18; (*linesIndices)[41] = 12;
     (*linesIndices)[42] = 12; (*linesIndices)[43] = 1;
     (*linesIndices)[44] = 1; (*linesIndices)[45] = 17;
     (*linesIndices)[46] = 17; (*linesIndices)[47] = 18;
 ​
     (*linesIndices)[48] = 18; (*linesIndices)[49] = 15;
     (*linesIndices)[50] = 15; (*linesIndices)[51] = 9;
     (*linesIndices)[52] = 9; (*linesIndices)[53] = 12;
     (*linesIndices)[54] = 12; (*linesIndices)[55] = 18;
 ​
     (*linesIndices)[56] = 18; (*linesIndices)[57] = 15;
     (*linesIndices)[58] = 15; (*linesIndices)[59] = 10;
     (*linesIndices)[60] = 10; (*linesIndices)[61] = 13;
     (*linesIndices)[62] = 13; (*linesIndices)[63] = 18;
 ​
     //yoz
     (*linesIndices)[64] = 18; (*linesIndices)[65] = 16;
     (*linesIndices)[66] = 16; (*linesIndices)[67] = 4;
     (*linesIndices)[68] = 4; (*linesIndices)[69] = 14;
     (*linesIndices)[70] = 14; (*linesIndices)[71] = 18;
 ​
     (*linesIndices)[72] = 18; (*linesIndices)[73] = 16;
     (*linesIndices)[74] = 16; (*linesIndices)[75] = 5;
     (*linesIndices)[76] = 5; (*linesIndices)[77] = 15;
     (*linesIndices)[78] = 15; (*linesIndices)[79] = 18;
 ​
     (*linesIndices)[80] = 18; (*linesIndices)[81] = 17;
     (*linesIndices)[82] = 17; (*linesIndices)[83] = 6;
     (*linesIndices)[84] = 6; (*linesIndices)[85] = 15;
     (*linesIndices)[86] = 15; (*linesIndices)[87] = 18;
 ​
     (*linesIndices)[88] = 18; (*linesIndices)[89] = 17;
     (*linesIndices)[90] = 17; (*linesIndices)[91] = 7;
     (*linesIndices)[92] = 7; (*linesIndices)[93] = 14;
     (*linesIndices)[94] = 14; (*linesIndices)[95] = 18;
 ​
     osg::ref_ptr<osg::Geometry> geom_lINES = new osg::Geometry;
     geom_lINES->setVertexArray(planeVertices.get());
     geom_lINES->addPrimitiveSet(linesIndices.get());
     osg::ref_ptr<osg::Vec4Array> lineColors = new osg::Vec4Array;
     lineColors->push_back(osg::Vec4(0., 0., 0., 1.));
     geom_lINES->setColorArray(lineColors);
     geom_lINES->setColorBinding(osg::Geometry::BIND_OVERALL);
 ​
     osg::ref_ptr<osg::Group> group = new osg::Group();
     osg::ref_ptr<osg::Geode> geode_QUADS = new osg::Geode();
     geode_QUADS->addDrawable(geom_QUADS.get());
     osg::ref_ptr<osg::Geode> geode_LINES = new osg::Geode();
     geode_LINES->addDrawable(geom_lINES.get());
     group->addChild(geode_QUADS);
     group->addChild(geom_lINES);
     group->setName("DrawPlane");
 ​
     return group;
 }
 ​
 osg::ref_ptr<osg::Geode> GenerateDrawable::createCubeEdgeWireframe()
 {
     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;
 ​
     float size = 0.5f;
 ​
     // 正方体的 8 个顶点
     vertices->push_back(osg::Vec3(-size, -size, -size));
     vertices->push_back(osg::Vec3(size, -size, -size));
     vertices->push_back(osg::Vec3(size, size, -size));
     vertices->push_back(osg::Vec3(-size, size, -size));
     vertices->push_back(osg::Vec3(-size, -size, size));
     vertices->push_back(osg::Vec3(size, -size, size));
     vertices->push_back(osg::Vec3(size, size, size));
     vertices->push_back(osg::Vec3(-size, size, size));
 ​
     osg::ref_ptr<osg::DrawElementsUInt> edges = new osg::DrawElementsUInt(GL_LINES);
 ​
     // 正方体边框的 12 条边
     edges->push_back(0); edges->push_back(1);
     edges->push_back(1); edges->push_back(2);
     edges->push_back(2); edges->push_back(3);
     edges->push_back(3); edges->push_back(0);
 ​
     edges->push_back(4); edges->push_back(5);
     edges->push_back(5); edges->push_back(6);
     edges->push_back(6); edges->push_back(7);
     edges->push_back(7); edges->push_back(4);
 ​
     edges->push_back(0); edges->push_back(4);
     edges->push_back(1); edges->push_back(5);
     edges->push_back(2); edges->push_back(6);
     edges->push_back(3); edges->push_back(7);
 ​
     geometry->setVertexArray(vertices);
     geometry->addPrimitiveSet(edges);
 ​
     // 设置边框颜色为白色
     osg::ref_ptr<osg::Vec4Array> edgeColors = new osg::Vec4Array;
     edgeColors->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));
     geometry->setColorArray(edgeColors, osg::Array::BIND_OVERALL);
 ​
     // 设置线宽
     osg::ref_ptr<osg::LineWidth> lineWidth = new osg::LineWidth(1.6f); // 线宽
     geometry->getOrCreateStateSet()->setAttributeAndModes(lineWidth, osg::StateAttribute::ON);
 ​
     geode->addDrawable(geometry);
     return geode;
 }
 //颜色映射函数
 // 随机生成的属性值范围
 const float ATTRIBUTE_MIN = 0.0f;
 const float ATTRIBUTE_MAX = 500.0f;
 osg::Vec4 mapValueToColor(float value)
 {
     float normalized = (value - ATTRIBUTE_MIN) / (ATTRIBUTE_MAX - ATTRIBUTE_MIN);  // 将值归一化到 [0, 1]
 ​
     if (normalized <= 0.2f)  // 红到黄
         return osg::Vec4(1.0f, normalized / 0.2f, 0.0f, 1.0f);
     else if (normalized <= 0.4f)  // 黄到绿
         return osg::Vec4(1.0f - (normalized - 0.2f) / 0.2f, 1.0f, 0.0f, 1.0f);
     else if (normalized <= 0.6f)  // 绿到青
         return osg::Vec4(0.0f, 1.0f, (normalized - 0.4f) / 0.2f, 1.0f);
     else if (normalized <= 0.8f)  // 青到蓝
         return osg::Vec4(0.0f, 1.0f - (normalized - 0.6f) / 0.2f, 1.0f, 1.0f);
     else  // 蓝色
         return osg::Vec4(0.0f, 0.0f, 1.0f - (normalized - 0.8f) / 0.2f, 1.0f);
 }
 ​
 osg::ref_ptr<osg::Geode> GenerateDrawable::createGradientPlane(int gridSize, std::vector<float> &attributeValues, osg::ref_ptr<osg::Vec4Array> colors)
 {
     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;
 ​
     geometry->setUseDisplayList(false);            // 禁用 Display List
     geometry->setUseVertexBufferObjects(true);     // 启用 VBO
 ​
     float size = 1.0f;
     float step = size / gridSize;
 ​
     // 创建平面上的点和颜色
     for (int i = 0; i <= gridSize; ++i)
     {
         for (int j = 0; j <= gridSize; ++j)
         {
             float x = -size / 2 + i * step;
             float y = -size / 2 + j * step;
             float z = 0.0f;
 ​
             vertices->push_back(osg::Vec3(x, y, z));
 ​
             // 为每个点生成一个随机属性值
             float attributeValue = ATTRIBUTE_MIN + static_cast<float>(rand()) / RAND_MAX * (ATTRIBUTE_MAX - ATTRIBUTE_MIN);
             attributeValues.push_back(attributeValue);  // 存储属性值
             colors->push_back(mapValueToColor(attributeValue));  // 将属性值映射到颜色
         }
     }
 ​
     // 创建平面上的矩形图元
     for (int i = 0; i < gridSize; ++i)
     {
         for (int j = 0; j < gridSize; ++j)
         {
             int idx0 = i * (gridSize + 1) + j;
             int idx1 = idx0 + 1;
             int idx2 = idx0 + (gridSize + 1);
             int idx3 = idx2 + 1;
 ​
             osg::ref_ptr<osg::DrawElementsUInt> quad = new osg::DrawElementsUInt(GL_QUADS);
             quad->push_back(idx0);
             quad->push_back(idx1);
             quad->push_back(idx3);
             quad->push_back(idx2);
 ​
             geometry->addPrimitiveSet(quad);
         }
     }
     geometry->setVertexArray(vertices);
     geometry->setColorArray(colors, osg::Array::BIND_PER_VERTEX);  // 每个顶点有单独的颜色
 ​
     geode->addDrawable(geometry);
     return geode;
 }

5)主类-MainWindow类

主类——调用OSGWidget类添加osg窗口,同时调用GenerateDrawable类添加可视化对象

MainWindow.h
 
#ifndef MAINWINDOW_H
 #define MAINWINDOW_H
 ​
 #include <QMainWindow>
 ​
 #include "osgwidget.h"
 ​
 #include "generatedrawable.h"
 QT_BEGIN_NAMESPACE
 namespace Ui { class MainWindow; }
 QT_END_NAMESPACE
 ​
 //static OSGWidget* osgWidget;//osg显示窗口
 ​
 ​
 class MainWindow : public QMainWindow
 {
     Q_OBJECT
 ​
 public:
     MainWindow(QWidget *parent = nullptr);
     ~MainWindow();
 ​
     void initLog();//初始化日志
 ​
     void createOsgWindows(int index);//创建窗口,
     void createOsgWindowsAddPoints(int index);//创建窗口,同时给可绘制体添加操作,双击可绘制体可以添加点和坐标信息,点会自动连接成线
     void addTabOsgWidget(int index, QString wname);//增加Tab窗口,将osg窗口放入Tab中
 ​
 private slots:
     void on_tabWidget_tabCloseRequested(int index);
 ​
     void on_pushButton_clicked();
 ​
     void on_pushButton_2_clicked();
 ​
     void on_pBOA1_clicked();
 ​
     void on_pBOA2_clicked();
 ​
     void on_pBO1_clicked();
 ​
     void on_pBO2_clicked();
 ​
     void on_pBO3_clicked();
 ​
 private:
     Ui::MainWindow *ui;
     std::map<std::string, int> osgToIndexMap;
     GenerateDrawable* _generateDrawable;
 ​
 };
 ​
 #endif // MAINWINDOW_H
MainWindow.cpp
 
#include "mainwindow.h"
 #include "ui_mainwindow.h"
 ​
 #include <QDebug>
 ​
 ​
 MainWindow::MainWindow(QWidget *parent)
     : QMainWindow(parent)
     , ui(new Ui::MainWindow)
 {
     ui->setupUi(this);
     ui->tabWidget->clear();
     _generateDrawable=new GenerateDrawable();
     initLog();
 ​
     ui->pBO1->setEnabled(false);
     ui->pBO2->setEnabled(false);
     ui->pBO3->setEnabled(false);
     ui->pBO4->setEnabled(false);
     ui->pBOA1->setEnabled(false);
     ui->pBOA2->setEnabled(false);
 }
 ​
 MainWindow::~MainWindow()
 {
     delete ui;
 }
 ​
 void MainWindow::initLog()
 {
     //初始化日志窗口
     logRestore = new QTextEdit();
     ui->tabWidget->setTabsClosable(true);
     //日志窗口填充文字编辑
     logRestore->setReadOnly(true);
     ui->bottomDockWidget->setWidget(logRestore);
 }
 ​
 ​
 void MainWindow::createOsgWindows(int index)
 {
     OSGWidget* osgOne = new OSGWidget(0, Qt::Widget, osgViewer::ViewerBase::SingleThreaded);
     osg::ref_ptr<osg::Group> group1 = new osg::Group();
 ​
     osgWidgetList.push_back(std::make_unique<OSGWidget>(osgOne));
     osgWidgetList[index].get()->view->setSceneData(osgWidgetList[index].get()->_group);
 ​
 }
 void MainWindow::createOsgWindowsAddPoints(int index)
 {
     OSGWidget* osgOne = new OSGWidget(0, Qt::Widget, osgViewer::ViewerBase::SingleThreaded);
 ​
     osgWidgetList.push_back(std::make_unique<OSGWidget>(osgOne));
     osgWidgetList[index].get()->view->addEventHandler(new AddLinePointHandler(index));//添加鼠标事件需要在viewer的run()和rellize()之前,这个很重要
     osgWidgetList[index].get()->view->setSceneData(osgWidgetList[index].get()->_group);
 ​
 }
 ​
 void MainWindow::addTabOsgWidget(int index, QString wname)
 {
     ui->tabWidget->addTab(osgWidgetList[index].get(),wname);
     ui->tabWidget->setCurrentIndex(index);
 }
 ​
 ​
 void MainWindow::on_tabWidget_tabCloseRequested(int index)
 {
     std::map<std::string, int>::const_iterator imap = osgToIndexMap.begin();
 ​
     for(; imap!=osgToIndexMap.end(); imap++){
         if(imap->second==index) break;
     }
     if(imap->first == "PlaneShow"){
         UpdateLog("******关闭OSG Window——PlaneShow****** \n");
         ui->pushButton_2->setEnabled(true);
         ui->checkBox->setCheckState(Qt::Unchecked);
         ui->pBO1->setEnabled(false);
         ui->pBO2->setEnabled(false);
         ui->pBO3->setEnabled(false);
         ui->pBO4->setEnabled(false);
     }else if(imap->first == "SeismicViewer"){
         UpdateLog("******关闭OSG Window——SeismicViewer****** \n");
         ui->checkBox_2->setCheckState(Qt::Unchecked);
         ui->pushButton->setEnabled(true);
 ​
         ui->pBOA1->setEnabled(false);
         ui->pBOA2->setEnabled(false);
     }
     osgToIndexMap.erase(imap);
 ​
     qDebug()<<index;
     ui->tabWidget->removeTab(index);
     osgWidgetList.erase(osgWidgetList.begin()+index);
 ​
     //因为osgWidgetList中索引改变,需要改变osgToIndexMap映射数组,和osgWidgetList中OSGWidget中事件处理器的索引
     for(std::map<std::string, int>::iterator it=osgToIndexMap.begin(); it!=osgToIndexMap.end(); it++){
         if(it->second>index) {
             it->second=it->second-1;
             // 获取事件处理器容器(假设你可以访问它)——一个因为OSGWidget只有一个事件处理器,所以下面统一设置成it->second
             osgViewer::View::EventHandlers& handlers = osgWidgetList[it->second].get()->view->getEventHandlers();
             if(!handlers.empty()){
                 for (auto& handlerPtr : handlers) {
                     AddLinePointHandler* handler = dynamic_cast<AddLinePointHandler*>(handlerPtr.get());
                     if (handler) {
                         // 找到处理器,设置新的索引值
                         handler->setIndex(it->second);
                         break;  // 找到后可以退出循环
                     }
                 }
             }
         }
     }
 }
 ​
 void MainWindow::on_pushButton_clicked()
 {
     UpdateLog("******生成OSG Window——SeismicViewer****** \n");
     ui->checkBox_2->setCheckState(Qt::Checked);
     ui->pBOA1->setEnabled(true);
     ui->pBOA2->setEnabled(true);
     int index = osgWidgetList.size();
     createOsgWindowsAddPoints(index);
 ​
     ui->pushButton->setEnabled(false);
     osgToIndexMap.insert(std::make_pair("SeismicViewer",index));
     //osg显示窗口添加绘制平面
 ​
     osg::ref_ptr<osg::Group> showGroup = dynamic_cast<osg::Group*>(osgWidgetList[index].get()->_group->getChild(0));
     showGroup->addChild(_generateDrawable->creatDrawPlane());//如果有双击加节点操作,这个是第5个节点(group),不然是第3个
 ​
     QString wname = QString::number(index + 1)+"-SeismicViewer";
     addTabOsgWidget(index,wname);
 }
 ​
 void MainWindow::on_pushButton_2_clicked()
 {
     ui->pushButton_2->setEnabled(false);
     UpdateLog("******生成OSG Window——PlaneShow****** \n");
     ui->checkBox->setCheckState(Qt::Checked);
     ui->pBO1->setEnabled(true);
     ui->pBO2->setEnabled(true);
     ui->pBO3->setEnabled(true);
     ui->pBO4->setEnabled(true);
 ​
     int index = osgWidgetList.size();
     createOsgWindowsAddPoints(index);
 ​
     osgToIndexMap.insert(std::make_pair("PlaneShow", index));
 ​
     osg::ref_ptr<osg::Geode> wireframeGeode = _generateDrawable->createCubeEdgeWireframe();
 ​
     int gridSize = 6;  // 6x6 网格,总共 36 个矩形
     std::vector<float> attributeValues;  // 存储每个点的属性值
     osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array;  // 存储每个点的颜色
 ​
     osg::ref_ptr<osg::Geode> planeGeode = _generateDrawable->createGradientPlane(gridSize, attributeValues, colors);
 ​
     osg::ref_ptr<osg::Group> showGroup = dynamic_cast<osg::Group*>(osgWidgetList[index].get()->_group->getChild(0));
     showGroup->addChild(wireframeGeode);
     showGroup->addChild(planeGeode);
 ​
     QString wname = QString::number(index + 1)+"-PlaneShow";
     addTabOsgWidget(index,wname);
 ​
 }
 ​
 ​
 void MainWindow::on_pBOA1_clicked()
 {
     std::map<std::string, int>::const_iterator it= osgToIndexMap.find("SeismicViewer");
     int index = it->second;
     osgWidgetList[index].get()->updateShowPLFlag();
     bool flag = osgWidgetList[index].get()->_showPLFlag;
     if(flag){
         UpdateLog("显示SeismicViewer中所有点线字 \n");
     }else{
         UpdateLog("隐藏SeismicViewer中所有点线字 \n");
     }
     osg::ref_ptr<osg::Group> pointsgroup = dynamic_cast<osg::Group*>(osgWidgetList[index].get()->_group->getChild(3));
     osg::ref_ptr<osg::Group> linesgroup = dynamic_cast<osg::Group*>(osgWidgetList[index].get()->_group->getChild(4));
     pointsgroup->setNodeMask(flag);
     linesgroup->setNodeMask(flag);
 }
 ​
 ​
 void MainWindow::on_pBOA2_clicked()
 {
     UpdateLog("清空SeismicViewer中所有点线字 \n");
     std::map<std::string, int>::const_iterator it= osgToIndexMap.find("SeismicViewer");
     int index = it->second;
     osg::ref_ptr<osg::Group> pointsgroup = dynamic_cast<osg::Group*>(osgWidgetList[index].get()->_group->getChild(3));
     osg::ref_ptr<osg::Group> linesgroup = dynamic_cast<osg::Group*>(osgWidgetList[index].get()->_group->getChild(4));
     pointsgroup->removeChildren(0, pointsgroup->getNumChildren());
     linesgroup->removeChildren(0,linesgroup->getNumChildren());
 }
 ​
 ​
 void MainWindow::on_pBO1_clicked()
 {
     std::map<std::string, int>::const_iterator it= osgToIndexMap.find("PlaneShow");
     int index = it->second;
     osgWidgetList[index].get()->updateShowPLFlag();
     bool flag = osgWidgetList[index].get()->_showPLFlag;
     if(flag){
         UpdateLog("显示 PlaneShow 中所有点线字 \n");
     }else{
         UpdateLog("隐藏 PlaneShow 中所有点线字 \n");
     }
     osg::ref_ptr<osg::Group> pointsgroup = dynamic_cast<osg::Group*>(osgWidgetList[index].get()->_group->getChild(3));
     osg::ref_ptr<osg::Group> linesgroup = dynamic_cast<osg::Group*>(osgWidgetList[index].get()->_group->getChild(4));
     pointsgroup->setNodeMask(flag);
     linesgroup->setNodeMask(flag);
 }
 ​
 ​
 void MainWindow::on_pBO2_clicked()
 {
     UpdateLog("清空 PlaneShow 中所有点线字 \n");
     std::map<std::string, int>::const_iterator it= osgToIndexMap.find("PlaneShow");
     int index = it->second;
     osg::ref_ptr<osg::Group> pointsgroup = dynamic_cast<osg::Group*>(osgWidgetList[index].get()->_group->getChild(3));
     osg::ref_ptr<osg::Group> linesgroup = dynamic_cast<osg::Group*>(osgWidgetList[index].get()->_group->getChild(4));
     pointsgroup->removeChildren(0, pointsgroup->getNumChildren());
     linesgroup->removeChildren(0,linesgroup->getNumChildren());
 }
 ​
 ​
 void MainWindow::on_pBO3_clicked()
 {
     std::map<std::string, int>::const_iterator it= osgToIndexMap.find("PlaneShow");
     int index = it->second;
 ​
 }

3 效果图

4 最后

建议将所有需要添加的可视化对象都写在GenerateDrawable中,自己手动添加的可视化对象都节点加在_group下第一个子节点上。
(后续会更新节点动效及地震可视化相关内容)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值