Merge branch 'main' into djairo-vtk-camera

This commit is contained in:
Djairo authored and GitHub committed 2024-05-06 12:15:50 +00:00
commit 866d8e444f
33 files changed
+272 -431

No files matched your search

+30 -49
View File
@@ -11,43 +11,20 @@
#include <vtkProperty.h>
#include <vtkProperty2D.h>
#include <vtkVertexGlyphFilter.h>
#include <netcdf>
#include <vtkArrowSource.h>
#include "../CartographicTransformation.h"
#include "../advection/readdata.h"
#include "../advection/interpolate.h"
using namespace netCDF;
using namespace std;
template <typename T>
vector<T> getVarVector(const NcVar &var) {
int length = 1;
for (NcDim dim : var.getDims()) {
length *= dim.getSize();
}
vector<T> vec(length);
var.getVar(vec.data());
return vec;
}
tuple<vector<int>, vector<double>, vector<double>> readGrid() {
netCDF::NcFile data("../../../../data/grid.h5", netCDF::NcFile::read);
multimap< string, NcVar > vars = data.getVars();
vector<int> time = getVarVector<int>(vars.find("times")->second);
vector<double> longitude = getVarVector<double>(vars.find("longitude")->second);
vector<double> latitude = getVarVector<double>(vars.find("latitude")->second);
return {time, latitude, longitude};
}
EGlyphLayer::EGlyphLayer() {
EGlyphLayer::EGlyphLayer(std::shared_ptr<UVGrid> uvGrid) {
this->ren = vtkSmartPointer<vtkRenderer>::New();
this->ren->SetLayer(1);
this->ren->InteractiveOff();
this->uvGrid = uvGrid;
this->data = vtkSmartPointer<vtkPolyData>::New();
this->direction = vtkSmartPointer<vtkDoubleArray>::New();
this->direction->SetName("direction");
@@ -57,28 +34,30 @@ EGlyphLayer::EGlyphLayer() {
void EGlyphLayer::readCoordinates() {
vtkNew<vtkPoints> points;
auto [times, lats, lons] = readGrid(); // FIXME: import Robin's readData function and use it
this->numLats = lats.size();
this->numLons = lons.size();
this->numLats = uvGrid->lats.size();
this->numLons = uvGrid->lons.size();
this->direction->SetNumberOfComponents(3);
this->direction->SetNumberOfTuples(numLats*numLons);
points->Allocate(numLats*numLons);
this->direction->SetNumberOfTuples(numLats * numLons);
points->Allocate(numLats * numLons);
int i = 0;
for (double lat : lats) {
for (double lon : lons) {
// cout << "lon: " << lon << " lat: " << lat << endl;
direction->SetTuple3(i, 0.45, 0.90, 0); //FIXME: read this info from file
int latIndex = 0;
for (double lat: uvGrid->lats) {
int lonIndex = 0;
for (double lon: uvGrid->lons) {
auto [u, v] = (*uvGrid)[0, latIndex, lonIndex];
direction->SetTuple3(i, 5*u, 5*v, 0);
points->InsertPoint(i++, lon, lat, 0);
// see also https://vtk.org/doc/nightly/html/classvtkPolyDataMapper2D.html
lonIndex++;
}
latIndex++;
}
this->data->SetPoints(points);
this->data->GetPointData()->AddArray(this->direction);
this->data->GetPointData()->SetActiveVectors("direction");
vtkSmartPointer<vtkTransformFilter> transformFilter = createCartographicTransformFilter();
vtkSmartPointer<vtkTransformFilter> transformFilter = createCartographicTransformFilter(uvGrid);
transformFilter->SetInputData(data);
vtkNew<vtkGlyphSource2D> arrowSource;
@@ -91,31 +70,33 @@ void EGlyphLayer::readCoordinates() {
glyph2D->SetInputConnection(transformFilter->GetOutputPort());
glyph2D->OrientOn();
glyph2D->ClampingOn();
glyph2D->SetScaleModeToScaleByVector();
glyph2D->SetVectorModeToUseVector();
glyph2D->SetScaleModeToScaleByVector();
glyph2D->SetVectorModeToUseVector();
glyph2D->Update();
// vtkNew<vtkCoordinate> coordinate;
// coordinate->SetCoordinateSystemToWorld();
vtkNew<vtkPolyDataMapper>(mapper);
// mapper->SetTransformCoordinate(coordinate);
mapper->SetInputConnection(glyph2D->GetOutputPort());
mapper->Update();
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
actor->GetProperty()->SetColor(0,0,0);
actor->GetProperty()->SetColor(0, 0, 0);
actor->GetProperty()->SetOpacity(0.2);
this->ren->AddActor(actor) ;
this->ren->AddActor(actor);
}
void EGlyphLayer::updateData(int t) {
for (int i=0; i < numLats*numLons; i++) {
this->direction->SetTuple3(i, std::cos(t), std::sin(t), 0); // FIXME: fetch data from file.
int i = 0;
for (int lat = 0; lat < uvGrid->latSize; lat++) {
for (int lon = 0; lon < uvGrid->lonSize; lon++) {
auto [u, v] = (*uvGrid)[t/3600, lat, lon];
// TODO: 5*v scaling stuff should really be a filter transform
this->direction->SetTuple3(i, 5*u, 5*v, 0);
i++;
}
}
this->direction->Modified();
}
+5 -1
View File
@@ -2,8 +2,11 @@
#define EGLYPHLAYER_H
#include "Layer.h"
#include <memory>
#include <vtkPolyData.h>
#include "../advection/UVGrid.h"
/** Implements the Layer class for the case of a Eulerian visualization.
* Specifically, this class models the eulerian flow-fields of the simulation using the 'glyph' mark and 'direction' and 'form' channels to denote direction and strength of velocities.
*/
@@ -11,6 +14,7 @@ class EGlyphLayer : public Layer {
private:
vtkSmartPointer<vtkPolyData> data;
vtkSmartPointer<vtkDoubleArray> direction;
std::shared_ptr<UVGrid> uvGrid;
int numLats;
int numLons;
@@ -22,7 +26,7 @@ private:
public:
/** Constructor.
*/
EGlyphLayer();
EGlyphLayer(std::shared_ptr<UVGrid> uvGrid);
/** updates the glyphs to reflect the given timestamp in the dataset.
* @param t : the time at which to fetch the data.
+46 -48
View File
@@ -18,13 +18,13 @@
#include "../CartographicTransformation.h"
vtkSmartPointer<SpawnPointCallback> LGlyphLayer::createSpawnPointCallback() {
auto newPointCallBack = vtkSmartPointer<SpawnPointCallback>::New();
newPointCallBack->setData(data);
newPointCallBack->setPoints(points);
newPointCallBack->setRen(ren);
return newPointCallBack;
auto newPointCallBack = vtkSmartPointer<SpawnPointCallback>::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.
@@ -32,37 +32,39 @@ vtkSmartPointer<SpawnPointCallback> 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() {
this->ren = vtkSmartPointer<vtkRenderer>::New();
this->ren->SetLayer(2);
LGlyphLayer::LGlyphLayer(std::shared_ptr<UVGrid> uvGrid, std::unique_ptr<AdvectionKernel> advectionKernel) {
this->ren = vtkSmartPointer<vtkRenderer>::New();
this->ren->SetLayer(2);
this->points = vtkSmartPointer<vtkPoints>::New();
this->data = vtkSmartPointer<vtkPolyData>::New();
this->data->SetPoints(this->points);
this->points = vtkSmartPointer<vtkPoints>::New();
this->data = vtkSmartPointer<vtkPolyData>::New();
this->data->SetPoints(this->points);
vtkSmartPointer<vtkTransformFilter> transformFilter = createCartographicTransformFilter();
transformFilter->SetInputData(data);
advector = std::move(advectionKernel);
this->uvGrid = uvGrid;
vtkNew<vtkGlyphSource2D> circleSource;
circleSource->SetGlyphTypeToCircle();
circleSource->SetScale(0.01);
circleSource->Update();
vtkSmartPointer<vtkTransformFilter> transformFilter = createCartographicTransformFilter(uvGrid);
transformFilter->SetInputData(data);
vtkNew<vtkGlyph2D> glyph2D;
glyph2D->SetSourceConnection(circleSource->GetOutputPort());
glyph2D->SetInputConnection(transformFilter->GetOutputPort());
glyph2D->SetColorModeToColorByScalar();
glyph2D->Update();
vtkNew<vtkGlyphSource2D> circleSource;
circleSource->SetGlyphTypeToCircle();
circleSource->SetScale(0.05);
circleSource->Update();
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputConnection(glyph2D->GetOutputPort());
mapper->Update();
vtkNew<vtkGlyph2D> glyph2D;
glyph2D->SetSourceConnection(circleSource->GetOutputPort());
glyph2D->SetInputConnection(transformFilter->GetOutputPort());
glyph2D->SetColorModeToColorByScalar();
glyph2D->Update();
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
actor->GetProperty()->SetOpacity(0.8);
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputConnection(glyph2D->GetOutputPort());
mapper->Update();
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
this->ren->AddActor(actor);
this->ren->AddActor(actor);
}
// creates a few points so we can test the updateData function
@@ -82,27 +84,23 @@ void LGlyphLayer::spoofPoints() {
this->points->Modified();
}
// returns new coords for a point; used to test the updateData function
std::pair<double, double> advect(int time, double lat, double lon) {
return {lat + 0.01, lon + 0.01};
}
void LGlyphLayer::updateData(int t) {
double point[3];
for (vtkIdType n = 0; n < this->points->GetNumberOfPoints(); n++) {
this->points->GetPoint(n, point);
auto [xNew, yNew] = advect(n, point[0], point[1]);
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<vtkRenderWindowInteractor> interactor) {
auto newPointCallBack = vtkSmartPointer<SpawnPointCallback>::New();
newPointCallBack->setData(data);
newPointCallBack->setPoints(points);
newPointCallBack->setRen(ren);
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);
}
+5 -3
View File
@@ -2,6 +2,7 @@
#define LGLYPHLAYER_H
#include "Layer.h"
#include "../advection/AdvectionKernel.h"
#include "../commands/SpawnPointCallback.h"
#include <vtkPolyData.h>
#include <vtkInteractorStyle.h>
@@ -13,13 +14,14 @@ class LGlyphLayer : public Layer {
private:
vtkSmartPointer<vtkPoints> points;
vtkSmartPointer<vtkPolyData> data;
std::unique_ptr<AdvectionKernel> advector;
std::shared_ptr<UVGrid> uvGrid;
int lastT = 1000;
public:
/** Constructor.
*/
LGlyphLayer();
LGlyphLayer(std::shared_ptr<UVGrid> uvGrid, std::unique_ptr<AdvectionKernel> advectionKernel);
/** This function spoofs a few points in the dataset. Mostly used for testing.
*/
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.