first commit
This commit is contained in:
commit
ac8b22f196
54
.gitignore
vendored
Normal file
54
.gitignore
vendored
Normal 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
151
MousePicker.cpp
Normal 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
43
MousePicker.h
Normal 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
18
main.cpp
Normal 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
262
mainwindow.cpp
Normal 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
60
mainwindow.h
Normal 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
61
mainwindow.ui
Normal 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
147
myNodeVisitor.cpp
Normal 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
35
myNodeVisitor.h
Normal 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
45
simulationMaster.pro
Normal 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
|
3
simulationMaster_zh_CN.ts
Normal file
3
simulationMaster_zh_CN.ts
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!DOCTYPE TS>
|
||||||
|
<TS version="2.1" language="simulationMaster_zh_CN"></TS>
|
Loading…
x
Reference in New Issue
Block a user