From 650a245f0ab6cd9763cf4d3b2425f3b7e0fba550 Mon Sep 17 00:00:00 2001 From: djairoh Date: Mon, 20 May 2024 00:07:14 +0200 Subject: [PATCH] feat: particle aging --- .../src/commands/SpawnPointCallback.cpp | 6 +- .../src/commands/SpawnPointCallback.h | 3 + .../src/layers/LGlyphLayer.cpp | 59 +++++++++++++------ .../src/layers/LGlyphLayer.h | 2 + particle-track-and-trace/src/main.cpp | 2 +- 5 files changed, 52 insertions(+), 20 deletions(-) diff --git a/particle-track-and-trace/src/commands/SpawnPointCallback.cpp b/particle-track-and-trace/src/commands/SpawnPointCallback.cpp index 2db89c0..7cb84ea 100644 --- a/particle-track-and-trace/src/commands/SpawnPointCallback.cpp +++ b/particle-track-and-trace/src/commands/SpawnPointCallback.cpp @@ -42,10 +42,10 @@ void SpawnPointCallback::Execute(vtkObject *caller, unsigned long evId, void *ca points->InsertNextPoint(worldPos[0], worldPos[1], 0); this->particlesBeached->InsertNextValue(0); + this->particlesAge->InsertNextValue(0); // FIXME: The below lines cause some weird interaction with our vtkTimer. // see github issue https://github.com/MakeNEnjoy/interactive-track-and-trace/issues/28 - this->particlesBeached->Modified(); this->points->Modified(); ren->GetRenderWindow()->Render(); } @@ -80,3 +80,7 @@ void SpawnPointCallback::setUVGrid(const std::shared_ptr &uvGrid) { void SpawnPointCallback::setBeached(const vtkSmartPointer &ints) { this->particlesBeached = ints; } + +void SpawnPointCallback::setAge(const vtkSmartPointer &ints) { + this->particlesAge = ints; +} diff --git a/particle-track-and-trace/src/commands/SpawnPointCallback.h b/particle-track-and-trace/src/commands/SpawnPointCallback.h index c8d6767..7e9f3e5 100644 --- a/particle-track-and-trace/src/commands/SpawnPointCallback.h +++ b/particle-track-and-trace/src/commands/SpawnPointCallback.h @@ -25,6 +25,8 @@ public: void setBeached(const vtkSmartPointer &parts); + void setAge(const vtkSmartPointer &parts); + void setUVGrid(const std::shared_ptr &uvGrid); private: @@ -32,6 +34,7 @@ private: vtkSmartPointer points; vtkSmartPointer ren; vtkSmartPointer particlesBeached; + vtkSmartPointer particlesAge; std::shared_ptr uvGrid; vtkSmartPointer inverseCartographicProjection; diff --git a/particle-track-and-trace/src/layers/LGlyphLayer.cpp b/particle-track-and-trace/src/layers/LGlyphLayer.cpp index 8fb03b0..5dbd57b 100644 --- a/particle-track-and-trace/src/layers/LGlyphLayer.cpp +++ b/particle-track-and-trace/src/layers/LGlyphLayer.cpp @@ -27,6 +27,7 @@ vtkSmartPointer LGlyphLayer::createSpawnPointCallback() { newPointCallBack->setRen(this->ren); newPointCallBack->setUVGrid(this->uvGrid); newPointCallBack->setBeached(this->particlesBeached); + newPointCallBack->setAge(this->particlesAge); return newPointCallBack; } @@ -35,20 +36,24 @@ vtkSmartPointer LGlyphLayer::createSpawnPointCallback() { /** * 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.5,0.5,0.5,0.5] in n steps. + * @return : a vtkLookupTable with grayscale colours from [1,1,1,1] to [1,1,1,0.25] in n steps. */ vtkSmartPointer buildLut(int n) { vtkNew lut; - lut->SetNumberOfColors(n+1); + lut->SetNumberOfColors(n); lut->SetTableRange(0, n); lut->SetScaleToLinear(); lut->Build(); for (int i=0; i < n; i++) { - lut->SetTableValue(i, 1-(0.5*i/(n-1)), 1-(0.5*i/(n-1)), 1-(0.5*i/(n-1)), 1-(0.5*i/(n-1))); + lut->SetTableValue(i, 1, 1, 1, 1-(0.75*i/(n-1))); } - // set the last value to separate fully beached particles from those that have simply not moved in a bit. - lut->SetTableValue(n-1, 0, 0, 0, 0.25); - lut->SetTableValue(n, 0, 0, 0, 0); + lut->UseAboveRangeColorOn(); + lut->SetAboveRangeColor(1,1,1,0.20); + + // 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; } @@ -64,8 +69,13 @@ LGlyphLayer::LGlyphLayer(std::shared_ptr uvGrid, std::unique_ptrparticlesBeached->SetName("particlesBeached"); this->particlesBeached->SetNumberOfComponents(0); + this->particlesAge = vtkSmartPointer::New(); + this->particlesAge->SetName("particlesAge"); + this->particlesAge->SetNumberOfComponents(0); + data->GetPointData()->AddArray(this->particlesBeached); - data->GetPointData()->SetActiveScalars("particlesBeached"); + data->GetPointData()->AddArray(this->particlesAge); + data->GetPointData()->SetActiveScalars("particlesAge"); advector = std::move(advectionKernel); this->uvGrid = uvGrid; @@ -86,8 +96,9 @@ LGlyphLayer::LGlyphLayer(std::shared_ptr uvGrid, std::unique_ptr mapper; mapper->SetInputConnection(glyph2D->GetOutputPort()); - mapper->SetLookupTable(buildLut(this->beachedAtNumberOfTimes)); - mapper->SetScalarRange(0, this->beachedAtNumberOfTimes+1); + mapper->SetColorModeToMapScalars(); + mapper->SetLookupTable(buildLut(512)); + mapper->UseLookupTableScalarRangeOn(); mapper->Update(); vtkNew actor; @@ -101,6 +112,7 @@ void LGlyphLayer::spoofPoints() { for (int j=0; j < 330; j+=5) { this->points->InsertNextPoint(-15.875+(12.875+15.875)/330*j, 46.125+(62.625-46.125)/330*i, 0); this->particlesBeached->InsertNextValue(0); + this->particlesAge->InsertNextValue(0); } } this->points->Modified(); @@ -113,16 +125,24 @@ void LGlyphLayer::updateData(int t) { // iterate over every point. for (vtkIdType n=0; n < this->points->GetNumberOfPoints(); n++) { + // first check: only update points within our grid's boundary. + this->points->GetPoint(n, point); + 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. + this->particlesBeached->SetValue(n, this->beachedAtNumberOfTimes+1); + this->particlesAge->SetValue(n, -1); + continue; + } + + // update particle age. + int age = this->particlesAge->GetValue(n); + if (age >= 0) + this->particlesAge->SetValue(n, age+1); + + // second check: only update non-beached particles. int beachedFor = this->particlesBeached->GetValue(n); - // first check: only update non-beached particles. if (beachedFor < this->beachedAtNumberOfTimes-1) { - this->points->GetPoint(n, point); - // second check: only update points within our grid's boundary. - 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. - this->particlesBeached->SetValue(n, this->beachedAtNumberOfTimes+1); - continue; - } + oldX = point[0]; oldY = point[1]; // supersampling @@ -140,7 +160,10 @@ void LGlyphLayer::updateData(int t) { } } } - if (modifiedData) this->points->Modified(); + if (modifiedData) { + this->particlesAge->Modified(); + this->points->Modified(); + } } void LGlyphLayer::addObservers(vtkSmartPointer interactor) { diff --git a/particle-track-and-trace/src/layers/LGlyphLayer.h b/particle-track-and-trace/src/layers/LGlyphLayer.h index 58d9b95..8cec151 100644 --- a/particle-track-and-trace/src/layers/LGlyphLayer.h +++ b/particle-track-and-trace/src/layers/LGlyphLayer.h @@ -13,7 +13,9 @@ class LGlyphLayer : public Layer { private: vtkSmartPointer points; + vtkSmartPointer data; vtkSmartPointer particlesBeached; + vtkSmartPointer particlesAge; std::unique_ptr advector; std::shared_ptr uvGrid; int dt = 3600; diff --git a/particle-track-and-trace/src/main.cpp b/particle-track-and-trace/src/main.cpp index 00cc38d..6997c65 100644 --- a/particle-track-and-trace/src/main.cpp +++ b/particle-track-and-trace/src/main.cpp @@ -31,7 +31,7 @@ int main() { cout << "Starting vtk..." << endl; auto l = new LGlyphLayer(uvGrid, std::move(kernelRK4BoundaryChecked)); -// l->spoofPoints(); + l->spoofPoints(); l->setDt(DT); unique_ptr program = make_unique(DT);