diff --git a/particle-track-and-trace/src/CMakeLists.txt b/particle-track-and-trace/src/CMakeLists.txt index ff62643..88ef71d 100644 --- a/particle-track-and-trace/src/CMakeLists.txt +++ b/particle-track-and-trace/src/CMakeLists.txt @@ -54,6 +54,8 @@ add_executable(ParticleTrackTrace MACOSX_BUNDLE main.cpp layers/Layer.h layers/LGlyphLayer.cpp layers/LGlyphLayer.h + layers/Technique.cpp + layers/Technique.h Program.cpp Program.h commands/TimerCallbackCommand.h diff --git a/particle-track-and-trace/src/Program.cpp b/particle-track-and-trace/src/Program.cpp index c75b93e..de2f932 100644 --- a/particle-track-and-trace/src/Program.cpp +++ b/particle-track-and-trace/src/Program.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -53,11 +54,10 @@ void Program::setupCameraCallback() { Program::Program(QWidget *parent): QVTKOpenGLNativeWidget(parent) { this->win = vtkSmartPointer::New(); - // this->interact = vtkSmartPointer::New(); - // this->interact = vtkSmartPointer::New(); setRenderWindow(this->win); this->interact = win->GetInteractor(); this->cam = createNormalisedCamera(); + this->activeIdx = -1; this->win->SetNumberOfLayers(0); setWinProperties(); @@ -66,44 +66,55 @@ Program::Program(QWidget *parent): QVTKOpenGLNativeWidget(parent) { } -void Program::addLayer(Layer *layer) { - layer->setCamera(this->cam); +void Program::addTechnique(Technique *technique) { + this->techniques.push_back(technique); - this->layers.push_back(layer); - this->win->AddRenderer(layer->getLayer()); - this->win->SetNumberOfLayers(this->win->GetNumberOfLayers() + 1); } -void Program::removeLayer(Layer *layer) { - this->win->RemoveRenderer(layer->getLayer()); - - auto it = std::find(this->layers.begin(), this->layers.end(), layer); - if (it != this->layers.end()) { - this->layers.erase(it); - this->win->SetNumberOfLayers(this->win->GetNumberOfLayers() - 1); +void Program::removeTechnique(Technique *technique) { + auto it = std::find(this->techniques.begin(), this->techniques.end(), technique); + if (it != this->techniques.end()) { + int idx = it - this->techniques.begin(); + if (idx == this->activeIdx) { + throw std::out_of_range("Can't remove active technique."); + } + this->techniques.erase(it); + this->activeIdx = -1; + setActiveTechnique(0); } } - void Program::updateData(int t) { + // FIXME: think on how to update techniques; do we update all? just active? unsure. win->Render(); - for (Layer *l: layers) { - l->updateData(t); - } + this->techniques[this->activeIdx]->updateData(t); } -void Program::setupInteractions() { - for (Layer *l: layers) { - l->addObservers(this->interact); +void Program::setActiveTechnique(int idx) { + // Only change things if a different technique has been selected. + if (idx == this->activeIdx) { + return; } + + // check the given idx is valid. + if (idx >= this->techniques.size()) { + throw std::out_of_range("Index out of range!"); + } + + if (this->activeIdx >= 0 and this->activeIdx < this->techniques.size()) + this->techniques[this->activeIdx]->unbind(this->win, this->interact); + + this->techniques[idx]->bind(this->win, this->interact); + + this->activeIdx = idx; } -void Program::render() { - setupInteractions(); - win->Render(); - interact->Start(); -} Program::~Program() { cout << "deleting program" << endl; } + + +vtkSmartPointer Program::getCamera() { + return this->cam; +} diff --git a/particle-track-and-trace/src/Program.h b/particle-track-and-trace/src/Program.h index 60fc6e3..bd259ac 100644 --- a/particle-track-and-trace/src/Program.h +++ b/particle-track-and-trace/src/Program.h @@ -7,6 +7,7 @@ #include #include "layers/Layer.h" +#include "layers/Technique.h" /** This class manages the upper levels of the vtk pipeline; it has attributes for the vtkrenderWindow and a vector of Layers to represent a variable number of vtkRenderers. * It can also set up a vtkTimer by connecting an instance of TimerCallbackCommand with its contained vtkRenderWindowInteractor. @@ -15,19 +16,19 @@ class Program : public QVTKOpenGLNativeWidget { Q_OBJECT private: - /** This attribute models a variable number of vtkRenderers, managed through the abstract Layer class. + /** This attribute models a variable number of vtkRenderers, managed through the abstract Technique class. */ - std::vector layers; + std::vector techniques; + int activeIdx; + /** The window this program's layers render to. */ - // 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. @@ -53,33 +54,30 @@ public: Program(QWidget *parent = nullptr); ~Program() override; - /** 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. - * @param layer : pointer to the layer to add. + /** This function adds a new technique to the program. + * The technique is expected to manage the layers itself in the vtkRenderWindow layer system. + * @param technique : pointer to the technique to add. */ - void addLayer(Layer *layer); + void addTechnique(Technique *technique); /** This function removes a given layer from the vtkRenderWindow and layers vector. * If the given layer is not actually in the program, nothing happens. - * @param layer : the layer to removeLayer + * @param layer : the layer to removeTechnique */ - void removeLayer(Layer *layer); + void removeTechnique(Technique *layer); - /** This function updates the data for the associated layers to the given timestamp. + /** This function updates the data for the associated techniques to the given timestamp. * Also updates the renderWindow. * @param t : the timestamp to update the data to. */ 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(); + // TODO: using an idx to indicate which technique to use is not ideal; use an enum instead? But then the question is where to put it... + void setActiveTechnique(int idx); + + + vtkSmartPointer getCamera(); }; diff --git a/particle-track-and-trace/src/QT/MainWindow.cpp b/particle-track-and-trace/src/QT/MainWindow.cpp index 3a5afee..014f441 100644 --- a/particle-track-and-trace/src/QT/MainWindow.cpp +++ b/particle-track-and-trace/src/QT/MainWindow.cpp @@ -18,32 +18,11 @@ using namespace std; MainWindow::MainWindow(QWidget* parent) - : QMainWindow(parent) - , ui(new Ui::MainWindow) + : QMainWindow(parent) + , ui(new Ui::MainWindow) { - ui->setupUi(this); - - cout << "Reading data..." << endl; - string dataPath = "../../../../data"; - shared_ptr uvGrid = make_shared(dataPath); - auto kernelRK4 = make_unique(uvGrid); - auto kernelRK4BoundaryChecked = make_unique(std::move(kernelRK4), uvGrid); - cout << "Starting vtk..." << endl; - - auto l = new LGlyphLayer(uvGrid, std::move(kernelRK4BoundaryChecked)); - // l->spoofPoints(); - l->setDt(3600); - // TODO: implement feature to call this function on widget - // l->cycleGlyphStyle(); - - Program *program = this->ui->program; - program->addLayer(new BackgroundImage(dataPath + "/map_qgis_1035.png")); - // TODO: implement feature to cycle between layers thru QT - program->addLayer(new EGlyphLayer(uvGrid)); - program->addLayer(new EColLayer(uvGrid)); - program->addLayer(l); - - program->setupInteractions(); + ui->setupUi(this); + this->setupTechniques(); } MainWindow::~MainWindow() { @@ -51,6 +30,50 @@ MainWindow::~MainWindow() { } +void MainWindow::setupTechniques() { + cout << "Reading data..." << endl; + string dataPath = "../../../../data"; + shared_ptr uvGrid = make_shared(dataPath); + + // initialize techniques + Program *program = this->ui->program; + auto technique1 = new Technique(program->getCamera()); + auto technique2 = new Technique(program->getCamera()); + + // add bg layer + auto bg = new BackgroundImage(dataPath + "/map_qgis_1035.png"); + technique1->addLayer(bg); + technique2->addLayer(bg); + + // add Euler layers + technique1->addLayer(new EColLayer(uvGrid)); + technique2->addLayer(new EGlyphLayer(uvGrid)); + + // setup LGlyphLayer + auto kernelRK4 = make_unique(uvGrid); + auto kernelRK4BoundaryChecked = make_unique(std::move(kernelRK4), uvGrid); + auto lGlyph = new LGlyphLayer(uvGrid, std::move(kernelRK4BoundaryChecked)); + lGlyph->setDt(3600); + + technique1->addLayer(lGlyph); + // technique2->addLayer(new LColLayer(uvGrid)); // TODO: add LColLayer + technique2->addLayer(lGlyph); + + cout << technique1->numberOfLayers() << endl; + + program->addTechnique(technique1); + program->addTechnique(technique2); + + program->setActiveTechnique(0); + + // TODO: implement feature to call this function on widget + // l->spoofPoints(); + // l->cycleGlyphStyle(); + + +} + + /* -------------------------------------------------------------------- * + QTWidget callbacks + * --------------------------------------------------------------------*/ diff --git a/particle-track-and-trace/src/QT/MainWindow.h b/particle-track-and-trace/src/QT/MainWindow.h index ef9a5cf..32516a7 100644 --- a/particle-track-and-trace/src/QT/MainWindow.h +++ b/particle-track-and-trace/src/QT/MainWindow.h @@ -2,17 +2,18 @@ #define MAINWINDOW_H #include +#include "../advection/UVGrid.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { - Q_OBJECT + Q_OBJECT public: - explicit MainWindow(QWidget* parent = 0); - ~MainWindow(); + explicit MainWindow(QWidget* parent = 0); + ~MainWindow(); private slots: void on_FirstButton_clicked(bool checked); @@ -31,7 +32,9 @@ private slots: void on_IregularlySubsampledButton_clicked(bool checked); private: - Ui::MainWindow* ui; + Ui::MainWindow* ui; + + void setupTechniques(); }; #endif diff --git a/particle-track-and-trace/src/layers/LColLayer.cpp b/particle-track-and-trace/src/layers/LColLayer.cpp index 5dbd57b..f3d2eb5 100644 --- a/particle-track-and-trace/src/layers/LColLayer.cpp +++ b/particle-track-and-trace/src/layers/LColLayer.cpp @@ -173,6 +173,10 @@ void LGlyphLayer::addObservers(vtkSmartPointer intera interactor->AddObserver(vtkCommand::MouseMoveEvent, newPointCallBack); } +void LGlyphLayer::removeObservers(vtkSmartPointer interactor) { + // todo: logic for these +} + void LGlyphLayer::setDt(int dt) { this->dt = dt; diff --git a/particle-track-and-trace/src/layers/LColLayer.h b/particle-track-and-trace/src/layers/LColLayer.h index 79ede1f..0ae5a4c 100644 --- a/particle-track-and-trace/src/layers/LColLayer.h +++ b/particle-track-and-trace/src/layers/LColLayer.h @@ -40,6 +40,7 @@ public: vtkSmartPointer createSpawnPointCallback(); void addObservers(vtkSmartPointer interactor) override; + void removeObservers(vtkSmartPointer interactor) override; /** diff --git a/particle-track-and-trace/src/layers/LGlyphLayer.cpp b/particle-track-and-trace/src/layers/LGlyphLayer.cpp index 311a2f7..170b3f9 100644 --- a/particle-track-and-trace/src/layers/LGlyphLayer.cpp +++ b/particle-track-and-trace/src/layers/LGlyphLayer.cpp @@ -21,7 +21,7 @@ #include "../CartographicTransformation.h" vtkSmartPointer LGlyphLayer::createSpawnPointCallback() { - auto newPointCallBack = vtkSmartPointer::New(); + vtkNew newPointCallBack; newPointCallBack->setData(this->data); newPointCallBack->setPoints(this->points); newPointCallBack->setRen(this->ren); @@ -137,6 +137,8 @@ LGlyphLayer::LGlyphLayer(std::shared_ptr uvGrid, std::unique_ptrSetMapper(this->mapper); this->ren->AddActor(actor); + + this->callback = createSpawnPointCallback(); } void LGlyphLayer::spoofPoints() { @@ -199,10 +201,15 @@ void LGlyphLayer::updateData(int t) { } void LGlyphLayer::addObservers(vtkSmartPointer interactor) { - auto newPointCallBack = createSpawnPointCallback(); - interactor->AddObserver(vtkCommand::LeftButtonPressEvent, newPointCallBack); - interactor->AddObserver(vtkCommand::LeftButtonReleaseEvent, newPointCallBack); - interactor->AddObserver(vtkCommand::MouseMoveEvent, newPointCallBack); + interactor->AddObserver(vtkCommand::LeftButtonPressEvent, this->callback); + interactor->AddObserver(vtkCommand::LeftButtonReleaseEvent, this->callback); + interactor->AddObserver(vtkCommand::MouseMoveEvent, this->callback); +} + +void LGlyphLayer::removeObservers(vtkSmartPointer interactor) { + interactor->RemoveObserver(this->callback); + interactor->RemoveObserver(this->callback); + interactor->RemoveObserver(this->callback); } diff --git a/particle-track-and-trace/src/layers/LGlyphLayer.h b/particle-track-and-trace/src/layers/LGlyphLayer.h index e15d0f1..2c1dc4d 100644 --- a/particle-track-and-trace/src/layers/LGlyphLayer.h +++ b/particle-track-and-trace/src/layers/LGlyphLayer.h @@ -23,6 +23,7 @@ private: int dt = 3600; int beachedAtNumberOfTimes = 20; std::queue> luts; + vtkSmartPointer callback; public: /** Constructor. @@ -43,6 +44,7 @@ public: vtkSmartPointer createSpawnPointCallback(); void addObservers(vtkSmartPointer interactor) override; + void removeObservers(vtkSmartPointer interactor) override; /** This function cycles which lut is used for the layer, according to the lookuptables in the luts attribute. */ diff --git a/particle-track-and-trace/src/layers/Layer.cpp b/particle-track-and-trace/src/layers/Layer.cpp index e7a156d..df1c0c9 100644 --- a/particle-track-and-trace/src/layers/Layer.cpp +++ b/particle-track-and-trace/src/layers/Layer.cpp @@ -1,5 +1,6 @@ #include "Layer.h" #include +#include #include using std::string; @@ -16,7 +17,10 @@ void Layer::addObservers(vtkSmartPointer interactor) // By default, do nothing } - -void Layer::setCamera(vtkCamera *camera) { - this->getLayer()->SetActiveCamera(camera); +void Layer::removeObservers(vtkSmartPointer interactor) { + // By default, do nothing +} + +void Layer::setCamera(vtkSmartPointer cam) { + this->getLayer()->SetActiveCamera(cam.GetPointer()); } diff --git a/particle-track-and-trace/src/layers/Layer.h b/particle-track-and-trace/src/layers/Layer.h index fd20823..4594f9a 100644 --- a/particle-track-and-trace/src/layers/Layer.h +++ b/particle-track-and-trace/src/layers/Layer.h @@ -28,10 +28,16 @@ public: */ virtual void addObservers(vtkSmartPointer interactor); + + /** Removes observers to the renderWindowinteractor within which this layer is active. + * @param interactor : pointer to the interactor that observers can be removed from. + */ + virtual void removeObservers(vtkSmartPointer interactor); + /** Sets the active camera for the vtkRenderer associated with this layer. * Used to share one camera between multiple layers. */ - virtual void setCamera(vtkCamera *camera); + virtual void setCamera(vtkSmartPointer cam); }; #endif diff --git a/particle-track-and-trace/src/layers/Technique.cpp b/particle-track-and-trace/src/layers/Technique.cpp new file mode 100644 index 0000000..e9221ff --- /dev/null +++ b/particle-track-and-trace/src/layers/Technique.cpp @@ -0,0 +1,50 @@ +#include + +#include "Technique.h" + +Technique::Technique(vtkSmartPointer cam) : cam(cam) {} + + +void Technique::addLayer(Layer *l) { + l->setCamera(this->cam); + this->layers.push_back(l); +} + + +void Technique::removeLayer(Layer *l) { + auto it = std::find(this->layers.begin(), this->layers.end(), l); + if (it != this->layers.end()) { + this->layers.erase(it); + } +} + + +void Technique::updateData(int t) { + for (Layer *l : this->layers) { + l->updateData(t); + } +} + + +int Technique::numberOfLayers() { + return this->layers.size(); +} + + +void Technique::bind(vtkSmartPointer win, vtkSmartPointer intr) { + for (Layer *l : this->layers) { + l->addObservers(intr); + win->AddRenderer(l->getLayer()); + } + win->SetNumberOfLayers(this->layers.size()); + // win->Render(); +} + + +void Technique::unbind(vtkSmartPointer win, vtkSmartPointer intr) { + for (Layer *l : this->layers) { + l->removeObservers(intr); + win->RemoveRenderer(l->getLayer()); + } + win->SetNumberOfLayers(0); +} diff --git a/particle-track-and-trace/src/layers/Technique.h b/particle-track-and-trace/src/layers/Technique.h new file mode 100644 index 0000000..4027f09 --- /dev/null +++ b/particle-track-and-trace/src/layers/Technique.h @@ -0,0 +1,25 @@ +#ifndef TECHNIQUE_H +#define TECHNIQUE_H + +#include "Layer.h" +#include +#include +class Technique { +private: + std::vector layers; + vtkSmartPointer cam; + +public: + Technique(vtkSmartPointer cam); + void addLayer(Layer *l); + void removeLayer(Layer *l); + void updateData(int t); + int numberOfLayers(); + void bind(vtkSmartPointer win, vtkSmartPointer intr); + void unbind(vtkSmartPointer win, vtkSmartPointer intr); + +}; + + + +#endif diff --git a/particle-track-and-trace/src/main.cpp b/particle-track-and-trace/src/main.cpp index 6140a84..1232dbe 100644 --- a/particle-track-and-trace/src/main.cpp +++ b/particle-track-and-trace/src/main.cpp @@ -1,49 +1,16 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "layers/BackgroundImage.h" -#include "layers/EColLayer.h" -#include "layers/EGlyphLayer.h" -#include "layers/LGlyphLayer.h" -#include "Program.h" -#include "advection/UVGrid.h" -#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 argc, char* argv[]) { QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat()); QApplication app(argc, argv); - // Main window. - MainWindow mainWindow; - mainWindow.resize(1200, 900); + MainWindow w; + w.resize(1200, 900); - mainWindow.show(); + w.show(); return app.exec(); } diff --git a/particle-track-and-trace/src/technique.cpp b/particle-track-and-trace/src/technique.cpp deleted file mode 100644 index e69de29..0000000 diff --git a/particle-track-and-trace/src/technique.h b/particle-track-and-trace/src/technique.h deleted file mode 100644 index e43888a..0000000 --- a/particle-track-and-trace/src/technique.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef TECHNIQUE_H -#define TECHNIQUE_H - -#include "layers/Layer.h" -#include -class Technique { -private: - std::vector layers; - vtkSmartPointer points; - vtkSmartPointer data; - - void setupInteractions(); - -public: - Technique(); - void addLayer(Layer *l); - void removeLayer(Layer *l); - void updateData(int t); - int numberOfLayers(); - -}; - - - -#endif