commit ac8b22f196644a57723e95b1ac891e165939d637 Author: Zd <1628411814@qq.com> Date: Thu Dec 23 17:46:55 2021 +0800 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5405aaa --- /dev/null +++ b/.gitignore @@ -0,0 +1,54 @@ +# ---> Qt +# C++ objects and libs +*.slo +*.lo +*.o +*.a +*.la +*.lai +*.so +*.so.* +*.dll +*.dylib + +# Qt-es +object_script.*.Release +object_script.*.Debug +*_plugin_import.cpp +/.qmake.cache +/.qmake.stash +*.pro.user +*.pro.user.* +*.qbs.user +*.qbs.user.* +*.moc +moc_*.cpp +moc_*.h +qrc_*.cpp +ui_*.h +*.qmlc +*.jsc +Makefile* +*build-* +*.qm +*.prl + +# Qt unit tests +target_wrapper.* + +# QtCreator +*.autosave + +# QtCreator Qml +*.qmlproject.user +*.qmlproject.user.* + +# QtCreator CMake +CMakeLists.txt.user* + +# QtCreator 4.8< compilation database +compile_commands.json + +# QtCreator local machine specific files for imported projects +*creator.user* + diff --git a/MousePicker.cpp b/MousePicker.cpp new file mode 100644 index 0000000..d7c4656 --- /dev/null +++ b/MousePicker.cpp @@ -0,0 +1,151 @@ +#include "MousePicker.h" + +#include + +#include +#include +#include + +MousePicker::MousePicker(QObject *parent) + : QObject(parent) +{ + // 防止老点绘制影响新点的求交运算 + currentDrawNode->setNodeMask(0xffffffff & (~0x00000004)); +} + +void MousePicker::setRoot(osg::ref_ptr root) +{ +// root->addChild(currentDrawNode); + root->addChild(drawNodeList); +} + +void MousePicker::activate(PickingMode _mode, osg::Node* node) +{ + disactivate(); + mode = _mode; + isActivated = true; + model = node; +} + +bool MousePicker::handle(const osgGA::GUIEventAdapter &ea, osgGA::GUIActionAdapter &aa) +{ + if(!isActivated){ + return false; + } + osgViewer::Viewer* pViewer = dynamic_cast( &aa ); + osgUtil::LineSegmentIntersector::Intersections intersections; + pViewer->computeIntersections(ea, intersections, 0x00000004); + if(intersections.empty()){ + return false; + } + osg::Vec3 mouseWorldCoord = intersections.begin()->getWorldIntersectPoint(); + switch( ea.getEventType() ){ + case osgGA::GUIEventAdapter::PUSH:{ + if(ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON){ + if(!isDrawing){ + // 初始化lineGeometry + lineGeometry = new osg::Geometry; + lineGeometry->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); + currentDrawNode->addDrawable(lineGeometry); + // 初始化vertexArray + vertexArray = new osg::Vec3Array; + vertexArray->push_back(mouseWorldCoord); + osg::ref_ptr color = new osg::Vec4Array(); + color->push_back(osg::Vec4(0.0f, 0.8f, 0.8f, 0.5f) ); + lineGeometry->setColorArray(color, osg::Array::BIND_OVERALL); + isDrawing = true; + } + vertexArray->push_back(mouseWorldCoord); + vertexArray->dirty(); + pushPnt = mouseWorldCoord; + } + if(ea.getButton() == osgGA::GUIEventAdapter::RIGHT_MOUSE_BUTTON){ + // 当点击右键时, 退出编辑 + disactivate(); + } + return false; + } + case osgGA::GUIEventAdapter::RELEASE:{ + if(ea.getButton() == osgGA::GUIEventAdapter::LEFT_MOUSE_BUTTON){ + // 点击事件完成时 + if(pushPnt != mouseWorldCoord){ + // 当用户真正希望的是拖动视角时,弹出点击事件的录入操作,假装无事发生 + vertexArray->pop_back(); + return false; + } + // 绘制相应点 +// currentDrawNode->addDrawable(createPointGeode(mouseWorldCoord)); + + osg::MatrixTransform* mt = new osg::MatrixTransform; + mt->setMatrix( + osg::Matrix::translate(mouseWorldCoord)); + mt->addChild(model); + drawNodeList->addChild(mt); + if(mode == LinePicker){ + // 如果是线要素则绘制该线段并显示长度 + lineGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, vertexArray->size())); + } + if(mode == AreaPicker){ + // 如果是面要素则绘制该面并显示面积 + lineGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POLYGON, 0, vertexArray->size())); + } + } + return false; + } + case osgGA::GUIEventAdapter::MOVE:{ + if(isDrawing){ + // 绘制过程中,按不同的图形类型进行图形绘制的预览 + vertexArray->pop_back(); + vertexArray->push_back(mouseWorldCoord); + vertexArray->dirty(); + if(mode == PointPicker){ + return false; + } + // 根据MOVE的坐标实时更新lineGeometry + lineGeometry->setVertexArray(vertexArray); + lineGeometry->dirtyDisplayList(); + } + return false; + } + case osgGA::GUIEventAdapter::DOUBLECLICK:{ + if(isDrawing){ + // 当双击时,完成当前geode的编辑 + isDrawing = false; + } + // 双击时应避免视角操作,故返回true + return true; + } + } + return false; +} + +void MousePicker::disactivate() +{ + isDrawing = false; + isActivated = false; + emit editionDone(mode, vertexArray); + + currentDrawNode->removeChildren(0, currentDrawNode->getNumChildren()); + lineGeometry = nullptr; + vertexArray = nullptr; +} + +osg::ref_ptr MousePicker::createPointGeode(const osg::Vec3 &pos) +{ + osg::Geometry *geom = new osg::Geometry(); + + osg::ref_ptr vertex = new osg::Vec3Array(); + vertex->push_back(pos); + geom->setVertexArray(vertex.get()); + + osg::ref_ptr color = new osg::Vec4Array(); + color->push_back(osg::Vec4(1.0f, 0.0f, 0.0f, 1.0f) ); + geom->setColorArray(color, osg::Array::BIND_OVERALL); + + geom->getOrCreateStateSet()->setAttribute(new osg::Point(6.0f), osg::StateAttribute::ON); + geom->getOrCreateStateSet()->setMode(GL_POINT_SMOOTH, osg::StateAttribute::ON); + geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::POINTS, 0, 1)); + geom->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE); + + return geom; +} diff --git a/MousePicker.h b/MousePicker.h new file mode 100644 index 0000000..a177b66 --- /dev/null +++ b/MousePicker.h @@ -0,0 +1,43 @@ +#ifndef MOUSEPICKER_H +#define MOUSEPICKER_H + +#include +#include +#include +#include + +enum PickingMode{ + PointPicker = 0, + LinePicker = 1, + AreaPicker = 2, +}; + +class MousePicker : public QObject, public osgGA::GUIEventHandler +{ + Q_OBJECT +public: + explicit MousePicker(QObject *parent = nullptr); + void setRoot(osg::ref_ptr root = nullptr); + void activate(PickingMode _mode, osg::Node* model); + bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa ); + void disactivate(); + static osg::ref_ptr createPointGeode(const osg::Vec3 &pos); + +signals: + void editionDone(PickingMode, osg::ref_ptr); + +private: + bool isActivated = false; + bool isDrawing = false; + PickingMode mode; + + osg::Vec3 pushPnt; + osg::ref_ptr model; + osg::ref_ptr drawNodeList = new osg::Group; + osg::ref_ptr currentDrawNode = new osg::Geode; + osg::ref_ptr lineGeometry; + osg::ref_ptr vertexArray; +}; + + +#endif // MOUSEPICKER_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..59fd086 --- /dev/null +++ b/main.cpp @@ -0,0 +1,18 @@ +#include "mainwindow.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); + QApplication::setStyle("fusion"); + + auto font = QFont("Microsoft YaHei UI"); + font.setPointSize(12); + QApplication::setFont(font); + QApplication a(argc, argv); + MainWindow w; + w.show(); + return a.exec(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..e053c78 --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,262 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::MainWindow) +{ + ui->setupUi(this); + setAcceptDrops(true); + + QHBoxLayout * hlayout = new QHBoxLayout(ui->centralwidget); + hlayout->addWidget(osgWidget); + hlayout->setSizeConstraint(QLayout::SetNoConstraint); + osgWidget->setMouseTracking(true); + + connect(osgWidget, &osgQOpenGLWidget::initialized, this, &MainWindow::initOsg); + connect(ui->actionOpenModel, &QAction::triggered, [this](){ + QString modelFile = QFileDialog::getOpenFileName(this, tr("3D Model File Selection"), "", "*.s3c; *.osg; *.osgb"); + if(modelFile != ""){ + addModel(modelFile); + } + }); + connect(ui->actionUpdateModel, &QAction::triggered, this, &MainWindow::updateModel); + connect(ui->actionZoomToExtent, &QAction::triggered, [this]{ + osgWidget->getOsgViewer()->setCameraManipulator(new osgGA::TrackballManipulator()); + }); +} + +MainWindow::~MainWindow() +{ + delete ui; +} +void MainWindow::dragEnterEvent(QDragEnterEvent *event) +{ + event->acceptProposedAction(); +} + +void MainWindow::dropEvent(QDropEvent *event) +{ + QList urls = event->mimeData()->urls(); + if(urls.isEmpty()){ + return; + } + QList::iterator it; + for(it = urls.begin(); it != urls.end(); it++){ + QFileInfo fileInfo(it->toLocalFile()); + if(fileInfo.isFile()){ + addModel(fileInfo.filePath()); + } + } +} + +void MainWindow::initOsg() +{ + osgWidget->getOsgViewer()->setSceneData(root); + osgWidget->getOsgViewer()->getCamera()->setSmallFeatureCullingPixelSize(-1.0f); + osgWidget->getOsgViewer()->getCamera()->setClearColor(osg::Vec4(0.5,0.5,0.5,0.5)); + osgWidget->getOsgViewer()->getCamera()->setNearFarRatio(0.0001); + + float aspectRatio = static_cast( osgWidget->width()) / static_cast( osgWidget->height() ); + osgWidget->getOsgViewer()->getCamera()->setProjectionMatrixAsPerspective( 30.f, aspectRatio, 1.f, 1000.f ); + + osg::ref_ptr light = new osg::Light(); + light->setLightNum(0); + light->setDirection(osg::Vec3(0.0f, 0.0f, -1.0f)); + light->setPosition(osg::Vec4(0.0f, 0.0f, 1000, 0.0f)); + light->setAmbient(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); + light->setDiffuse(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f)); + +// //设置恒衰减指数 +// light->setConstantAttenuation(1.0f); +// //设置线形衰减指数 +// light->setLinearAttenuation(0.0f); +// //设置二次方衰减指数 +// light->setQuadraticAttenuation(0.0f); + + osgWidget->getOsgViewer()->setLight(light); + + mp = new MousePicker(this); + osgWidget->getOsgViewer()->addEventHandler(mp); + addModel("C:/Users/16284/Desktop/qt/Tile_+000_+005/Tile_+000_+005/Tile_+000_+005.osgb"); +} + +void MainWindow::addModel(QString modelFile) +{ + if(modelFile == filename){ + return; + } + + filename = modelFile; + QString ext = filename.split('.').back().toLower(); + + osg::Group* layer = new osg::Group; + if(ext == "osg" || ext == "osgb" || ext == "obj" || ext == "ive"){ + clearModel(); + osg::Node* node = osgDB::readNodeFile(Utf8ToGbk(filename.toStdString())); + node->setName(filename.toStdString()); + layer->addChild(node); + } + else if(ext == "s3c"){ + QDir folder(filename); + folder.cdUp(); + QDir dataPath(folder.absolutePath() + "/Data"); + clearModel(); + QStringList tileFolderList = dataPath.entryList(); + for(QString tileFolder: tileFolderList){ + QString tileFile = dataPath.absolutePath() + '/' + tileFolder + '/' + tileFolder + ".osgb"; + if(QDir().exists(tileFile)){ + osg::Node* node = osgDB::readNodeFile(Utf8ToGbk(tileFile.toStdString())); + node->setName(tileFolder.toStdString() + ".osgb"); + layer->addChild(node); + } + } + } + else{ + QMessageBox::warning(this, "simulationMaster", "Unsupported File Format! "); + return; + } + root->addChild(layer); + mp->setRoot(root); + osgGA::TrackballManipulator* tm = new osgGA::TrackballManipulator(); + tm->setAllowThrow(false); + tm->setAnimationTime(1000); + osgWidget->getOsgViewer()->setCameraManipulator(tm); +} + +void MainWindow::updateModel() +{ + // 选择模型更新基于的三维符号库 +// QString libFileName = QFileDialog::getOpenFileName(this, "Plz choose the 3dl file", "", "*.3dl"); + QString libFileName = QString::fromLocal8Bit("C:/Users/16284/Desktop/qt/LibMASTER/基础三维符号库.3dl"); + if(libFileName == ""){ + return; + } + QDir dir = QDir(libFileName); + dir.cdUp(); + + // 将三维符号库读取到内存中 + QMap> map; + QDomDocument doc; + QFile file(libFileName); + file.open(QIODevice::ReadOnly); + doc.setContent(&file); + file.close(); + + QDomNode FLevNode = doc.documentElement().firstChild().toElement().firstChild(); //用来访问第一级符号 + QDomNode SLevNode = FLevNode.toElement().firstChild(); //用来访问第二级符号 + + while(!FLevNode.isNull()){ + if (FLevNode.toElement().tagName() == QStringLiteral("catagory")){ + Item FirstItem; //存一级符号 + QList SecondList; //某一级符号下,所有二级符号组成的列表 + FirstItem.name = FLevNode.toElement().attribute("name").trimmed(); + FirstItem.code = FLevNode.toElement().attribute("code").trimmed(); + SLevNode = FLevNode.toElement().firstChild(); + while(!SLevNode.isNull()){ + if (SLevNode.toElement().tagName() == QStringLiteral("feature")){ + Item SecondItem; //存二级符号 + SecondItem.name = SLevNode.toElement().attribute("name").trimmed(); + SecondItem.code = SLevNode.toElement().attribute("code").trimmed(); + SecondItem.address = SLevNode.toElement().attribute("address").trimmed(); + SecondList << SecondItem; + } + SLevNode = SLevNode.nextSibling(); + } + map.insert(FirstItem, SecondList); + } + FLevNode = FLevNode.nextSibling(); //访问下一个兄弟节点 + } + + // 选择需要渲染的符号 + QDialog dialog(this); + QFormLayout form(&dialog); + form.addRow(new QLabel(QStringLiteral("选择渲染使用的符号"))); + // 获取符号类别名称 + QComboBox *cataChosen = new QComboBox(&dialog); + form.addRow(QStringLiteral("类别名称: "), cataChosen); + // 获取符号类别编码 + QComboBox *modelChosen = new QComboBox(&dialog); + connect(cataChosen, static_cast(&QComboBox::currentIndexChanged), [=](int index){ + modelChosen->clear(); + QList itemList = map.values().at(index); + for(int i = 0; i < itemList.count(); i++){ + modelChosen->addItem(itemList.at(i).name); + } + }); + for(int i = 0; i < map.count(); i++){ + cataChosen->addItem(map.keys().at(i).name); + } + form.addRow(QStringLiteral("符号名称: "), modelChosen); + + // Add Cancel and OK button + QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, + Qt::Horizontal, &dialog); + form.addRow(&buttonBox); + QObject::connect(&buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept())); + QObject::connect(&buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject())); + dialog.adjustSize(); +// dialog.setFixedWidth(250); +// dialog.setFixedHeight(120); + + // Process when OK button is clicked + int result = dialog.exec(); + while(result == QDialog::Accepted){ + if(cataChosen->currentIndex()==-1 || modelChosen->currentIndex()==-1){ + QMessageBox::warning(this, "simulationMaster", "Plz choose the catagory and model"); + result = dialog.exec(); + continue; + } + Item item = map.values().at(cataChosen->currentIndex()).at(modelChosen->currentIndex()); + // 根据item.address读取模型 + osg::Node* model = osgDB::readNodeFile(Utf8ToGbk((dir.absolutePath() + '/' + item.address).toStdString())); + + mp->activate(PickingMode::PointPicker, model); +// connect(mp, &MousePicker::editionDone, [=](PickingMode mode, osg::ref_ptr vertexArray) +// { +// if(vertexArray == nullptr){ +// return; +// } +// if(mode == PickingMode::PointPicker){ +// nv.setPoints(vertexArray); +// root->getChild(0)->accept(nv); +// } +// }); + break; + } +} + +void MainWindow::clearModel() +{ + root->removeChildren(0, root->getNumChildren()); +} + +std::string Utf8ToGbk(std::string str){ + const char* src_str = str.data(); + int len = MultiByteToWideChar(CP_UTF8, 0, src_str, -1, NULL, 0); + wchar_t* wszGBK = new wchar_t[len + 1]; + memset(wszGBK, 0, len * 2 + 2); + MultiByteToWideChar(CP_UTF8, 0, src_str, -1, wszGBK, len); + len = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL); + char* szGBK = new char[len + 1]; + memset(szGBK, 0, len + 1); + WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGBK, len, NULL, NULL); + std::string strTemp(szGBK); + if (wszGBK) delete[] wszGBK; + if (szGBK) delete[] szGBK; + return strTemp; +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..735a5a4 --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,60 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include "myNodeVisitor.h" +#include "MousePicker.h" + +#include + +#include +#include + +struct Item +{ + QString name; //符号名称 + QString code; //符号代码 + QString address; //符号所在的相对路径 + + bool operator < ( const Item& item) const + { + return this->name < item.name; + } +}; + + +QT_BEGIN_NAMESPACE +namespace Ui { class MainWindow; } +QT_END_NAMESPACE + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +private: + void initOsg(); + void addModel(QString filename); + void updateModel(); + void clearModel(); + +protected: + void dragEnterEvent(QDragEnterEvent* event = NULL); + void dropEvent(QDropEvent* event); + +private: + Ui::MainWindow *ui; + osgQOpenGLWidget* osgWidget = new osgQOpenGLWidget; + osg::Group* root = new osg::Group; + osg::Geode* drawNode = new osg::Geode; + myNodeVisitor nv; + QString filename; + + MousePicker* mp; +}; + +std::string Utf8ToGbk(std::string str); +#endif // MAINWINDOW_H + diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..7edf2c0 --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,61 @@ + + + MainWindow + + + + 0 + 0 + 1331 + 600 + + + + MainWindow + + + + + + 0 + 0 + 1331 + 30 + + + + + 鏂囦欢 + + + + + + + + + + + + 鎵撳紑妯″瀷 + + + + + 鏇存柊妯″瀷 + + + + + 閲嶇疆瑙嗚 + + + + + 妯″瀷缂栬緫 + + + + + + diff --git a/myNodeVisitor.cpp b/myNodeVisitor.cpp new file mode 100644 index 0000000..bedea39 --- /dev/null +++ b/myNodeVisitor.cpp @@ -0,0 +1,147 @@ +#include "myNodeVisitor.h" +#include "mainwindow.h" + +#include +#include +#include +#include +#include + +myNodeVisitor::myNodeVisitor() +{ + opt->setOptionString("WriteImageHint=IncludeFile"); +} + +void myNodeVisitor::apply(osg::Geode &node) +{ + // 遍历Geode里面的所有Geometry,即形状(点、线、面) + for(uint i = 0; iasGeometry(); + if(pGeo){ + osg::Vec3Array* vertex = dynamic_cast(pGeo->getVertexArray()); + if (!vertex){ + continue; + } + for (int i = 0; i < vertex->size(); i++){ + // 对于满足条件的点 + int index = pointsNearVertex((*vertex)[i]); + if (index != -1) + { + (*vertex)[i].z() = vertexArray->at(index).z(); + affected = true; + } + } + } + } + + if (affected && !node.getName().empty()){ + // 和PagedLOD的处理方式一致 + newFileName = QString::fromStdString(node.getName()).split('.').first() + "~.osgb"; + node.accept(*tv); + node.setName(newFileName.toStdString()); + // 写文件 + osgDB::writeNodeFile(node, (workingDir + '/' + newFileName).toStdString(), opt); + childAffected = true; + } +} + +void myNodeVisitor::apply(osg::Group &node) +{ + bool groupAffected = false; + for(uint i = 0; iaccept(*this); + if(childAffected){ + groupAffected = true; + } + } + + if(groupAffected && !node.getName().empty()){ + // 和PagedLOD的处理方式一致 + newFileName = QString::fromStdString(node.getName()).split('.').first() + "~.osgb"; + node.accept(*tv); + node.setName(newFileName.toStdString()); + // 写文件 + osgDB::writeNodeFile(node, (workingDir + '/' + newFileName).toStdString(), opt); + childAffected = true; + } +} + +void myNodeVisitor::apply(osg::PagedLOD &node) +{ + affected = false; + childAffected = false; + for(uint i = 0; i < node.getNumChildren(); i++){ + // 这个遍历过程可能会修改文件 + node.getChild(i)->accept(*this); + } + +// // 使用affected作为初步判断,以尽可能地减少计算量, 非affected文件都不会被修改 +// if(!affected && ! childAffected){ +// return; +// } + + // 如果真的被修改了文件,那么, + workingDir = QString::fromStdString(node.getDatabasePath()); + // for(uint i = 0; i < node.getNumFileNames(); i++){ + for(uint i = 1; i < node.getNumFileNames(); i++){ + // 遍历这个LOD文件中的所有子文件,即金字塔中更精细的那一层,他们也要改 + childAffected = false; + // 读文件以继续遍历 + osg::ref_ptr fileNode = osgDB::readNodeFile(workingDir.toStdString() + '/' + node.getFileName(i)); + if(!fileNode.valid()){ + continue; + } + // 将fileNode和文件名链接在一起,这样当节点被修改时,可以及时更新对应的文件 + fileNode->setName(node.getFileName(i)); + // 两个遍历器都要遍历 + fileNode->accept(*tv); + fileNode->accept(*this); + if(childAffected){ + //更改文件名链接 + node.setFileName(i, newFileName.toStdString()); + // 此时也应该相应地修改pLOD对应的文件 + } + } + + if(!node.getName().empty()){ + newFileName = QString::fromStdString(node.getName()).split('.').first() + "~.osgb"; + node.accept(*tv); + node.setName(newFileName.toStdString()); + // 写文件 + osgDB::writeNodeFile(node, (workingDir + '/' + newFileName).toStdString(), opt); + } + + // 作为别人的儿子,文件被修改了 + childAffected = true; +} + +bool myNodeVisitor::pointInPolygon(osg::Vec3 &point) +{ + for(osg::ref_ptr boundary: boundaryList){ + int i, j, nvert = boundary->size(); + bool c = false; + + // 射线法 + for (i = 0, j = nvert - 1; i < nvert; j = i++) { + if (((boundary->at(i).y() >= point.y()) != (boundary->at(j).y() >= point.y())) && + (point.x() <= (boundary->at(j).x() - boundary->at(i).x()) * (point.y() - boundary->at(i).y()) / (boundary->at(j).y() - boundary->at(i).y()) + boundary->at(i).x()) + ) + c = !c; + } + if(c && point.z() > boundary->at(0).z()){ + return true; + } + } + return false; +} + +int myNodeVisitor::pointsNearVertex(osg::Vec3 &point) +{ + for(int i = 0; i < vertexArray->size(); i++){ + if(pow(point.x() - vertexArray->at(i).x(), 2) + pow(point.y() - vertexArray->at(i).y(), 2) < 4 && point.z() > vertexArray->at(i).z()){ + return i; + } + } + return -1; +} diff --git a/myNodeVisitor.h b/myNodeVisitor.h new file mode 100644 index 0000000..be72746 --- /dev/null +++ b/myNodeVisitor.h @@ -0,0 +1,35 @@ +#ifndef MYNODEVISITOR_H +#define MYNODEVISITOR_H + +#include +#include +#include +#include + +// 深度优先的访问器 +class myNodeVisitor : public osg::NodeVisitor +{ +public: + myNodeVisitor(); + + void setPoints(osg::ref_ptr _vertexArray) {vertexArray = _vertexArray;} + void setBoundaryList(QList> _boundaryList){ boundaryList = _boundaryList; } + virtual void apply(osg::Geode &node) override; + virtual void apply(osg::Group &node) override; + virtual void apply(osg::PagedLOD &node) override; + bool pointInPolygon(osg::Vec3& point); + int pointsNearVertex(osg::Vec3& point); + +private: + osgUtil::Optimizer::TextureVisitor* tv = new osgUtil::Optimizer::TextureVisitor(true, false, false, false, false, false); + osgDB::ReaderWriter::Options* opt = new osgDB::ReaderWriter::Options; + QString workingDir; + QString newFileName; + // 记录点位是否被修改,从而缩减计算量 + bool affected = false; + bool childAffected = false; + + osg::ref_ptr vertexArray; + QList> boundaryList; +}; +#endif // MYNODEVISITOR_H diff --git a/simulationMaster.pro b/simulationMaster.pro new file mode 100644 index 0000000..e0aad2e --- /dev/null +++ b/simulationMaster.pro @@ -0,0 +1,45 @@ +QT += core gui opengl xml + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + + +TARGET = simulationMaster +TEMPLATE = app + + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +INCLUDEPATH += C:/Users/16284/Desktop/qt/OSG-install/include +LIBS += -LC:/Users/16284/Desktop/qt/OSG-install/lib -losg -losgDB -losgQOpenGL -losgViewer -losgGA -lOpenThreads -losgUtil + + +SOURCES += \ + main.cpp \ + mainwindow.cpp\ + MousePicker.cpp \ + myNodeVisitor.cpp + +HEADERS += \ + mainwindow.h\ + myNodeVisitor.h \ + MousePicker.h + +FORMS += \ + mainwindow.ui + +TRANSLATIONS += \ + simulationMaster_zh_CN.ts + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/simulationMaster_zh_CN.ts b/simulationMaster_zh_CN.ts new file mode 100644 index 0000000..77c9e05 --- /dev/null +++ b/simulationMaster_zh_CN.ts @@ -0,0 +1,3 @@ + + +