Merge branch 'main' into feat/swap-techniques
This commit is contained in:
commit
8f4dd0afc2
|
|
@ -5,8 +5,14 @@ project(ParticleTrackTrace)
|
|||
set(CMAKE_CXX_STANDARD 23)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CMAKE_AUTOMOC 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
|
||||
|
|
@ -48,8 +54,6 @@ add_executable(ParticleTrackTrace MACOSX_BUNDLE main.cpp
|
|||
layers/Layer.h
|
||||
layers/LGlyphLayer.cpp
|
||||
layers/LGlyphLayer.h
|
||||
layers/LColLayer.cpp
|
||||
layers/LColLayer.h
|
||||
Program.cpp
|
||||
Program.h
|
||||
commands/TimerCallbackCommand.h
|
||||
|
|
@ -74,6 +78,10 @@ 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
|
||||
QT/ui_mainwindow.h
|
||||
)
|
||||
|
||||
execute_process(
|
||||
|
|
@ -94,7 +102,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(
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <netcdf>
|
||||
#include <vtkArrowSource.h>
|
||||
#include <vtkNew.h>
|
||||
#include <vtkGenericOpenGLRenderWindow.h>
|
||||
#include <vtkCallbackCommand.h>
|
||||
#include <vtkInteractorStyleUser.h>
|
||||
|
||||
|
|
@ -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<vtkInteractorStyleUser> style;
|
||||
interact->SetInteractorStyle(style);
|
||||
this->interact->SetInteractorStyle(style);
|
||||
}
|
||||
|
||||
void Program::setupTimer(int dt) {
|
||||
|
|
@ -50,15 +51,17 @@ void Program::setupCameraCallback() {
|
|||
this->interact->AddObserver(vtkCommand::KeyPressEvent, callback);
|
||||
}
|
||||
|
||||
|
||||
Program::Program(int timerDT) {
|
||||
this->win = vtkSmartPointer<vtkRenderWindow>::New();
|
||||
this->interact = vtkSmartPointer<vtkRenderWindowInteractor>::New();
|
||||
Program::Program(QWidget *parent): QVTKOpenGLNativeWidget(parent) {
|
||||
this->win = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
|
||||
// this->interact = vtkSmartPointer<vtkRenderWindowInteractor>::New();
|
||||
// this->interact = vtkSmartPointer<QVTKInteractor>::New();
|
||||
setRenderWindow(this->win);
|
||||
this->interact = win->GetInteractor();
|
||||
this->cam = createNormalisedCamera();
|
||||
|
||||
this->win->SetNumberOfLayers(0);
|
||||
setWinProperties();
|
||||
setupTimer(timerDT);
|
||||
setupTimer(60 * 60); // FIXME: manually tracking this variable is a little stupid.
|
||||
setupCameraCallback();
|
||||
}
|
||||
|
||||
|
|
@ -91,7 +94,7 @@ void Program::updateData(int t) {
|
|||
|
||||
void Program::setupInteractions() {
|
||||
for (Layer *l: layers) {
|
||||
l->addObservers(interact);
|
||||
l->addObservers(this->interact);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -100,3 +103,7 @@ void Program::render() {
|
|||
win->Render();
|
||||
interact->Start();
|
||||
}
|
||||
|
||||
Program::~Program() {
|
||||
cout << "deleting program" << endl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef PROGRAM_H
|
||||
#define PROGRAM_H
|
||||
|
||||
#include <QVTKOpenGLNativeWidget.h>
|
||||
#include <vtkRenderWindow.h>
|
||||
#include <vtkRenderWindowInteractor.h>
|
||||
#include <vtkRenderer.h>
|
||||
|
|
@ -10,7 +11,9 @@
|
|||
/** 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.
|
||||
*/
|
||||
class Program {
|
||||
class Program : public QVTKOpenGLNativeWidget {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
/** This attribute models a variable number of vtkRenderers, managed through the abstract Layer class.
|
||||
*/
|
||||
|
|
@ -18,11 +21,13 @@ private:
|
|||
|
||||
/** 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.
|
||||
*/
|
||||
vtkSmartPointer<vtkRenderWindowInteractor> interact;
|
||||
// vtkSmartPointer<QVTKInteractor> interact;
|
||||
|
||||
|
||||
/** The camera used by all layers for this program.
|
||||
|
|
@ -37,9 +42,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 +50,8 @@ private:
|
|||
public:
|
||||
/** Constructor.
|
||||
*/
|
||||
Program(int timerDT);
|
||||
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.
|
||||
|
|
@ -68,11 +71,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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,156 @@
|
|||
#include "MainWindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include <vtkDataSetReader.h>
|
||||
|
||||
#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"
|
||||
using namespace std;
|
||||
|
||||
MainWindow::MainWindow(QWidget* parent)
|
||||
: QMainWindow(parent)
|
||||
, ui(new Ui::MainWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
cout << "Reading data..." << endl;
|
||||
string dataPath = "../../../../data";
|
||||
shared_ptr<UVGrid> uvGrid = make_shared<UVGrid>(dataPath);
|
||||
auto kernelRK4 = make_unique<RK4AdvectionKernel>(uvGrid);
|
||||
auto kernelRK4BoundaryChecked = make_unique<SnapBoundaryConditionKernel>(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();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------
|
||||
* + QTWidget callbacks +
|
||||
* --------------------------------------------------------------------*/
|
||||
|
||||
|
||||
void MainWindow::on_FirstButton_clicked(bool checked) {
|
||||
if (checked) {
|
||||
cout << "clicked button 1!" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_SecondButton_clicked(bool checked) {
|
||||
if (checked) {
|
||||
cout << "clicked button 2!" << endl;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_ComplementaryButton_clicked(bool checked) {
|
||||
if (checked) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_ContrastingButton_clicked(bool checked) {
|
||||
if (checked) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_MonochromaticButton_clicked(bool checked) {
|
||||
if (checked) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_SaturateButton_clicked(bool checked) {
|
||||
if (checked) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_DesaturateButton_clicked(bool checked) {
|
||||
if (checked) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_CircleButton_clicked(bool checked) {
|
||||
if (checked) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_TriangleButton_clicked(bool checked) {
|
||||
if (checked) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_SquareButton_clicked(bool checked) {
|
||||
if (checked) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_HexagonButton_clicked(bool checked) {
|
||||
if (checked) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_FullySampledButton_clicked(bool checked) {
|
||||
if (checked) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_RegularlySubsampledButton_clicked(bool checked) {
|
||||
if (checked) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::on_IregularlySubsampledButton_clicked(bool checked) {
|
||||
if (checked) {
|
||||
|
||||
}}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#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();
|
||||
|
||||
private slots:
|
||||
void on_FirstButton_clicked(bool checked);
|
||||
void on_SecondButton_clicked(bool checked);
|
||||
void on_ComplementaryButton_clicked(bool checked);
|
||||
void on_ContrastingButton_clicked(bool checked);
|
||||
void on_MonochromaticButton_clicked(bool checked);
|
||||
void on_SaturateButton_clicked(bool checked);
|
||||
void on_DesaturateButton_clicked(bool checked);
|
||||
void on_CircleButton_clicked(bool checked);
|
||||
void on_TriangleButton_clicked(bool checked);
|
||||
void on_SquareButton_clicked(bool checked);
|
||||
void on_HexagonButton_clicked(bool checked);
|
||||
void on_FullySampledButton_clicked(bool checked);
|
||||
void on_RegularlySubsampledButton_clicked(bool checked);
|
||||
void on_IregularlySubsampledButton_clicked(bool checked);
|
||||
|
||||
private:
|
||||
Ui::MainWindow* ui;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,355 @@
|
|||
<?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>1048</width>
|
||||
<height>772</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Simulation</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="settingsBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>220</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>280</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Settings</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="TechniqueBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Technique</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="FirstButton">
|
||||
<property name="text">
|
||||
<string>ECol + LGlyph</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="SecondButton">
|
||||
<property name="text">
|
||||
<string>EGlyph + LCol</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="ChannelBox">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>550</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Channel Options</string>
|
||||
</property>
|
||||
<widget class="QGroupBox" name="ColourBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>30</y>
|
||||
<width>300</width>
|
||||
<height>120</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>120</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Color</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="ComplementaryButton">
|
||||
<property name="text">
|
||||
<string>Complementary </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="ContrastingButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Contrasting</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="MonochromaticButton">
|
||||
<property name="text">
|
||||
<string>Monochromatic</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="SaturationBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>160</y>
|
||||
<width>269</width>
|
||||
<height>100</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>260</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Saturation</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="SaturateButton">
|
||||
<property name="text">
|
||||
<string>Fully saturated</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="DesaturateButton">
|
||||
<property name="text">
|
||||
<string>Desaturated</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="GlyphBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>270</y>
|
||||
<width>260</width>
|
||||
<height>150</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>260</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>150</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Glyph Shape</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_14">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_10">
|
||||
<property name="text">
|
||||
<string>Circle</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_11">
|
||||
<property name="text">
|
||||
<string>Triangle</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_12">
|
||||
<property name="text">
|
||||
<string>Square</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton">
|
||||
<property name="text">
|
||||
<string>Hexagon</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="GlyphBox_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>430</y>
|
||||
<width>260</width>
|
||||
<height>120</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>260</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>500</width>
|
||||
<height>120</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Glyph count</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_13">
|
||||
<property name="text">
|
||||
<string>Fully sampled</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_14">
|
||||
<property name="text">
|
||||
<string>Regularly subsampled</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioButton_15">
|
||||
<property name="text">
|
||||
<string>Irregularly sampled</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Program" name="program"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>MainView</class>
|
||||
<extends>QVTKOpenGLNativeWidget</extends>
|
||||
<header location="global">Program.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
|
@ -0,0 +1,278 @@
|
|||
/********************************************************************************
|
||||
** Form generated from reading UI file 'MainWindow.ui'
|
||||
**
|
||||
** Created by: Qt User Interface Compiler version 5.15.13
|
||||
**
|
||||
** WARNING! All changes made in this file will be lost when recompiling UI file!
|
||||
********************************************************************************/
|
||||
|
||||
#ifndef UI_MAINWINDOW_H
|
||||
#define UI_MAINWINDOW_H
|
||||
|
||||
#include "../Program.h"
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtWidgets/QGroupBox>
|
||||
#include <QtWidgets/QHBoxLayout>
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#include <QtWidgets/QRadioButton>
|
||||
#include <QtWidgets/QVBoxLayout>
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class Ui_MainWindow
|
||||
{
|
||||
public:
|
||||
QWidget *centralWidget;
|
||||
QHBoxLayout *horizontalLayout;
|
||||
QGroupBox *settingsBox;
|
||||
QVBoxLayout *verticalLayout_3;
|
||||
QGroupBox *TechniqueBox;
|
||||
QVBoxLayout *verticalLayout_2;
|
||||
QRadioButton *FirstButton;
|
||||
QRadioButton *SecondButton;
|
||||
QGroupBox *ChannelBox;
|
||||
QGroupBox *ColourBox;
|
||||
QVBoxLayout *verticalLayout_12;
|
||||
QRadioButton *ComplementaryButton;
|
||||
QRadioButton *ContrastingButton;
|
||||
QRadioButton *MonochromaticButton;
|
||||
QGroupBox *SaturationBox;
|
||||
QVBoxLayout *verticalLayout_13;
|
||||
QRadioButton *SaturateButton;
|
||||
QRadioButton *DesaturateButton;
|
||||
QGroupBox *GlyphBox;
|
||||
QVBoxLayout *verticalLayout_14;
|
||||
QRadioButton *CircleButton;
|
||||
QRadioButton *TriangleButton;
|
||||
QRadioButton *SquareButton;
|
||||
QRadioButton *HexagonButton;
|
||||
QGroupBox *GlyphBox_2;
|
||||
QVBoxLayout *verticalLayout_16;
|
||||
QRadioButton *FullySampledButton;
|
||||
QRadioButton *RegularlySubsampledButton;
|
||||
QRadioButton *IregularlySubsampledButton;
|
||||
Program *program;
|
||||
|
||||
void setupUi(QMainWindow *MainWindow)
|
||||
{
|
||||
if (MainWindow->objectName().isEmpty())
|
||||
MainWindow->setObjectName(QString::fromUtf8("MainWindow"));
|
||||
MainWindow->resize(1048, 772);
|
||||
centralWidget = new QWidget(MainWindow);
|
||||
centralWidget->setObjectName(QString::fromUtf8("centralWidget"));
|
||||
horizontalLayout = new QHBoxLayout(centralWidget);
|
||||
horizontalLayout->setSpacing(6);
|
||||
horizontalLayout->setContentsMargins(11, 11, 11, 11);
|
||||
horizontalLayout->setObjectName(QString::fromUtf8("horizontalLayout"));
|
||||
settingsBox = new QGroupBox(centralWidget);
|
||||
settingsBox->setObjectName(QString::fromUtf8("settingsBox"));
|
||||
QSizePolicy sizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
|
||||
sizePolicy.setHorizontalStretch(0);
|
||||
sizePolicy.setVerticalStretch(0);
|
||||
sizePolicy.setHeightForWidth(settingsBox->sizePolicy().hasHeightForWidth());
|
||||
settingsBox->setSizePolicy(sizePolicy);
|
||||
settingsBox->setMinimumSize(QSize(220, 0));
|
||||
settingsBox->setMaximumSize(QSize(280, 16777215));
|
||||
verticalLayout_3 = new QVBoxLayout(settingsBox);
|
||||
verticalLayout_3->setSpacing(6);
|
||||
verticalLayout_3->setContentsMargins(11, 11, 11, 11);
|
||||
verticalLayout_3->setObjectName(QString::fromUtf8("verticalLayout_3"));
|
||||
TechniqueBox = new QGroupBox(settingsBox);
|
||||
TechniqueBox->setObjectName(QString::fromUtf8("TechniqueBox"));
|
||||
sizePolicy.setHeightForWidth(TechniqueBox->sizePolicy().hasHeightForWidth());
|
||||
TechniqueBox->setSizePolicy(sizePolicy);
|
||||
TechniqueBox->setMinimumSize(QSize(0, 0));
|
||||
TechniqueBox->setMaximumSize(QSize(500, 100));
|
||||
verticalLayout_2 = new QVBoxLayout(TechniqueBox);
|
||||
verticalLayout_2->setSpacing(6);
|
||||
verticalLayout_2->setContentsMargins(11, 11, 11, 11);
|
||||
verticalLayout_2->setObjectName(QString::fromUtf8("verticalLayout_2"));
|
||||
FirstButton = new QRadioButton(TechniqueBox);
|
||||
FirstButton->setObjectName(QString::fromUtf8("FirstButton"));
|
||||
FirstButton->setChecked(true);
|
||||
|
||||
verticalLayout_2->addWidget(FirstButton);
|
||||
|
||||
SecondButton = new QRadioButton(TechniqueBox);
|
||||
SecondButton->setObjectName(QString::fromUtf8("SecondButton"));
|
||||
SecondButton->setChecked(false);
|
||||
|
||||
verticalLayout_2->addWidget(SecondButton);
|
||||
|
||||
|
||||
verticalLayout_3->addWidget(TechniqueBox);
|
||||
|
||||
ChannelBox = new QGroupBox(settingsBox);
|
||||
ChannelBox->setObjectName(QString::fromUtf8("ChannelBox"));
|
||||
ChannelBox->setMinimumSize(QSize(0, 550));
|
||||
ColourBox = new QGroupBox(ChannelBox);
|
||||
ColourBox->setObjectName(QString::fromUtf8("ColourBox"));
|
||||
ColourBox->setGeometry(QRect(0, 30, 300, 120));
|
||||
sizePolicy.setHeightForWidth(ColourBox->sizePolicy().hasHeightForWidth());
|
||||
ColourBox->setSizePolicy(sizePolicy);
|
||||
ColourBox->setMinimumSize(QSize(250, 0));
|
||||
ColourBox->setMaximumSize(QSize(500, 120));
|
||||
ColourBox->setAlignment(Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter);
|
||||
verticalLayout_12 = new QVBoxLayout(ColourBox);
|
||||
verticalLayout_12->setSpacing(6);
|
||||
verticalLayout_12->setContentsMargins(11, 11, 11, 11);
|
||||
verticalLayout_12->setObjectName(QString::fromUtf8("verticalLayout_12"));
|
||||
ComplementaryButton = new QRadioButton(ColourBox);
|
||||
ComplementaryButton->setObjectName(QString::fromUtf8("ComplementaryButton"));
|
||||
|
||||
verticalLayout_12->addWidget(ComplementaryButton);
|
||||
|
||||
ContrastingButton = new QRadioButton(ColourBox);
|
||||
ContrastingButton->setObjectName(QString::fromUtf8("ContrastingButton"));
|
||||
QSizePolicy sizePolicy1(QSizePolicy::Maximum, QSizePolicy::Fixed);
|
||||
sizePolicy1.setHorizontalStretch(0);
|
||||
sizePolicy1.setVerticalStretch(0);
|
||||
sizePolicy1.setHeightForWidth(ContrastingButton->sizePolicy().hasHeightForWidth());
|
||||
ContrastingButton->setSizePolicy(sizePolicy1);
|
||||
|
||||
verticalLayout_12->addWidget(ContrastingButton);
|
||||
|
||||
MonochromaticButton = new QRadioButton(ColourBox);
|
||||
MonochromaticButton->setObjectName(QString::fromUtf8("MonochromaticButton"));
|
||||
|
||||
verticalLayout_12->addWidget(MonochromaticButton);
|
||||
|
||||
SaturationBox = new QGroupBox(ChannelBox);
|
||||
SaturationBox->setObjectName(QString::fromUtf8("SaturationBox"));
|
||||
SaturationBox->setGeometry(QRect(0, 160, 269, 100));
|
||||
sizePolicy.setHeightForWidth(SaturationBox->sizePolicy().hasHeightForWidth());
|
||||
SaturationBox->setSizePolicy(sizePolicy);
|
||||
SaturationBox->setMinimumSize(QSize(260, 0));
|
||||
SaturationBox->setMaximumSize(QSize(500, 100));
|
||||
SaturationBox->setAlignment(Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter);
|
||||
verticalLayout_13 = new QVBoxLayout(SaturationBox);
|
||||
verticalLayout_13->setSpacing(6);
|
||||
verticalLayout_13->setContentsMargins(11, 11, 11, 11);
|
||||
verticalLayout_13->setObjectName(QString::fromUtf8("verticalLayout_13"));
|
||||
SaturateButton = new QRadioButton(SaturationBox);
|
||||
SaturateButton->setObjectName(QString::fromUtf8("SaturateButton"));
|
||||
|
||||
verticalLayout_13->addWidget(SaturateButton);
|
||||
|
||||
DesaturateButton = new QRadioButton(SaturationBox);
|
||||
DesaturateButton->setObjectName(QString::fromUtf8("DesaturateButton"));
|
||||
|
||||
verticalLayout_13->addWidget(DesaturateButton);
|
||||
|
||||
GlyphBox = new QGroupBox(ChannelBox);
|
||||
GlyphBox->setObjectName(QString::fromUtf8("GlyphBox"));
|
||||
GlyphBox->setGeometry(QRect(0, 270, 260, 150));
|
||||
sizePolicy.setHeightForWidth(GlyphBox->sizePolicy().hasHeightForWidth());
|
||||
GlyphBox->setSizePolicy(sizePolicy);
|
||||
GlyphBox->setMinimumSize(QSize(260, 0));
|
||||
GlyphBox->setMaximumSize(QSize(500, 150));
|
||||
GlyphBox->setAlignment(Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter);
|
||||
verticalLayout_14 = new QVBoxLayout(GlyphBox);
|
||||
verticalLayout_14->setSpacing(6);
|
||||
verticalLayout_14->setContentsMargins(11, 11, 11, 11);
|
||||
verticalLayout_14->setObjectName(QString::fromUtf8("verticalLayout_14"));
|
||||
CircleButton = new QRadioButton(GlyphBox);
|
||||
CircleButton->setObjectName(QString::fromUtf8("CircleButton"));
|
||||
|
||||
verticalLayout_14->addWidget(CircleButton);
|
||||
|
||||
TriangleButton = new QRadioButton(GlyphBox);
|
||||
TriangleButton->setObjectName(QString::fromUtf8("TriangleButton"));
|
||||
|
||||
verticalLayout_14->addWidget(TriangleButton);
|
||||
|
||||
SquareButton = new QRadioButton(GlyphBox);
|
||||
SquareButton->setObjectName(QString::fromUtf8("SquareButton"));
|
||||
|
||||
verticalLayout_14->addWidget(SquareButton);
|
||||
|
||||
HexagonButton = new QRadioButton(GlyphBox);
|
||||
HexagonButton->setObjectName(QString::fromUtf8("HexagonButton"));
|
||||
|
||||
verticalLayout_14->addWidget(HexagonButton);
|
||||
|
||||
GlyphBox_2 = new QGroupBox(ChannelBox);
|
||||
GlyphBox_2->setObjectName(QString::fromUtf8("GlyphBox_2"));
|
||||
GlyphBox_2->setGeometry(QRect(0, 430, 260, 120));
|
||||
QSizePolicy sizePolicy2(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
sizePolicy2.setHorizontalStretch(0);
|
||||
sizePolicy2.setVerticalStretch(0);
|
||||
sizePolicy2.setHeightForWidth(GlyphBox_2->sizePolicy().hasHeightForWidth());
|
||||
GlyphBox_2->setSizePolicy(sizePolicy2);
|
||||
GlyphBox_2->setMinimumSize(QSize(260, 0));
|
||||
GlyphBox_2->setMaximumSize(QSize(500, 120));
|
||||
GlyphBox_2->setAlignment(Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter);
|
||||
verticalLayout_16 = new QVBoxLayout(GlyphBox_2);
|
||||
verticalLayout_16->setSpacing(6);
|
||||
verticalLayout_16->setContentsMargins(11, 11, 11, 11);
|
||||
verticalLayout_16->setObjectName(QString::fromUtf8("verticalLayout_16"));
|
||||
FullySampledButton = new QRadioButton(GlyphBox_2);
|
||||
FullySampledButton->setObjectName(QString::fromUtf8("FullySampledButton"));
|
||||
|
||||
verticalLayout_16->addWidget(FullySampledButton);
|
||||
|
||||
RegularlySubsampledButton = new QRadioButton(GlyphBox_2);
|
||||
RegularlySubsampledButton->setObjectName(QString::fromUtf8("RegularlySubsampledButton"));
|
||||
|
||||
verticalLayout_16->addWidget(RegularlySubsampledButton);
|
||||
|
||||
IregularlySubsampledButton = new QRadioButton(GlyphBox_2);
|
||||
IregularlySubsampledButton->setObjectName(QString::fromUtf8("IregularlySubsampledButton"));
|
||||
|
||||
verticalLayout_16->addWidget(IregularlySubsampledButton);
|
||||
|
||||
|
||||
verticalLayout_3->addWidget(ChannelBox);
|
||||
|
||||
|
||||
horizontalLayout->addWidget(settingsBox);
|
||||
|
||||
program = new Program(centralWidget);
|
||||
program->setObjectName(QString::fromUtf8("program"));
|
||||
|
||||
horizontalLayout->addWidget(program);
|
||||
|
||||
MainWindow->setCentralWidget(centralWidget);
|
||||
|
||||
retranslateUi(MainWindow);
|
||||
|
||||
QMetaObject::connectSlotsByName(MainWindow);
|
||||
} // setupUi
|
||||
|
||||
void retranslateUi(QMainWindow *MainWindow)
|
||||
{
|
||||
MainWindow->setWindowTitle(QCoreApplication::translate("MainWindow", "Simulation", nullptr));
|
||||
settingsBox->setTitle(QCoreApplication::translate("MainWindow", "Settings", nullptr));
|
||||
TechniqueBox->setTitle(QCoreApplication::translate("MainWindow", "Technique", nullptr));
|
||||
FirstButton->setText(QCoreApplication::translate("MainWindow", "ECol + LGlyph", nullptr));
|
||||
SecondButton->setText(QCoreApplication::translate("MainWindow", "EGlyph + LCol", nullptr));
|
||||
ChannelBox->setTitle(QCoreApplication::translate("MainWindow", "Channel Options", nullptr));
|
||||
ColourBox->setTitle(QCoreApplication::translate("MainWindow", "Color", nullptr));
|
||||
ComplementaryButton->setText(QCoreApplication::translate("MainWindow", "Complementary ", nullptr));
|
||||
ContrastingButton->setText(QCoreApplication::translate("MainWindow", "Contrasting", nullptr));
|
||||
MonochromaticButton->setText(QCoreApplication::translate("MainWindow", "Monochromatic", nullptr));
|
||||
SaturationBox->setTitle(QCoreApplication::translate("MainWindow", "Saturation", nullptr));
|
||||
SaturateButton->setText(QCoreApplication::translate("MainWindow", "Fully saturated", nullptr));
|
||||
DesaturateButton->setText(QCoreApplication::translate("MainWindow", "Desaturated", nullptr));
|
||||
GlyphBox->setTitle(QCoreApplication::translate("MainWindow", "Glyph Shape", nullptr));
|
||||
CircleButton->setText(QCoreApplication::translate("MainWindow", "Circle", nullptr));
|
||||
TriangleButton->setText(QCoreApplication::translate("MainWindow", "Triangle", nullptr));
|
||||
SquareButton->setText(QCoreApplication::translate("MainWindow", "Square", nullptr));
|
||||
HexagonButton->setText(QCoreApplication::translate("MainWindow", "Hexagon", nullptr));
|
||||
GlyphBox_2->setTitle(QCoreApplication::translate("MainWindow", "Glyph count", nullptr));
|
||||
FullySampledButton->setText(QCoreApplication::translate("MainWindow", "Fully sampled", nullptr));
|
||||
RegularlySubsampledButton->setText(QCoreApplication::translate("MainWindow", "Regularly subsampled", nullptr));
|
||||
IregularlySubsampledButton->setText(QCoreApplication::translate("MainWindow", "Irregularly sampled", nullptr));
|
||||
} // retranslateUi
|
||||
|
||||
};
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow: public Ui_MainWindow {};
|
||||
} // namespace Ui
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // UI_MAINWINDOW_H
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
#include <vtkGeneralTransform.h>
|
||||
#include <vtkGeoProjection.h>
|
||||
#include <vtkGeoTransform.h>
|
||||
#include <vtkLookupTable.h>
|
||||
#include <vtkPointData.h>
|
||||
#include <vtkAbstractTransform.h>
|
||||
#include <vtkOutlineSource.h>
|
||||
|
|
@ -24,8 +25,9 @@
|
|||
|
||||
#include "../CartographicTransformation.h"
|
||||
|
||||
using namespace std;
|
||||
using std::numbers::pi;
|
||||
|
||||
using namespace std;
|
||||
|
||||
EColLayer::EColLayer(std::shared_ptr<UVGrid> uvGrid) {
|
||||
this->ren = vtkSmartPointer<vtkRenderer>::New();
|
||||
|
|
@ -41,9 +43,53 @@ EColLayer::EColLayer(std::shared_ptr<UVGrid> uvGrid) {
|
|||
this->strength->SetNumberOfComponents(1);
|
||||
this->strength->SetNumberOfTuples((numLats-1)*(numLons-1));
|
||||
|
||||
this->direction = vtkSmartPointer<vtkDoubleArray>::New();
|
||||
this->direction->SetName("direction");
|
||||
this->direction->SetNumberOfComponents(1);
|
||||
this->direction->SetNumberOfTuples((numLats-1)*(numLons-1));
|
||||
|
||||
readCoordinates();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a given rgba colour to a range of values [start, end] in the lut.
|
||||
* @param lut : lookuptable to operate on.
|
||||
* @ param start : starting index of range to assign
|
||||
* @ param end: ending index of range to assign
|
||||
* @param r : red value [0,1]
|
||||
* @param g : green value [0,1]
|
||||
* @param n : blue value [0,1]
|
||||
* @param a : alpha value [0,1]
|
||||
*/
|
||||
void setLutRange(vtkSmartPointer<vtkLookupTable> lut, int start, int end, double r, double g, double b, double a) {
|
||||
for (int i=start; i <= end; i++) {
|
||||
lut->SetTableValue(i, r, g, b, a);
|
||||
}
|
||||
}
|
||||
|
||||
// builds a 4-way lookuptable, used to encode the directional component
|
||||
vtkSmartPointer<vtkLookupTable> buildLutDirs() {
|
||||
vtkNew<vtkLookupTable> lut;
|
||||
lut->SetNumberOfColors(360);
|
||||
lut->SetTableRange(0, 359);
|
||||
lut->SetScaleToLinear();
|
||||
lut->Build();
|
||||
//currently builds a corkO cyclic colour map, divided into 8 colours (see https://www.fabiocrameri.ch/cycliccolourmaps/)
|
||||
setLutRange(lut, 000, 020, 0.247, 0.243, 0.227, 1);
|
||||
setLutRange(lut, 021, 060, 0.243, 0.267, 0.365, 1);
|
||||
setLutRange(lut, 061, 100, 0.318, 0.416, 0.557, 1);
|
||||
setLutRange(lut, 101, 140, 0.518, 0.620, 0.729, 1);
|
||||
setLutRange(lut, 141, 180, 0.667, 0.757, 0.773, 1);
|
||||
setLutRange(lut, 181, 220, 0.631, 0.769, 0.651, 1);
|
||||
setLutRange(lut, 221, 260, 0.451, 0.639, 0.435, 1);
|
||||
setLutRange(lut, 261, 300, 0.298, 0.431, 0.224, 1);
|
||||
setLutRange(lut, 301, 340, 0.263, 0.310, 0.173, 1);
|
||||
setLutRange(lut, 341, 359, 0.247, 0.243, 0.227, 1);
|
||||
|
||||
lut->SetNanColor(0,0,0,0);
|
||||
|
||||
return lut;
|
||||
}
|
||||
|
||||
// TODO: Bit of a superfunction here; can do with some refactoring.
|
||||
void EColLayer::readCoordinates() {
|
||||
|
|
@ -64,27 +110,26 @@ void EColLayer::readCoordinates() {
|
|||
for (auto lat : uvGrid->lats) {
|
||||
double out[3] = {lon, lat, 0};
|
||||
transform->TransformPoint(out, out);
|
||||
// cout << "inserting point (" << pointId << "): " << out[0] << " " << out[1] << endl;
|
||||
points->InsertPoint(pointId++, out[0], out[1], 0);
|
||||
|
||||
// logic for adding cells
|
||||
if (latIndex > 0 and lonIndex > 0 ) {
|
||||
int idx = latIndex+lonIndex*numLats;
|
||||
// cout << idx << " at " << lonIndex << " " << latIndex << endl;
|
||||
vtkNew<vtkIdList> l;
|
||||
l->SetNumberOfIds(4);
|
||||
l->SetId(0, idx-1);
|
||||
l->SetId(1, idx-numLats-1);
|
||||
l->SetId(2, idx-numLats);
|
||||
l->SetId(3, idx);
|
||||
// cout << "inserting cell: " << idx-1 << " " << idx-numLats-1 << " " << idx- numLats<< " " << idx << endl;
|
||||
|
||||
double coords[12];
|
||||
points->GetPoint(idx-1, coords);
|
||||
points->GetPoint(idx-numLats-1, coords+3);
|
||||
points->GetPoint(idx-numLats, coords+6);
|
||||
points->GetPoint(idx, coords+9);
|
||||
// cout << "Inserting cell with points at: (" << coords[0] << " " << coords[1] << "), (" << coords[3] << " " << coords[4] << "), (" << coords[6] << " " << coords[7] << "), (" << coords[9] << " " << coords[10] << ")" << endl;
|
||||
data->InsertNextCell(VTK_QUAD, l);
|
||||
|
||||
// ltake the average of the four surrounding points as the cell's velocity.
|
||||
double u=0, v=0;
|
||||
for (int j=0; j < 2; j++ ) {
|
||||
for (int k=0; k < 2; k++ ) {
|
||||
|
|
@ -95,7 +140,8 @@ void EColLayer::readCoordinates() {
|
|||
}
|
||||
u /= 4;
|
||||
v /= 4;
|
||||
this->strength->SetTuple1(cellId++, std::sqrt(u*u + v*v));
|
||||
this->strength->SetTuple1(cellId, std::sqrt(u*u + v*v));
|
||||
this->direction->SetTuple1(cellId++, atan(u/v)*180/pi);
|
||||
}
|
||||
latIndex++;
|
||||
}
|
||||
|
|
@ -103,16 +149,20 @@ void EColLayer::readCoordinates() {
|
|||
}
|
||||
|
||||
data->GetCellData()->AddArray(this->strength);
|
||||
data->GetCellData()->SetActiveScalars("strength");
|
||||
data->GetCellData()->AddArray(this->direction);
|
||||
// data->GetCellData()->SetActiveScalars("strength");
|
||||
|
||||
vtkNew<vtkPolyDataMapper>(mapper);
|
||||
mapper->SetInputData(data);
|
||||
mapper->SetLookupTable(buildLutDirs());
|
||||
mapper->UseLookupTableScalarRangeOn();
|
||||
mapper->Update();
|
||||
data->GetCellData()->SetActiveScalars("direction");
|
||||
|
||||
vtkNew<vtkActor> actor;
|
||||
actor->SetMapper(mapper);
|
||||
actor->GetProperty()->SetColor(0, 1, 0);
|
||||
actor->GetProperty()->SetOpacity(0.2);
|
||||
actor->GetProperty()->SetOpacity(0.5);
|
||||
|
||||
// vtkNew<vtkActor> act2;
|
||||
// act2->SetMapper(mapper);
|
||||
|
|
@ -137,7 +187,8 @@ void EColLayer::updateData(int t) {
|
|||
}
|
||||
u /= 4;
|
||||
v /= 4;
|
||||
this->strength->SetTuple1(i++, std::sqrt(u*u + v*v));
|
||||
this->strength->SetTuple1(i, std::sqrt(u*u + v*v));
|
||||
this->direction->SetTuple1(i++, atan(u/v)*180/pi);
|
||||
}
|
||||
}
|
||||
this->strength->Modified();
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
class EColLayer : public Layer {
|
||||
private:
|
||||
vtkSmartPointer<vtkDoubleArray> strength;
|
||||
vtkSmartPointer<vtkDoubleArray> direction;
|
||||
std::shared_ptr<UVGrid> uvGrid;
|
||||
int numLats;
|
||||
int numLons;
|
||||
|
|
|
|||
|
|
@ -33,12 +33,36 @@ vtkSmartPointer<SpawnPointCallback> LGlyphLayer::createSpawnPointCallback() {
|
|||
|
||||
// Further notes; current thinking is to allow tracking a particle's age by using a scalar array in the VtkPolyData. This would be incremented for every tick/updateData function call.
|
||||
|
||||
/**
|
||||
* Build and returns a vtkLookupTable for the given number of colours in grayscale.
|
||||
* @param n : number of colours to add to the SetTableRange
|
||||
* @return : a vtkLookupTable with grayscale colours from [1,1,1,1] to [0.25, 0.25, 0.25, 1] in n steps.
|
||||
*/
|
||||
vtkSmartPointer<vtkLookupTable> buildLutBrightness(int n) {
|
||||
vtkNew<vtkLookupTable> lut;
|
||||
lut->SetNumberOfColors(n);
|
||||
lut->SetTableRange(0, n);
|
||||
lut->SetScaleToLinear();
|
||||
lut->Build();
|
||||
for (int i=0; i < n; i++) {
|
||||
lut->SetTableValue(i, 1-(0.75*i/(n-1)), 1-(0.75*i/(n-1)), 1-(0.75*i/(n-1)), 1);
|
||||
}
|
||||
lut->UseAboveRangeColorOn();
|
||||
lut->SetAboveRangeColor(0.2, 0.2, 0.2, 1);
|
||||
|
||||
// We cheat a little here: any particle with an age of -1 is out of bounds, and thus set invisible.
|
||||
lut->UseBelowRangeColorOn();
|
||||
lut->SetBelowRangeColor(1,1,1,0);
|
||||
|
||||
return lut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and returns a vtkLookupTable for the given number of colours in grayscale.
|
||||
* @param n : number of colours to add to the SetTableRange
|
||||
* @return : a vtkLookupTable with grayscale colours from [1,1,1,1] to [1,1,1,0.25] in n steps.
|
||||
*/
|
||||
vtkSmartPointer<vtkLookupTable> buildLut(int n) {
|
||||
vtkSmartPointer<vtkLookupTable> buildLutOpacity(int n) {
|
||||
vtkNew<vtkLookupTable> lut;
|
||||
lut->SetNumberOfColors(n);
|
||||
lut->SetTableRange(0, n);
|
||||
|
|
@ -58,6 +82,9 @@ vtkSmartPointer<vtkLookupTable> buildLut(int n) {
|
|||
}
|
||||
|
||||
LGlyphLayer::LGlyphLayer(std::shared_ptr<UVGrid> uvGrid, std::unique_ptr<AdvectionKernel> advectionKernel) {
|
||||
this->luts.push(buildLutOpacity(512));
|
||||
this->luts.push(buildLutBrightness(512));
|
||||
|
||||
this->ren = vtkSmartPointer<vtkRenderer>::New();
|
||||
this->ren->SetLayer(2);
|
||||
|
||||
|
|
@ -94,15 +121,20 @@ LGlyphLayer::LGlyphLayer(std::shared_ptr<UVGrid> uvGrid, std::unique_ptr<Advecti
|
|||
glyph2D->SetScaleModeToDataScalingOff();
|
||||
glyph2D->Update();
|
||||
|
||||
vtkNew<vtkPolyDataMapper> mapper;
|
||||
mapper->SetInputConnection(glyph2D->GetOutputPort());
|
||||
mapper->SetColorModeToMapScalars();
|
||||
mapper->SetLookupTable(buildLut(512));
|
||||
mapper->UseLookupTableScalarRangeOn();
|
||||
mapper->Update();
|
||||
this->mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
||||
this->mapper->SetInputConnection(glyph2D->GetOutputPort());
|
||||
this->mapper->SetColorModeToMapScalars();
|
||||
|
||||
auto lut = this->luts.front();
|
||||
mapper->SetLookupTable(lut);
|
||||
this->luts.pop();
|
||||
this->luts.push(lut);
|
||||
|
||||
this->mapper->UseLookupTableScalarRangeOn();
|
||||
this->mapper->Update();
|
||||
|
||||
vtkNew<vtkActor> actor;
|
||||
actor->SetMapper(mapper);
|
||||
actor->SetMapper(this->mapper);
|
||||
|
||||
this->ren->AddActor(actor);
|
||||
}
|
||||
|
|
@ -174,6 +206,13 @@ void LGlyphLayer::addObservers(vtkSmartPointer<vtkRenderWindowInteractor> intera
|
|||
}
|
||||
|
||||
|
||||
void LGlyphLayer::cycleGlyphStyle() {
|
||||
auto lut = this->luts.front();
|
||||
this->mapper->SetLookupTable(lut);
|
||||
this->luts.pop();
|
||||
this->luts.push(lut);
|
||||
}
|
||||
|
||||
void LGlyphLayer::setDt(int dt) {
|
||||
this->dt = dt;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "Layer.h"
|
||||
#include "../advection/kernel/AdvectionKernel.h"
|
||||
#include "../commands/SpawnPointCallback.h"
|
||||
#include <queue>
|
||||
#include <vtkPolyData.h>
|
||||
#include <vtkInteractorStyle.h>
|
||||
|
||||
|
|
@ -16,10 +17,12 @@ private:
|
|||
vtkSmartPointer<vtkPolyData> data;
|
||||
vtkSmartPointer<vtkIntArray> particlesBeached;
|
||||
vtkSmartPointer<vtkIntArray> particlesAge;
|
||||
vtkSmartPointer<vtkPolyDataMapper> mapper;
|
||||
std::unique_ptr<AdvectionKernel> advector;
|
||||
std::shared_ptr<UVGrid> uvGrid;
|
||||
int dt = 3600;
|
||||
int beachedAtNumberOfTimes = 20;
|
||||
std::queue<vtkSmartPointer<vtkLookupTable>> luts;
|
||||
|
||||
public:
|
||||
/** Constructor.
|
||||
|
|
@ -41,6 +44,9 @@ public:
|
|||
|
||||
void addObservers(vtkSmartPointer<vtkRenderWindowInteractor> interactor) override;
|
||||
|
||||
/** This function cycles which lut is used for the layer, according to the lookuptables in the luts attribute.
|
||||
*/
|
||||
void cycleGlyphStyle();
|
||||
|
||||
/**
|
||||
* Sets a custom DT value, needed for advect calls to the simulation logic.
|
||||
|
|
|
|||
|
|
@ -18,11 +18,60 @@
|
|||
#include "advection/kernel/RK4AdvectionKernel.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;
|
||||
|
||||
#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.
|
||||
MainWindow mainWindow;
|
||||
mainWindow.resize(1200, 900);
|
||||
|
||||
mainWindow.show();
|
||||
return app.exec();
|
||||
|
||||
// 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;
|
||||
string dataPath = "../../../../data";
|
||||
shared_ptr<UVGrid> uvGrid = make_shared<UVGrid>(dataPath);
|
||||
|
|
@ -31,17 +80,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();
|
||||
|
||||
unique_ptr<Program> program = make_unique<Program>(DT);
|
||||
program->addLayer(new BackgroundImage(dataPath + "/map_661-661.png"));
|
||||
// program->addLayer(new EGlyphLayer(uvGrid));
|
||||
unique_ptr<Program> program = make_unique<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->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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef TECHNIQUE_H
|
||||
#define TECHNIQUE_H
|
||||
|
||||
#include "layers/Layer.h"
|
||||
#include <vtkPolyData.h>
|
||||
class Technique {
|
||||
private:
|
||||
std::vector<Layer *> layers;
|
||||
vtkSmartPointer<vtkPoints> points;
|
||||
vtkSmartPointer<vtkPolyData> data;
|
||||
|
||||
void setupInteractions();
|
||||
|
||||
public:
|
||||
Technique();
|
||||
void addLayer(Layer *l);
|
||||
void removeLayer(Layer *l);
|
||||
void updateData(int t);
|
||||
int numberOfLayers();
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue