working ver with QT

This commit is contained in:
Djairo Hougee 2024-05-25 14:35:54 +02:00
parent 7d6b9cb047
commit 4a5b7c4712
7 changed files with 397 additions and 20 deletions

View File

@ -7,6 +7,11 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS 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 find_package(VTK COMPONENTS
GeovisCore GeovisCore
CommonColor CommonColor
@ -72,6 +77,9 @@ add_executable(ParticleTrackTrace MACOSX_BUNDLE main.cpp
advection/Vel.h advection/Vel.h
advection/kernel/SnapBoundaryConditionKernel.h advection/kernel/SnapBoundaryConditionKernel.h
advection/kernel/SnapBoundaryConditionKernel.cpp advection/kernel/SnapBoundaryConditionKernel.cpp
# QT/MainWindow.h
# QT/MainWindow.cpp
# QT/MainWindow.ui
) )
execute_process( 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. # 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.") 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 is needed
vtk_module_autoinit( vtk_module_autoinit(

View File

@ -14,6 +14,7 @@
#include <netcdf> #include <netcdf>
#include <vtkArrowSource.h> #include <vtkArrowSource.h>
#include <vtkNew.h> #include <vtkNew.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkCallbackCommand.h> #include <vtkCallbackCommand.h>
#include <vtkInteractorStyleUser.h> #include <vtkInteractorStyleUser.h>
@ -27,11 +28,11 @@ void Program::setWinProperties() {
this->win->SetSize(661, 661); this->win->SetSize(661, 661);
this->win->SetDesiredUpdateRate(60); this->win->SetDesiredUpdateRate(60);
this->interact->SetRenderWindow(this->win); this->interact->SetRenderWindow(this->win.Get());
this->interact->Initialize(); this->interact->Initialize();
vtkNew<vtkInteractorStyleUser> style; vtkNew<vtkInteractorStyleUser> style;
interact->SetInteractorStyle(style); this->interact->SetInteractorStyle(style);
} }
void Program::setupTimer(int dt) { void Program::setupTimer(int dt) {
@ -50,10 +51,12 @@ void Program::setupCameraCallback() {
this->interact->AddObserver(vtkCommand::KeyPressEvent, callback); this->interact->AddObserver(vtkCommand::KeyPressEvent, callback);
} }
Program::Program(int timerDT, vtkSmartPointer<vtkGenericOpenGLRenderWindow> win) {
Program::Program(int timerDT) { // this->win = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
this->win = vtkSmartPointer<vtkRenderWindow>::New(); this->win = win;
this->interact = vtkSmartPointer<vtkRenderWindowInteractor>::New(); // this->interact = vtkSmartPointer<vtkRenderWindowInteractor>::New();
// this->interact = vtkSmartPointer<QVTKInteractor>::New();
this->interact = win->GetInteractor();
this->cam = createNormalisedCamera(); this->cam = createNormalisedCamera();
this->win->SetNumberOfLayers(0); this->win->SetNumberOfLayers(0);
@ -91,7 +94,7 @@ void Program::updateData(int t) {
void Program::setupInteractions() { void Program::setupInteractions() {
for (Layer *l: layers) { for (Layer *l: layers) {
l->addObservers(interact); l->addObservers(this->interact);
} }
} }

View File

@ -1,6 +1,7 @@
#ifndef PROGRAM_H #ifndef PROGRAM_H
#define PROGRAM_H #define PROGRAM_H
#include <QVTKOpenGLNativeWidget.h>
#include <vtkRenderWindow.h> #include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h> #include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h> #include <vtkRenderer.h>
@ -18,11 +19,13 @@ private:
/** The window this program's layers render to. /** The window this program's layers render to.
*/ */
vtkSmartPointer<vtkRenderWindow> win; // vtkSmartPointer<vtkRenderWindow> win;
vtkSmartPointer<vtkGenericOpenGLRenderWindow> win;
/** The interactor through which the layers can interact with the window. /** The interactor through which the layers can interact with the window.
*/ */
vtkSmartPointer<vtkRenderWindowInteractor> interact; vtkSmartPointer<vtkRenderWindowInteractor> interact;
// vtkSmartPointer<QVTKInteractor> interact;
/** The camera used by all layers for this program. /** The camera used by all layers for this program.
@ -37,9 +40,6 @@ private:
*/ */
void setupTimer(int dt); 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.. /** This function sets up the camera's associated movement callbacks..
*/ */
@ -48,7 +48,7 @@ private:
public: public:
/** Constructor. /** Constructor.
*/ */
Program(int timerDT); Program(int timerDT, vtkSmartPointer<vtkGenericOpenGLRenderWindow> win);
/** This function adds a new layer (and thus vtkRenderer) to the program. /** 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. * The layer is expected to set its own position in the vtkRenderWindow layer system.
@ -68,11 +68,16 @@ public:
*/ */
void updateData(int t); 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. * This function renders the vtkRenderWindow for the first time.
* Only call this function once! * Only call this function once!
*/ */
void render(); void render();
}; };
#endif #endif

View File

@ -0,0 +1,57 @@
#include "MainWindow.h"
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>
#include <vtkDataSetReader.h>
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<vtkDataSetReader> reader = vtkSmartPointer<vtkDataSetReader>::New();
reader->SetFileName(fileName.toStdString().c_str());
// Read the file
reader->Update();
// Add data set to 3D view
vtkSmartPointer<vtkDataSet> dataSet = reader->GetOutput();
if (dataSet != nullptr) {
ui->sceneWidget->addDataSet(reader->GetOutput());
}
}

View File

@ -0,0 +1,35 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
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

View File

@ -0,0 +1,210 @@
<?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>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Qt VTK Viewer</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="0" column="0">
<widget class="SceneWidget" name="sceneWidget"/>
</item>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="actionOpenFile"/>
<addaction name="separator"/>
<addaction name="actionQuit"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string>Help</string>
</property>
<addaction name="actionAbout"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="actionOpenFile"/>
<addaction name="actionZoomToExtent"/>
</widget>
<action name="actionOpenFile">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/icons/open_file.png</normaloff>:/icons/open_file.png</iconset>
</property>
<property name="text">
<string>Open file...</string>
</property>
<property name="toolTip">
<string>Open file...</string>
</property>
<property name="shortcut">
<string>Ctrl+O</string>
</property>
</action>
<action name="actionZoomToExtent">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/icons/zoom_to.png</normaloff>:/icons/zoom_to.png</iconset>
</property>
<property name="text">
<string>Zoom to extent</string>
</property>
<property name="toolTip">
<string>Zoom to extent</string>
</property>
</action>
<action name="actionQuit">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/icons/quit.png</normaloff>:/icons/quit.png</iconset>
</property>
<property name="text">
<string>Quit</string>
</property>
<property name="shortcut">
<string>Ctrl+Q</string>
</property>
</action>
<action name="actionAbout">
<property name="icon">
<iconset resource="resources.qrc">
<normaloff>:/icons/about.png</normaloff>:/icons/about.png</iconset>
</property>
<property name="text">
<string>About</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>
<class>SceneWidget</class>
<extends>QOpenGLWidget</extends>
<header>scenewidget.h</header>
<slots>
<slot>zoomToExtent()</slot>
</slots>
</customwidget>
</customwidgets>
<resources>
<include location="resources.qrc"/>
</resources>
<connections>
<connection>
<sender>actionOpenFile</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>showOpenFileDialog()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>399</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionQuit</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>close()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>399</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionZoomToExtent</sender>
<signal>triggered()</signal>
<receiver>sceneWidget</receiver>
<slot>zoomToExtent()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>399</x>
<y>314</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionAbout</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>showAboutDialog()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>399</x>
<y>299</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>showOpenFileDialog()</slot>
<slot>showAboutDialog()</slot>
</slots>
</ui>

View File

@ -18,11 +18,58 @@
#include "advection/kernel/RK4AdvectionKernel.h" #include "advection/kernel/RK4AdvectionKernel.h"
#include "advection/kernel/SnapBoundaryConditionKernel.h" #include "advection/kernel/SnapBoundaryConditionKernel.h"
#include <QApplication>
#include <QVTKOpenGLNativeWidget.h>
#include <QDockWidget>
#include <QGridLayout>
#include <vtkGenericOpenGLRenderWindow.h>
#include <QLabel>
#include <QMainWindow>
#include <QPointer>
#include <QPushButton>
#include <QVBoxLayout>
#include "QT/MainWindow.h"
using namespace std; using namespace std;
#define DT 60 * 60 // 60 sec/min * 60 mins #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<QVBoxLayout> dockLayout = new QVBoxLayout();
QWidget layoutContainer;
layoutContainer.setLayout(dockLayout);
controlDock.setWidget(&layoutContainer);
QPushButton randomizeButton;
randomizeButton.setText("Randomize");
dockLayout->addWidget(&randomizeButton);
// Render area.
QPointer<QVTKOpenGLNativeWidget> vtkRenderWidget =
new QVTKOpenGLNativeWidget();
mainWindow.setCentralWidget(vtkRenderWidget);
// VTK part.
vtkNew<vtkGenericOpenGLRenderWindow> window;
vtkRenderWidget->setRenderWindow(window.Get());
cout << "Reading data..." << endl; cout << "Reading data..." << endl;
string dataPath = "../../../../data"; string dataPath = "../../../../data";
shared_ptr<UVGrid> uvGrid = make_shared<UVGrid>(dataPath); shared_ptr<UVGrid> uvGrid = make_shared<UVGrid>(dataPath);
@ -31,19 +78,31 @@ int main() {
cout << "Starting vtk..." << endl; cout << "Starting vtk..." << endl;
auto l = new LGlyphLayer(uvGrid, std::move(kernelRK4BoundaryChecked)); auto l = new LGlyphLayer(uvGrid, std::move(kernelRK4BoundaryChecked));
l->spoofPoints(); // l->spoofPoints();
l->setDt(DT); l->setDt(DT);
// TODO: implement feature to call this function on widget // TODO: implement feature to call this function on widget
l->cycleGlyphStyle(); // l->cycleGlyphStyle();
unique_ptr<Program> program = make_unique<Program>(DT); unique_ptr<Program> program = make_unique<Program>(DT, window);
program->addLayer(new BackgroundImage(dataPath + "/map_qgis_1035.png")); 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(new EColLayer(uvGrid));
program->addLayer(l); 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();
} }