From 4a5b7c4712aa2a510724ae725db68b2830ae9903 Mon Sep 17 00:00:00 2001 From: djairoh Date: Sat, 25 May 2024 14:35:54 +0200 Subject: [PATCH] working ver with QT --- particle-track-and-trace/src/CMakeLists.txt | 10 +- particle-track-and-trace/src/Program.cpp | 17 +- particle-track-and-trace/src/Program.h | 15 +- .../src/QT/MainWindow.cpp | 57 +++++ particle-track-and-trace/src/QT/MainWindow.h | 35 +++ particle-track-and-trace/src/QT/MainWindow.ui | 210 ++++++++++++++++++ particle-track-and-trace/src/main.cpp | 73 +++++- 7 files changed, 397 insertions(+), 20 deletions(-) create mode 100644 particle-track-and-trace/src/QT/MainWindow.cpp create mode 100644 particle-track-and-trace/src/QT/MainWindow.h create mode 100644 particle-track-and-trace/src/QT/MainWindow.ui diff --git a/particle-track-and-trace/src/CMakeLists.txt b/particle-track-and-trace/src/CMakeLists.txt index dabecca..1494578 100644 --- a/particle-track-and-trace/src/CMakeLists.txt +++ b/particle-track-and-trace/src/CMakeLists.txt @@ -7,6 +7,11 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) +find_package(Qt5Core REQUIRED) +find_package(Qt5Gui REQUIRED) +find_package(Qt5Widgets REQUIRED) +find_package(Qt5OpenGL REQUIRED) + find_package(VTK COMPONENTS GeovisCore CommonColor @@ -72,6 +77,9 @@ add_executable(ParticleTrackTrace MACOSX_BUNDLE main.cpp advection/Vel.h advection/kernel/SnapBoundaryConditionKernel.h advection/kernel/SnapBoundaryConditionKernel.cpp + # QT/MainWindow.h + # QT/MainWindow.cpp + # QT/MainWindow.ui ) execute_process( @@ -92,7 +100,7 @@ find_library(NETCDF_LIB NAMES netcdf-cxx4 netcdf_c++4 PATHS ${NETCDFCXX_LIB_DIR} # Prevent a "command line is too long" failure in Windows. set(CMAKE_NINJA_FORCE_RESPONSE_FILE "ON" CACHE BOOL "Force Ninja to use response files.") -target_link_libraries(ParticleTrackTrace ${NETCDF_LIB} ${VTK_LIBRARIES}) +target_link_libraries(ParticleTrackTrace ${NETCDF_LIB} ${VTK_LIBRARIES} Qt5::Widgets Qt5::OpenGL VTK::GUISupportQt VTK::IOLegacy) # vtk_module_autoinit is needed vtk_module_autoinit( diff --git a/particle-track-and-trace/src/Program.cpp b/particle-track-and-trace/src/Program.cpp index bae7b2c..f36da4d 100644 --- a/particle-track-and-trace/src/Program.cpp +++ b/particle-track-and-trace/src/Program.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -27,11 +28,11 @@ void Program::setWinProperties() { this->win->SetSize(661, 661); this->win->SetDesiredUpdateRate(60); - this->interact->SetRenderWindow(this->win); + this->interact->SetRenderWindow(this->win.Get()); this->interact->Initialize(); vtkNew style; - interact->SetInteractorStyle(style); + this->interact->SetInteractorStyle(style); } void Program::setupTimer(int dt) { @@ -50,10 +51,12 @@ void Program::setupCameraCallback() { this->interact->AddObserver(vtkCommand::KeyPressEvent, callback); } - -Program::Program(int timerDT) { - this->win = vtkSmartPointer::New(); - this->interact = vtkSmartPointer::New(); +Program::Program(int timerDT, vtkSmartPointer win) { + // this->win = vtkSmartPointer::New(); + this->win = win; + // this->interact = vtkSmartPointer::New(); + // this->interact = vtkSmartPointer::New(); + this->interact = win->GetInteractor(); this->cam = createNormalisedCamera(); this->win->SetNumberOfLayers(0); @@ -91,7 +94,7 @@ void Program::updateData(int t) { void Program::setupInteractions() { for (Layer *l: layers) { - l->addObservers(interact); + l->addObservers(this->interact); } } diff --git a/particle-track-and-trace/src/Program.h b/particle-track-and-trace/src/Program.h index 5009957..e591a04 100644 --- a/particle-track-and-trace/src/Program.h +++ b/particle-track-and-trace/src/Program.h @@ -1,6 +1,7 @@ #ifndef PROGRAM_H #define PROGRAM_H +#include #include #include #include @@ -18,11 +19,13 @@ private: /** The window this program's layers render to. */ - vtkSmartPointer win; + // vtkSmartPointer win; + vtkSmartPointer win; /** The interactor through which the layers can interact with the window. */ vtkSmartPointer interact; + // vtkSmartPointer interact; /** The camera used by all layers for this program. @@ -37,9 +40,6 @@ private: */ void setupTimer(int dt); - /** This function adds all interactors of each layer to the interactor/window - */ - void setupInteractions(); /** This function sets up the camera's associated movement callbacks.. */ @@ -48,7 +48,7 @@ private: public: /** Constructor. */ - Program(int timerDT); + Program(int timerDT, vtkSmartPointer win); /** This function adds a new layer (and thus vtkRenderer) to the program. * The layer is expected to set its own position in the vtkRenderWindow layer system. @@ -68,11 +68,16 @@ public: */ void updateData(int t); + /** This function adds all interactors of each layer to the interactor/window + */ + void setupInteractions(); + /** * This function renders the vtkRenderWindow for the first time. * Only call this function once! */ void render(); + }; #endif diff --git a/particle-track-and-trace/src/QT/MainWindow.cpp b/particle-track-and-trace/src/QT/MainWindow.cpp new file mode 100644 index 0000000..486fbbf --- /dev/null +++ b/particle-track-and-trace/src/QT/MainWindow.cpp @@ -0,0 +1,57 @@ +#include "MainWindow.h" + +#include +#include +#include + +#include + +MainWindow::MainWindow(QWidget* parent) + : QMainWindow(parent) + , ui(new Ui::MainWindow) +{ + ui->setupUi(this); +} + +MainWindow::~MainWindow() { delete ui; } + +void MainWindow::showAboutDialog() +{ + QMessageBox::information( + this, "About", + "interactive particle in-fluid simulation program for surface level advection."); +} + +void MainWindow::showOpenFileDialog() +{ + QString fileName = QFileDialog::getOpenFileName(this, tr("Open file"), "", + "VTK Files (*.vtk)"); + + // Open file + QFile file(fileName); + file.open(QIODevice::ReadOnly); + + // Return on Cancel + if (!file.exists()) + return; + + openFile(fileName); +} + +void MainWindow::openFile(const QString& fileName) +{ + ui->sceneWidget->removeDataSet(); + + // Create reader + vtkSmartPointer reader = vtkSmartPointer::New(); + reader->SetFileName(fileName.toStdString().c_str()); + + // Read the file + reader->Update(); + + // Add data set to 3D view + vtkSmartPointer dataSet = reader->GetOutput(); + if (dataSet != nullptr) { + ui->sceneWidget->addDataSet(reader->GetOutput()); + } +} diff --git a/particle-track-and-trace/src/QT/MainWindow.h b/particle-track-and-trace/src/QT/MainWindow.h new file mode 100644 index 0000000..679c0dc --- /dev/null +++ b/particle-track-and-trace/src/QT/MainWindow.h @@ -0,0 +1,35 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow { + Q_OBJECT + +public: + explicit MainWindow(QWidget* parent = 0); + ~MainWindow(); + +public slots: + //! Show the 'About this application' dialog + void showAboutDialog(); + + //! Show the 'Open file...' dialog + void showOpenFileDialog(); + +protected: + //! Open a file + /*! + \param[in] fileName The name of the file including the path + */ + void openFile(const QString& fileName); + +private: + Ui::MainWindow* ui; +}; + +#endif diff --git a/particle-track-and-trace/src/QT/MainWindow.ui b/particle-track-and-trace/src/QT/MainWindow.ui new file mode 100644 index 0000000..6865dec --- /dev/null +++ b/particle-track-and-trace/src/QT/MainWindow.ui @@ -0,0 +1,210 @@ + + + MainWindow + + + + 0 + 0 + 800 + 600 + + + + Qt VTK Viewer + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + + + + 0 + 0 + 800 + 21 + + + + + File + + + + + + + + Help + + + + + + + + + + toolBar + + + TopToolBarArea + + + false + + + + + + + + :/icons/open_file.png:/icons/open_file.png + + + Open file... + + + Open file... + + + Ctrl+O + + + + + + :/icons/zoom_to.png:/icons/zoom_to.png + + + Zoom to extent + + + Zoom to extent + + + + + + :/icons/quit.png:/icons/quit.png + + + Quit + + + Ctrl+Q + + + + + + :/icons/about.png:/icons/about.png + + + About + + + + + + SceneWidget + QOpenGLWidget +
scenewidget.h
+ + zoomToExtent() + +
+
+ + + + + + actionOpenFile + triggered() + MainWindow + showOpenFileDialog() + + + -1 + -1 + + + 399 + 299 + + + + + actionQuit + triggered() + MainWindow + close() + + + -1 + -1 + + + 399 + 299 + + + + + actionZoomToExtent + triggered() + sceneWidget + zoomToExtent() + + + -1 + -1 + + + 399 + 314 + + + + + actionAbout + triggered() + MainWindow + showAboutDialog() + + + -1 + -1 + + + 399 + 299 + + + + + + showOpenFileDialog() + showAboutDialog() + +
diff --git a/particle-track-and-trace/src/main.cpp b/particle-track-and-trace/src/main.cpp index a677041..b49b4f0 100644 --- a/particle-track-and-trace/src/main.cpp +++ b/particle-track-and-trace/src/main.cpp @@ -18,11 +18,58 @@ #include "advection/kernel/RK4AdvectionKernel.h" #include "advection/kernel/SnapBoundaryConditionKernel.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "QT/MainWindow.h" + using namespace std; #define DT 60 * 60 // 60 sec/min * 60 mins -int main() { +int main(int argc, char* argv[]) { + QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat()); + + QApplication app(argc, argv); + + // Main window. + QMainWindow mainWindow; + mainWindow.resize(1200, 900); + + // Control area. + QDockWidget controlDock; + mainWindow.addDockWidget(Qt::LeftDockWidgetArea, &controlDock); + + QLabel controlDockTitle("Control Dock"); + controlDockTitle.setMargin(20); + controlDock.setTitleBarWidget(&controlDockTitle); + + QPointer dockLayout = new QVBoxLayout(); + QWidget layoutContainer; + layoutContainer.setLayout(dockLayout); + controlDock.setWidget(&layoutContainer); + + QPushButton randomizeButton; + randomizeButton.setText("Randomize"); + dockLayout->addWidget(&randomizeButton); + + // Render area. + QPointer vtkRenderWidget = + new QVTKOpenGLNativeWidget(); + mainWindow.setCentralWidget(vtkRenderWidget); + + // VTK part. + vtkNew window; + vtkRenderWidget->setRenderWindow(window.Get()); + + cout << "Reading data..." << endl; string dataPath = "../../../../data"; shared_ptr uvGrid = make_shared(dataPath); @@ -31,19 +78,31 @@ int main() { cout << "Starting vtk..." << endl; auto l = new LGlyphLayer(uvGrid, std::move(kernelRK4BoundaryChecked)); - l->spoofPoints(); + // l->spoofPoints(); l->setDt(DT); // TODO: implement feature to call this function on widget - l->cycleGlyphStyle(); + // l->cycleGlyphStyle(); - unique_ptr program = make_unique(DT); + unique_ptr program = make_unique(DT, window); program->addLayer(new BackgroundImage(dataPath + "/map_qgis_1035.png")); - // program->addLayer(new EGlyphLayer(uvGrid)); + // TODO: implement feature to cycle between layers thru QT + program->addLayer(new EGlyphLayer(uvGrid)); program->addLayer(new EColLayer(uvGrid)); program->addLayer(l); - program->render(); + program->setupInteractions(); - return EXIT_SUCCESS; + // program->render(); + + // Setup initial status. + // std::mt19937 randEng(0); + // ::Randomize(sphere, mapper, window, randEng); + + // connect the buttons + // QObject::connect(&randomizeButton, &QPushButton::released, + // [&]() { ::Randomize(sphere, mapper, window, randEng); }); + + mainWindow.show(); + return app.exec(); }