fix: LCol colour maps tweaked

This commit is contained in:
Djairo Hougee 2024-05-29 20:33:36 +02:00
parent 11944e679e
commit 28fb651037
7 changed files with 175 additions and 74 deletions

View File

@ -117,7 +117,7 @@ void EColLayer::readCoordinates() {
} }
u /= 4; u /= 4;
v /= 4; v /= 4;
this->lutIdx->SetTuple1(cellId++, calcIndex(u,v, this->maxStrength)); this->lutIdx->SetValue(cellId++, calcIndex(u,v, this->maxStrength));
} }
latIndex++; latIndex++;
} }
@ -156,7 +156,7 @@ void EColLayer::updateData(int t) {
} }
u /= 4; u /= 4;
v /= 4; v /= 4;
this->lutIdx->SetTuple1(i++, calcIndex(u,v, this->maxStrength)); this->lutIdx->SetValue(i++, calcIndex(u,v, this->maxStrength));
} }
} }
this->lutIdx->Modified(); this->lutIdx->Modified();

View File

@ -69,7 +69,7 @@ void EGlyphLayer::readCoordinates() {
vtkNew<vtkGlyphSource2D> arrowSource; vtkNew<vtkGlyphSource2D> arrowSource;
arrowSource->SetGlyphTypeToArrow(); arrowSource->SetGlyphTypeToArrow();
arrowSource->SetScale(0.2); //TODO: set this properly arrowSource->SetScale(0.2);
arrowSource->Update(); arrowSource->Update();
vtkNew<vtkGlyph2D> glyph2D; vtkNew<vtkGlyph2D> glyph2D;

View File

@ -20,6 +20,9 @@
#include <vtkCamera.h> #include <vtkCamera.h>
#include "../CartographicTransformation.h" #include "../CartographicTransformation.h"
#include "luts.h"
using namespace std;
// TODO: spawning one particle per event is nice and all, but for a colour map doesnt really look great // TODO: spawning one particle per event is nice and all, but for a colour map doesnt really look great
// potential solution: spawn a number of particles randomly around the selected point instead. // potential solution: spawn a number of particles randomly around the selected point instead.
@ -36,33 +39,12 @@ vtkSmartPointer<SpawnPointCallback> LColLayer::createSpawnPointCallback() {
} }
/**
*/
// TODO: edit this function; probably extract all lut builders into a builder pattern or something.
vtkSmartPointer<vtkLookupTable> buildLutDens() {
int n = 5;
vtkNew<vtkLookupTable> lut;
lut->SetNumberOfColors(n);
lut->SetTableRange(1, n+1);
lut->SetScaleToLinear();
lut->Build();
for (int i=n-1; i >= 0; i--) {
lut->SetTableValue(i, 0, 1-(0.75*i/(n-1)), 1, 1);
}
lut->UseAboveRangeColorOn();
lut->SetAboveRangeColor(1,0,0,1);
lut->UseBelowRangeColorOn();
lut->SetBelowRangeColor(1,1,1,0);
return lut;
}
// There's two separate pipelines going on here: the one where we build a vtkPoints array for the spawnpointcallback, // There's two separate pipelines going on here: the one where we build a vtkPoints array for the spawnpointcallback,
// and the one where we build a vtkPolyData with Cells for the colour map. // and the one where we build a vtkPolyData with Cells for the colour map.
// TODO: it would make sense to separate these pipelines out to their own functions. // TODO: it would make sense to separate these pipelines out to their own functions.
LColLayer::LColLayer(std::shared_ptr<UVGrid> uvGrid, std::unique_ptr<AdvectionKernel> advectionKernel) { LColLayer::LColLayer(shared_ptr<UVGrid> uvGrid, unique_ptr<AdvectionKernel> advectionKernel) {
buildLuts();
// general management; probably should be the actual constructor. // general management; probably should be the actual constructor.
this->ren = vtkSmartPointer<vtkRenderer>::New(); this->ren = vtkSmartPointer<vtkRenderer>::New();
this->ren->SetLayer(2); this->ren->SetLayer(2);
@ -78,15 +60,14 @@ LColLayer::LColLayer(std::shared_ptr<UVGrid> uvGrid, std::unique_ptr<AdvectionKe
this->particlesBeached = vtkSmartPointer<vtkIntArray>::New(); this->particlesBeached = vtkSmartPointer<vtkIntArray>::New();
this->particlesBeached->SetName("particlesBeached"); this->particlesBeached->SetName("particlesBeached");
this->particlesBeached->SetNumberOfComponents(1);
this->particlesAge = vtkSmartPointer<vtkIntArray>::New(); this->particlesAge = vtkSmartPointer<vtkIntArray>::New();
this->particlesAge->SetName("particlesAge"); this->particlesAge->SetName("particlesAge");
this->particlesAge->SetNumberOfComponents(1);
this->lutIdx = vtkSmartPointer<vtkIntArray>::New(); this->lutIdx = vtkSmartPointer<vtkIntArray>::New();
this->lutIdx->SetName("lutIdx"); this->lutIdx->SetName("lutIdx");
this->lutIdx->SetNumberOfComponents(1); this->lutIdx->SetNumberOfTuples((numLats-1)*(numLons-1));
this->lutIdx->Fill(-1);
// pipeline 2 // pipeline 2
@ -97,12 +78,15 @@ LColLayer::LColLayer(std::shared_ptr<UVGrid> uvGrid, std::unique_ptr<AdvectionKe
data->Allocate((numLats-1)*(numLons-1)); data->Allocate((numLats-1)*(numLons-1));
this->cellParticleDensity = vtkSmartPointer<vtkIntArray>::New(); this->cellParticleDensity = vtkSmartPointer<vtkIntArray>::New();
this->cellParticleDensity->SetName("cellParticleDensity");
this->cellParticleDensity->SetNumberOfComponents(1);
this->cellParticleDensity->SetNumberOfTuples((numLats-1)*(numLons-1)); this->cellParticleDensity->SetNumberOfTuples((numLats-1)*(numLons-1));
this->cellParticleDensity->Fill(0);
this->data->GetCellData()->AddArray(this->cellParticleDensity); this->cellParticleAge = vtkSmartPointer<vtkIntArray>::New();
this->data->GetCellData()->SetActiveScalars("cellParticleDensity"); this->cellParticleAge->SetNumberOfTuples((numLats-1)*(numLons-1));
this->cellParticleDensity->Fill(0);
this->data->GetCellData()->AddArray(this->lutIdx);
this->data->GetCellData()->SetActiveScalars("lutIdx");
vtkSmartPointer<vtkTransformFilter> transformFilter = createCartographicTransformFilter(uvGrid); vtkSmartPointer<vtkTransformFilter> transformFilter = createCartographicTransformFilter(uvGrid);
auto transform = transformFilter->GetTransform(); auto transform = transformFilter->GetTransform();
@ -127,34 +111,39 @@ LColLayer::LColLayer(std::shared_ptr<UVGrid> uvGrid, std::unique_ptr<AdvectionKe
l->SetId(3, idx); l->SetId(3, idx);
this->data->InsertNextCell(VTK_QUAD, l); this->data->InsertNextCell(VTK_QUAD, l);
this->cellParticleDensity->SetTuple1(cellId++, 0);
} }
latIndex++; latIndex++;
} }
lonIndex++; lonIndex++;
} }
vtkNew<vtkPolyDataMapper>(mapper); this->mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputData(data); this->mapper->SetInputData(data);
mapper->SetLookupTable(buildLutDens()); setColourMode(COMPLEMENTARY);
mapper->UseLookupTableScalarRangeOn(); this->mapper->UseLookupTableScalarRangeOn();
mapper->Update(); this->mapper->Update();
vtkNew<vtkActor> actor; vtkNew<vtkActor> actor;
actor->SetMapper(mapper); actor->SetMapper(this->mapper);
actor->GetProperty()->SetColor(0, 1, 0); // actor->GetProperty()->SetOpacity(0.5);
actor->GetProperty()->SetOpacity(0.5); actor->GetProperty()->SetOpacity(1);
// vtkNew<vtkActor> act2;
// act2->SetMapper(mapper);
// act2->GetProperty()->SetRepresentationToWireframe();
// this->ren->AddActor(act2);
this->ren->AddActor(actor); this->ren->AddActor(actor);
this->callback = createSpawnPointCallback(); this->callback = createSpawnPointCallback();
} }
void LColLayer::buildLuts() {
this->tables.push_back(buildDensityComplementary());
this->tables.push_back(buildDensityContrasting());
this->tables.push_back(buildDensityMonochromatic());
this->tables.push_back(buildDensityDesaturated());
this->activeColourMode = COMPLEMENTARY;
this->activeSaturationMode = SATURATED;
}
void LColLayer::spoofPoints() { void LColLayer::spoofPoints() {
for (int i=0; i < 330; i+=5) { for (int i=0; i < 330; i+=5) {
for (int j=0; j < 330; j+=5) { for (int j=0; j < 330; j+=5) {
@ -166,15 +155,7 @@ void LColLayer::spoofPoints() {
this->points->Modified(); this->points->Modified();
} }
// calculates the cellIndex for a given lat,lon pair. // FIXME: delete this once done testing
int LColLayer::calcIndex(double x, double y) {
int lonIndex = std::floor((x - uvGrid->lonMin()) / uvGrid->lonStep());
int latIndex = std::floor((y - uvGrid->latMin()) / uvGrid->latStep());
return latIndex+lonIndex*(uvGrid->latSize-1);
}
void printArray(vtkSmartPointer<vtkIntArray> data, int numLons, int numLats, int latsize) { void printArray(vtkSmartPointer<vtkIntArray> data, int numLons, int numLats, int latsize) {
for (int i=0; i < numLons-1; i++) { for (int i=0; i < numLons-1; i++) {
for (int j=0; j < numLats-1; j++) { for (int j=0; j < numLats-1; j++) {
@ -189,8 +170,8 @@ void printArray(vtkSmartPointer<vtkIntArray> data, int numLons, int numLats, int
void LColLayer::updateData(int t) { void LColLayer::updateData(int t) {
const int SUPERSAMPLINGRATE = 4; const int SUPERSAMPLINGRATE = 4;
double point[3], oldX, oldY; double point[3], oldX, oldY;
bool modifiedData = false;
this->cellParticleDensity->Fill(0); this->cellParticleDensity->Fill(0);
this->cellParticleAge->Fill(0);
// iterate over every point. // iterate over every point.
for (vtkIdType n=0; n < this->points->GetNumberOfPoints(); n++) { for (vtkIdType n=0; n < this->points->GetNumberOfPoints(); n++) {
@ -216,28 +197,27 @@ void LColLayer::updateData(int t) {
// supersampling // supersampling
for (int i=0; i < SUPERSAMPLINGRATE; i++) { for (int i=0; i < SUPERSAMPLINGRATE; i++) {
std::tie(point[1], point[0]) = advector->advect(t, point[1], point[0], this->dt/SUPERSAMPLINGRATE); tie(point[1], point[0]) = advector->advect(t, point[1], point[0], this->dt/SUPERSAMPLINGRATE);
} }
// if the particle's location remains unchanged, increase beachedFor number. Else, decrease it and update point position. // if the particle's location remains unchanged, increase beachedFor number. Else, decrease it and update point position.
if (oldX == point[0] and oldY == point[1]) { if (oldX == point[0] and oldY == point[1]) {
this->particlesBeached->SetValue(n, beachedFor+1); this->particlesBeached->SetValue(n, beachedFor+1);
} else { } else {
this->particlesBeached->SetValue(n, std::max(beachedFor-1, 0)); this->particlesBeached->SetValue(n, max(beachedFor-1, 0));
this->points->SetPoint(n, point); this->points->SetPoint(n, point);
modifiedData = true;
} }
} }
// add point to cellparticleDensity // add point to cellparticleDensity
int index = calcIndex(point[0], point[1]); int index = calcCellIndex(point[0], point[1], uvGrid);
this->cellParticleDensity->SetValue(index, cellParticleDensity->GetValue(index)+1); this->cellParticleDensity->SetValue(index, cellParticleDensity->GetValue(index)+1);
this->cellParticleAge->SetValue(index, cellParticleAge->GetValue(index)+age+1);
} }
if (modifiedData) {
this->particlesAge->Modified(); for (int idx=0; idx < (numLons-1)*(numLats-1); idx++) {
this->points->Modified(); this->lutIdx->SetValue(idx, calcIndex(this->cellParticleAge->GetValue(idx), this->cellParticleDensity->GetValue(idx)));
this->cellParticleDensity->Modified();
} }
// printArray(this->cellParticleDensity, numLons, numLats, uvGrid->latSize-1); this->lutIdx->Modified();
} }
void LColLayer::addObservers(vtkSmartPointer<vtkRenderWindowInteractor> interactor) { void LColLayer::addObservers(vtkSmartPointer<vtkRenderWindowInteractor> interactor) {
@ -256,3 +236,38 @@ void LColLayer::removeObservers(vtkSmartPointer<vtkRenderWindowInteractor> inter
void LColLayer::setDt(int dt) { void LColLayer::setDt(int dt) {
this->dt = dt; this->dt = dt;
} }
void LColLayer::setColourMode(ColourMode mode) {
this->activeColourMode = mode;
if (this->activeSaturationMode == DESATURATED) return;
this->mapper->SetLookupTable(this->tables[mode]);
}
void LColLayer::setSaturationMode(SaturationMode mode) {
this->activeSaturationMode = mode;
if (mode == DESATURATED) {
this->mapper->SetLookupTable(this->tables[mode]);
} else {
this->mapper->SetLookupTable(this->tables[this->activeColourMode]);
}
}
// TODO: this function can do with some improvement as well; it's completely heuristic right now.
int calcIndex(const int age, const int density) {
if (not density) return -1;
int calcAge = (double)age/density/60;
return min(9, calcAge)+min(9, density)*10;
}
int calcCellIndex(const double u, const double v, const shared_ptr<UVGrid> uvGrid) {
int lonIndex = floor((u - uvGrid->lonMin()) / uvGrid->lonStep());
int latIndex = floor((v - uvGrid->latMin()) / uvGrid->latStep());
return latIndex+lonIndex*(uvGrid->latSize-1);
}

View File

@ -14,11 +14,16 @@ class LColLayer : public Layer {
private: private:
vtkSmartPointer<vtkPoints> points; vtkSmartPointer<vtkPoints> points;
vtkSmartPointer<vtkPolyData> data; vtkSmartPointer<vtkPolyData> data;
vtkSmartPointer<vtkPolyDataMapper> mapper;
vtkSmartPointer<vtkIntArray> particlesBeached; vtkSmartPointer<vtkIntArray> particlesBeached;
vtkSmartPointer<vtkIntArray> particlesAge; vtkSmartPointer<vtkIntArray> particlesAge;
vtkSmartPointer<vtkIntArray> lutIdx; vtkSmartPointer<vtkIntArray> lutIdx;
vtkSmartPointer<vtkIntArray> cellParticleDensity; vtkSmartPointer<vtkIntArray> cellParticleDensity;
vtkSmartPointer<vtkIntArray> cellParticleAge;
vtkSmartPointer<SpawnPointCallback> callback; vtkSmartPointer<SpawnPointCallback> callback;
std::vector<vtkSmartPointer<vtkLookupTable>> tables;
ColourMode activeColourMode;
SaturationMode activeSaturationMode;
std::unique_ptr<AdvectionKernel> advector; std::unique_ptr<AdvectionKernel> advector;
std::shared_ptr<UVGrid> uvGrid; std::shared_ptr<UVGrid> uvGrid;
int dt = 3600; int dt = 3600;
@ -26,8 +31,7 @@ private:
int numLats; int numLats;
int numLons; int numLons;
void buildLuts();
int calcIndex(double x, double y);
public: public:
/** Constructor. /** Constructor.
@ -51,10 +55,17 @@ public:
void removeObservers(vtkSmartPointer<vtkRenderWindowInteractor> interactor) override; void removeObservers(vtkSmartPointer<vtkRenderWindowInteractor> interactor) override;
void setColourMode(ColourMode mode) override;
void setSaturationMode(SaturationMode mode) override;
/** /**
* Sets a custom DT value, needed for advect calls to the simulation logic. * Sets a custom DT value, needed for advect calls to the simulation logic.
*/ */
void setDt(int dt); void setDt(int dt);
}; };
// TODO: comments
int calcIndex(const int age, const int density);
int calcCellIndex(const double u, const double v, const std::shared_ptr<UVGrid> uvGrid);
#endif #endif

View File

@ -120,7 +120,7 @@ void LGlyphLayer::updateData(int t) {
if (point[0] <= this->uvGrid->lonMin() or point[0] >= this->uvGrid->lonMax() or point[1] <= this->uvGrid->latMin() or point[1] >= this->uvGrid->latMax()) { if (point[0] <= this->uvGrid->lonMin() or point[0] >= this->uvGrid->lonMax() or point[1] <= this->uvGrid->latMin() or point[1] >= this->uvGrid->latMax()) {
// sets any particle out of bounds to be beached - so it gets assigned the right colour in the lookup table. // sets any particle out of bounds to be beached - so it gets assigned the right colour in the lookup table.
this->particlesAge->SetValue(n, -1); this->particlesAge->SetValue(n, -1);
this->lutIdx->SetTuple1(n, -1); this->lutIdx->SetValue(n, -1);
continue; continue;
} }
@ -143,15 +143,15 @@ void LGlyphLayer::updateData(int t) {
// if the particle's location remains unchanged, increase beachedFor number. Else, decrease it and update point position. // if the particle's location remains unchanged, increase beachedFor number. Else, decrease it and update point position.
if (oldX == point[0] and oldY == point[1]) { if (oldX == point[0] and oldY == point[1]) {
this->particlesBeached->SetValue(n, beachedFor+1); this->particlesBeached->SetValue(n, beachedFor+1);
this->lutIdx->SetTuple1(n, beachedFor == this->beachedAtNumberOfTimes-2 ? calcIndex(age+1, true) : calcIndex(age+1, false)); this->lutIdx->SetValue(n, beachedFor == this->beachedAtNumberOfTimes-2 ? calcIndex(age+1, true) : calcIndex(age+1, false));
} else { } else {
this->particlesBeached->SetValue(n, std::max(beachedFor-1, 0)); this->particlesBeached->SetValue(n, std::max(beachedFor-1, 0));
this->points->SetPoint(n, point); this->points->SetPoint(n, point);
this->lutIdx->SetTuple1(n, calcIndex(age+1, false)); this->lutIdx->SetValue(n, calcIndex(age+1, false));
modifiedData = true; modifiedData = true;
} }
} else { } else {
this->lutIdx->SetTuple1(n, calcIndex(age+1, true)); this->lutIdx->SetValue(n, calcIndex(age+1, true));
} }
} }
if (modifiedData) { if (modifiedData) {

View File

@ -74,7 +74,7 @@ vtkSmartPointer<vtkLookupTable> buildCyclicComplementary() {
lut->Build(); lut->Build();
int idx=0; int idx=0;
for (double opacity=0.1; opacity <= 1.0; opacity+=0.1) { for (double opacity=0.5; opacity <= 1.0; opacity+=0.05) {
lut->SetTableValue(idx++, 0.247059, 0.243137, 0.227451, opacity); lut->SetTableValue(idx++, 0.247059, 0.243137, 0.227451, opacity);
lut->SetTableValue(idx++, 0.243137, 0.266667, 0.364706, opacity); lut->SetTableValue(idx++, 0.243137, 0.266667, 0.364706, opacity);
lut->SetTableValue(idx++, 0.329412, 0.431373, 0.580392, opacity); lut->SetTableValue(idx++, 0.329412, 0.431373, 0.580392, opacity);
@ -178,22 +178,88 @@ vtkSmartPointer<vtkLookupTable> buildCyclicDesaturated() {
// LCol tables // LCol tables
vtkSmartPointer<vtkLookupTable> buildDensityComplementary() { vtkSmartPointer<vtkLookupTable> buildDensityComplementary() {
// uses a reverse matplotlib YlGn colour map.
vtkNew<vtkLookupTable> lut; vtkNew<vtkLookupTable> lut;
lut->SetNumberOfColors(100);
lut->SetTableRange(0, 99);
lut->SetScaleToLinear();
lut->Build();
int idx=0;
for (double opacity=0.5; opacity <= 1.0; opacity+=0.05) {
lut->SetTableValue(idx++, 0.0, 0.27058823529411763, 0.1607843137254902, opacity);
lut->SetTableValue(idx++, 0.0, 0.3911572472126105, 0.20901191849288736, opacity);
lut->SetTableValue(idx++, 0.10388312187620147, 0.4909496347558632, 0.2513033448673587, opacity);
lut->SetTableValue(idx++, 0.21568627450980393, 0.6196078431372549, 0.330718954248366, opacity);
lut->SetTableValue(idx++, 0.3724721261053441, 0.7283044982698962, 0.424559784698193, opacity);
lut->SetTableValue(idx++, 0.5651364859669358, 0.8175009611687812, 0.5119723183391004, opacity);
lut->SetTableValue(idx++, 0.7359477124183007, 0.8915032679738563, 0.5843137254901961, opacity);
lut->SetTableValue(idx++, 0.8795847750865051, 0.9526182237600923, 0.6601922337562476, opacity);
lut->SetTableValue(idx++, 0.9724413687043445, 0.9896655132641292, 0.7464667435601692, opacity);
lut->SetTableValue(idx++, 1.0, 1.0, 0.8980392156862745, opacity);
}
lut->UseBelowRangeColorOn();
lut->SetBelowRangeColor(0,0,0,0);
lut->SetNanColor(0.0,0,0,0);
return lut; return lut;
} }
vtkSmartPointer<vtkLookupTable> buildDensityContrasting() { vtkSmartPointer<vtkLookupTable> buildDensityContrasting() {
// uses the matplotlib viridis colour map.
vtkNew<vtkLookupTable> lut; vtkNew<vtkLookupTable> lut;
lut->SetNumberOfColors(100);
lut->SetTableRange(0, 99);
lut->SetScaleToLinear();
lut->Build();
int idx=0;
for (double opacity=0.5; opacity <= 1.0; opacity+=0.05) {
lut->SetTableValue(idx++, 0.267004, 0.004874, 0.329415, opacity);
lut->SetTableValue(idx++, 0.281412, 0.155834, 0.469201, opacity);
lut->SetTableValue(idx++, 0.244972, 0.287675, 0.53726, opacity);
lut->SetTableValue(idx++, 0.190631, 0.407061, 0.556089, opacity);
lut->SetTableValue(idx++, 0.147607, 0.511733, 0.557049, opacity);
lut->SetTableValue(idx++, 0.119699, 0.61849, 0.536347, opacity);
lut->SetTableValue(idx++, 0.20803, 0.718701, 0.472873, opacity);
lut->SetTableValue(idx++, 0.430983, 0.808473, 0.346476, opacity);
lut->SetTableValue(idx++, 0.709898, 0.868751, 0.169257, opacity);
lut->SetTableValue(idx++, 0.993248, 0.906157, 0.143936, opacity);
}
lut->UseBelowRangeColorOn();
lut->SetBelowRangeColor(0,0,0,0);
lut->SetNanColor(0.0,0,0,0);
return lut; return lut;
} }
vtkSmartPointer<vtkLookupTable> buildDensityMonochromatic() { vtkSmartPointer<vtkLookupTable> buildDensityMonochromatic() {
// uses a reverse matplotlib Greens colour map.
vtkNew<vtkLookupTable> lut; vtkNew<vtkLookupTable> lut;
lut->SetNumberOfColors(100);
lut->SetTableRange(0, 99);
lut->SetScaleToLinear();
lut->Build();
int idx=0;
for (double opacity=0.5; opacity <= 1.0; opacity+=0.05) {
lut->SetTableValue(idx++, 0.0, 0.26666666666666666, 0.10588235294117647, opacity);
lut->SetTableValue(idx++, 0.0, 0.4079046520569012, 0.16444444444444445, opacity);
lut->SetTableValue(idx++, 0.10388312187620147, 0.5164936562860438, 0.2467512495194156, opacity);
lut->SetTableValue(idx++, 0.21568627450980393, 0.6287581699346405, 0.3333333333333333, opacity);
lut->SetTableValue(idx++, 0.36392156862745095, 0.7240292195309497, 0.4181468665897732, opacity);
lut->SetTableValue(idx++, 0.5351787773933102, 0.8060899653979239, 0.5287504805843906, opacity);
lut->SetTableValue(idx++, 0.681045751633987, 0.8718954248366013, 0.6562091503267974, opacity);
lut->SetTableValue(idx++, 0.8089965397923875, 0.9251672433679354, 0.7834525182622069, opacity);
lut->SetTableValue(idx++, 0.9066205305651672, 0.9641214917339485, 0.8884429065743944, opacity);
lut->SetTableValue(idx++, 0.9686274509803922, 0.9882352941176471, 0.9607843137254902, opacity);
}
lut->UseBelowRangeColorOn();
lut->SetBelowRangeColor(0,0,0,0);
lut->SetNanColor(0.0,0,0,0);
return lut; return lut;
} }

View File

@ -2,6 +2,15 @@
#include <QVTKOpenGLNativeWidget.h> #include <QVTKOpenGLNativeWidget.h>
#include "QT/MainWindow.h" #include "QT/MainWindow.h"
// TODO: add a widget to act as legend. This is fourfold: particle-age, LCol-density, Lcol-age, ECol-direction ECol-strength?
// TODO: add text widget showing simulation time (in days/weeks/months from 0).
// TODO: make Lagrangian Layers share one vtkPoints for seemless technique switching
// TODO: make LColLayer use a modified spawnpointCallback to spawn multiple particles per interaction
// TODO: add text gui explaining the above?
// TODO: yoink Robin's isNearestNeighbourZero function to improve beaching
// TODO: add a button to reset the simulation - set time=0 and reset points array of particles.
// FIXME: go over each function and add const where appropriate.
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat()); QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());