diff --git a/vtk/src/advection/AdvectionKernel.h b/vtk/src/advection/AdvectionKernel.h index 50da1ce..5f6c784 100644 --- a/vtk/src/advection/AdvectionKernel.h +++ b/vtk/src/advection/AdvectionKernel.h @@ -19,7 +19,7 @@ public: * @param longitude Longitude of particle * @return A pair of latitude and longitude of particle. */ - virtual std::pair advect(int time, double latitude, double longitude) const = 0; + virtual std::pair advect(int time, double latitude, double longitude, int dt) const = 0; // Taken from Parcels https://github.com/OceanParcels/parcels/blob/daa4b062ed8ae0b2be3d87367d6b45599d6f95db/parcels/tools/converters.py#L155 const static double metreToDegrees(double metre) { diff --git a/vtk/src/advection/EulerAdvectionKernel.cpp b/vtk/src/advection/EulerAdvectionKernel.cpp index 82059cc..f9a4b52 100644 --- a/vtk/src/advection/EulerAdvectionKernel.cpp +++ b/vtk/src/advection/EulerAdvectionKernel.cpp @@ -4,9 +4,9 @@ using namespace std; -EulerAdvectionKernel::EulerAdvectionKernel(std::shared_ptr grid, int dt) : grid(grid), dt(dt) {} +EulerAdvectionKernel::EulerAdvectionKernel(std::shared_ptr grid) : grid(grid) {} -std::pair EulerAdvectionKernel::advect(int time, double latitude, double longitude) const { +std::pair EulerAdvectionKernel::advect(int time, double latitude, double longitude, int dt) const { auto [u, v] = bilinearinterpolate(*grid, time, latitude, longitude); return {latitude + metreToDegrees(v * dt), longitude + metreToDegrees(u * dt)}; diff --git a/vtk/src/advection/EulerAdvectionKernel.h b/vtk/src/advection/EulerAdvectionKernel.h index e2d9353..2938019 100644 --- a/vtk/src/advection/EulerAdvectionKernel.h +++ b/vtk/src/advection/EulerAdvectionKernel.h @@ -15,10 +15,9 @@ class EulerAdvectionKernel: public AdvectionKernel { private: std::shared_ptr grid; - int dt; public: - explicit EulerAdvectionKernel(std::shared_ptr grid, int dt); - std::pair advect(int time, double latitude, double longitude) const override; + explicit EulerAdvectionKernel(std::shared_ptr grid); + std::pair advect(int time, double latitude, double longitude, int dt) const override; }; diff --git a/vtk/src/advection/RK4AdvectionKernel.cpp b/vtk/src/advection/RK4AdvectionKernel.cpp index 2e62fdf..85104b5 100644 --- a/vtk/src/advection/RK4AdvectionKernel.cpp +++ b/vtk/src/advection/RK4AdvectionKernel.cpp @@ -3,9 +3,9 @@ using namespace std; -RK4AdvectionKernel::RK4AdvectionKernel(std::shared_ptr grid, int dt): grid(grid), dt(dt) { } +RK4AdvectionKernel::RK4AdvectionKernel(std::shared_ptr grid): grid(grid) { } -std::pair RK4AdvectionKernel::advect(int time, double latitude, double longitude) const { +std::pair RK4AdvectionKernel::advect(int time, double latitude, double longitude, int dt) const { auto [u1, v1] = bilinearinterpolate(*grid, time, latitude, longitude); // lon1, lat1 = (particle.lon + u1*.5*particle.dt, particle.lat + v1*.5*particle.dt); double lon1 = longitude + metreToDegrees(u1 * 0.5*dt); diff --git a/vtk/src/advection/RK4AdvectionKernel.h b/vtk/src/advection/RK4AdvectionKernel.h index ce7d4e3..94db490 100644 --- a/vtk/src/advection/RK4AdvectionKernel.h +++ b/vtk/src/advection/RK4AdvectionKernel.h @@ -12,10 +12,9 @@ class RK4AdvectionKernel: public AdvectionKernel { private: std::shared_ptr grid; - int dt; public: - explicit RK4AdvectionKernel(std::shared_ptr grid, int dt); - std::pair advect(int time, double latitude, double longitude) const override; + explicit RK4AdvectionKernel(std::shared_ptr grid); + std::pair advect(int time, double latitude, double longitude, int dt) const override; }; diff --git a/vtk/src/layers/LGlyphLayer.cpp b/vtk/src/layers/LGlyphLayer.cpp index 311c49c..3e0e53c 100644 --- a/vtk/src/layers/LGlyphLayer.cpp +++ b/vtk/src/layers/LGlyphLayer.cpp @@ -17,14 +17,13 @@ #include "../CartographicTransformation.h" - vtkSmartPointer LGlyphLayer::createSpawnPointCallback() { - auto newPointCallBack = vtkSmartPointer::New(); - newPointCallBack->setData(data); - newPointCallBack->setPoints(points); - newPointCallBack->setRen(ren); - newPointCallBack->setUVGrid(uvGrid); - return newPointCallBack; + auto newPointCallBack = vtkSmartPointer::New(); + newPointCallBack->setData(data); + newPointCallBack->setPoints(points); + newPointCallBack->setRen(ren); + newPointCallBack->setUVGrid(uvGrid); + return newPointCallBack; } // 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. @@ -33,72 +32,72 @@ vtkSmartPointer LGlyphLayer::createSpawnPointCallback() { // TODO: modelling all this in vtkClasses is workable, but ideally i would want to work with a native C++ class. See if this is doable and feasible. LGlyphLayer::LGlyphLayer(std::shared_ptr uvGrid, std::unique_ptr advectionKernel) { - this->ren = vtkSmartPointer::New(); - this->ren->SetLayer(2); + this->ren = vtkSmartPointer::New(); + this->ren->SetLayer(2); - this->points = vtkSmartPointer::New(); - this->data = vtkSmartPointer::New(); - this->data->SetPoints(this->points); + this->points = vtkSmartPointer::New(); + this->data = vtkSmartPointer::New(); + this->data->SetPoints(this->points); - advector = std::move(advectionKernel); - this->uvGrid = uvGrid; + advector = std::move(advectionKernel); + this->uvGrid = uvGrid; - auto camera = createNormalisedCamera(); - ren->SetActiveCamera(camera); + auto camera = createNormalisedCamera(); + ren->SetActiveCamera(camera); - vtkSmartPointer transformFilter = createCartographicTransformFilter(uvGrid); - transformFilter->SetInputData(data); + vtkSmartPointer transformFilter = createCartographicTransformFilter(uvGrid); + transformFilter->SetInputData(data); - vtkNew circleSource; - circleSource->SetGlyphTypeToCircle(); - circleSource->SetScale(0.05); - circleSource->Update(); + vtkNew circleSource; + circleSource->SetGlyphTypeToCircle(); + circleSource->SetScale(0.05); + circleSource->Update(); - vtkNew glyph2D; - glyph2D->SetSourceConnection(circleSource->GetOutputPort()); - glyph2D->SetInputConnection(transformFilter->GetOutputPort()); - glyph2D->SetColorModeToColorByScalar(); - glyph2D->Update(); + vtkNew glyph2D; + glyph2D->SetSourceConnection(circleSource->GetOutputPort()); + glyph2D->SetInputConnection(transformFilter->GetOutputPort()); + glyph2D->SetColorModeToColorByScalar(); + glyph2D->Update(); - vtkNew mapper; - mapper->SetInputConnection(glyph2D->GetOutputPort()); - mapper->Update(); + vtkNew mapper; + mapper->SetInputConnection(glyph2D->GetOutputPort()); + mapper->Update(); - vtkNew actor; - actor->SetMapper(mapper); + vtkNew actor; + actor->SetMapper(mapper); - this->ren->AddActor(actor); + this->ren->AddActor(actor); } // creates a few points so we can test the updateData function void LGlyphLayer::spoofPoints() { - this->points->InsertNextPoint(-4.125, 61.375 , 0); - this->points->InsertNextPoint(6.532949683882039, 53.24308582564463, 0); // Coordinates of Zernike - this->points->InsertNextPoint(5.315307819255385, 60.40001057122271, 0); // Coordinates of Bergen - this->points->InsertNextPoint( 6.646210231365825, 46.52346296009023, 0); // Coordinates of Lausanne - this->points->InsertNextPoint(-6.553894313570932, 62.39522131195857, 0); // Coordinates of the top of the Faroe islands + this->points->InsertNextPoint(-4.125, 61.375, 0); + this->points->InsertNextPoint(6.532949683882039, 53.24308582564463, 0); // Coordinates of Zernike + this->points->InsertNextPoint(5.315307819255385, 60.40001057122271, 0); // Coordinates of Bergen + this->points->InsertNextPoint(6.646210231365825, 46.52346296009023, 0); // Coordinates of Lausanne + this->points->InsertNextPoint(-6.553894313570932, 62.39522131195857, + 0); // Coordinates of the top of the Faroe islands - this->points->Modified(); -} - -// returns new coords for a point; used to test the updateData function -std::pair advect(int time, double lat, double lon) { - return {lat + 0.01, lon + 0.01}; + this->points->Modified(); } void LGlyphLayer::updateData(int t) { - double point[3]; - for (vtkIdType n = 0; n < this->points->GetNumberOfPoints(); n++) { - this->points->GetPoint(n, point); - auto [yNew, xNew] = advector->advect(t, point[1], point[0]); - this->points->SetPoint(n, xNew, yNew, 0); + const int SUPERSAMPLINGRATE = 4; + double point[3]; + for (vtkIdType n = 0; n < this->points->GetNumberOfPoints(); n++) { + this->points->GetPoint(n, point); + for (int i = 0; i < SUPERSAMPLINGRATE; i++) { + std::tie(point[1], point[0]) = advector->advect(t, point[1], point[0], (t-lastT)/SUPERSAMPLINGRATE); } - this->points->Modified(); + this->points->SetPoint(n, point[0], point[1], 0); + } + lastT = t; + this->points->Modified(); } void LGlyphLayer::addObservers(vtkSmartPointer interactor) { - auto newPointCallBack = createSpawnPointCallback(); - interactor->AddObserver(vtkCommand::LeftButtonPressEvent, newPointCallBack); - interactor->AddObserver(vtkCommand::LeftButtonReleaseEvent, newPointCallBack); - interactor->AddObserver(vtkCommand::MouseMoveEvent, newPointCallBack); + auto newPointCallBack = createSpawnPointCallback(); + interactor->AddObserver(vtkCommand::LeftButtonPressEvent, newPointCallBack); + interactor->AddObserver(vtkCommand::LeftButtonReleaseEvent, newPointCallBack); + interactor->AddObserver(vtkCommand::MouseMoveEvent, newPointCallBack); } diff --git a/vtk/src/layers/LGlyphLayer.h b/vtk/src/layers/LGlyphLayer.h index 48d3108..422cfcb 100644 --- a/vtk/src/layers/LGlyphLayer.h +++ b/vtk/src/layers/LGlyphLayer.h @@ -16,6 +16,7 @@ private: vtkSmartPointer data; std::unique_ptr advector; std::shared_ptr uvGrid; + int lastT = 1000; public: /** Constructor. diff --git a/vtk/src/main.cpp b/vtk/src/main.cpp index 7486eb1..592d943 100644 --- a/vtk/src/main.cpp +++ b/vtk/src/main.cpp @@ -22,10 +22,9 @@ using namespace std; int main() { shared_ptr uvGrid = std::make_shared(); - auto kernelRK4 = make_unique(uvGrid, DT); + auto kernelRK4 = make_unique(uvGrid); auto l = new LGlyphLayer(uvGrid, move(kernelRK4)); -// l->spoofPoints(); Program *program = new Program(DT); program->addLayer(new BackgroundImage("../../../../data/map_661-661.png"));