first commit

This commit is contained in:
仲迪 2021-12-23 17:46:55 +08:00
commit ac8b22f196
11 changed files with 879 additions and 0 deletions

54
.gitignore vendored Normal file
View File

@ -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*

151
MousePicker.cpp Normal file
View File

@ -0,0 +1,151 @@
#include "MousePicker.h"
#include <QtWidgets>
#include <osg/Point>
#include <osg/MatrixTransform>
#include <osgViewer/Viewer>
MousePicker::MousePicker(QObject *parent)
: QObject(parent)
{
// 防止老点绘制影响新点的求交运算
currentDrawNode->setNodeMask(0xffffffff & (~0x00000004));
}
void MousePicker::setRoot(osg::ref_ptr<osg::Group> 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<osgViewer::Viewer*>( &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<osg::Vec4Array> 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<osg::Geometry> MousePicker::createPointGeode(const osg::Vec3 &pos)
{
osg::Geometry *geom = new osg::Geometry();
osg::ref_ptr<osg::Vec3Array> vertex = new osg::Vec3Array();
vertex->push_back(pos);
geom->setVertexArray(vertex.get());
osg::ref_ptr<osg::Vec4Array> 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;
}

43
MousePicker.h Normal file
View File

@ -0,0 +1,43 @@
#ifndef MOUSEPICKER_H
#define MOUSEPICKER_H
#include <QtCore>
#include <QObject>
#include <osg/Geode>
#include <osgGA/GUIEventHandler>
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<osg::Group> root = nullptr);
void activate(PickingMode _mode, osg::Node* model);
bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa );
void disactivate();
static osg::ref_ptr<osg::Geometry> createPointGeode(const osg::Vec3 &pos);
signals:
void editionDone(PickingMode, osg::ref_ptr<osg::Vec3Array>);
private:
bool isActivated = false;
bool isDrawing = false;
PickingMode mode;
osg::Vec3 pushPnt;
osg::ref_ptr<osg::Node> model;
osg::ref_ptr<osg::Group> drawNodeList = new osg::Group;
osg::ref_ptr<osg::Geode> currentDrawNode = new osg::Geode;
osg::ref_ptr<osg::Geometry> lineGeometry;
osg::ref_ptr<osg::Vec3Array> vertexArray;
};
#endif // MOUSEPICKER_H

18
main.cpp Normal file
View File

@ -0,0 +1,18 @@
#include "mainwindow.h"
#include <QApplication>
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();
}

262
mainwindow.cpp Normal file
View File

@ -0,0 +1,262 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtWidgets>
#include <QtCore>
#include <QtXml>
#include <math.h>
#include <osgQOpenGL/osgQOpenGLWidget>
#include <osg/Point>
#include <osg/MatrixTransform>
#include <osgViewer/Viewer>
#include <osgDB/ReadFile>
#include <osgGA/TrackballManipulator>
#include <Windows.h>
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<QUrl> urls = event->mimeData()->urls();
if(urls.isEmpty()){
return;
}
QList<QUrl>::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<float>( osgWidget->width()) / static_cast<float>( osgWidget->height() );
osgWidget->getOsgViewer()->getCamera()->setProjectionMatrixAsPerspective( 30.f, aspectRatio, 1.f, 1000.f );
osg::ref_ptr<osg::Light> 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<Item, QList<Item>> 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<Item> 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<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), [=](int index){
modelChosen->clear();
QList<Item> 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<osg::Vec3Array> 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;
}

60
mainwindow.h Normal file
View File

@ -0,0 +1,60 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "myNodeVisitor.h"
#include "MousePicker.h"
#include <QMainWindow>
#include <osgQOpenGL/osgQOpenGLWidget>
#include <osgViewer/Viewer>
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

61
mainwindow.ui Normal file
View File

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1331</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget"/>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1331</width>
<height>30</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>文件</string>
</property>
<addaction name="actionOpenModel"/>
<addaction name="actionUpdateModel"/>
<addaction name="actionZoomToExtent"/>
<addaction name="actionEditModel"/>
</widget>
<addaction name="menuFile"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<action name="actionOpenModel">
<property name="text">
<string>打开模型</string>
</property>
</action>
<action name="actionUpdateModel">
<property name="text">
<string>更新模型</string>
</property>
</action>
<action name="actionZoomToExtent">
<property name="text">
<string>重置视角</string>
</property>
</action>
<action name="actionEditModel">
<property name="text">
<string>模型编辑</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>

147
myNodeVisitor.cpp Normal file
View File

@ -0,0 +1,147 @@
#include "myNodeVisitor.h"
#include "mainwindow.h"
#include <osg/Texture2D>
#include <osg/ProxyNode>
#include <osg/PagedLOD>
#include <osgDB/ReadFile>
#include <osgDB/WriteFile>
myNodeVisitor::myNodeVisitor()
{
opt->setOptionString("WriteImageHint=IncludeFile");
}
void myNodeVisitor::apply(osg::Geode &node)
{
// 遍历Geode里面的所有Geometry即形状点、线、面
for(uint i = 0; i<node.getNumDrawables(); i++){
osg::Geometry* pGeo = node.getDrawable(i)->asGeometry();
if(pGeo){
osg::Vec3Array* vertex = dynamic_cast<osg::Vec3Array*>(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; i<node.getNumChildren(); i++){
childAffected = false;
node.getChild(i)->accept(*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<osg::Node> 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<osg::Vec3Array> 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;
}

35
myNodeVisitor.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef MYNODEVISITOR_H
#define MYNODEVISITOR_H
#include <osg/NodeVisitor>
#include <osgUtil/Optimizer>
#include <osgDB/ReadFile>
#include <QtCore>
// 深度优先的访问器
class myNodeVisitor : public osg::NodeVisitor
{
public:
myNodeVisitor();
void setPoints(osg::ref_ptr<osg::Vec3Array> _vertexArray) {vertexArray = _vertexArray;}
void setBoundaryList(QList<osg::ref_ptr<osg::Vec3Array>> _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<osg::Vec3Array> vertexArray;
QList<osg::ref_ptr<osg::Vec3Array>> boundaryList;
};
#endif // MYNODEVISITOR_H

45
simulationMaster.pro Normal file
View File

@ -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

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="simulationMaster_zh_CN"></TS>