Files
interactive-track-and-trace/particle-track-and-trace/src/layers/EGlyphLayer.cpp
2024-05-06 17:08:09 +02:00

103 lines
2.9 KiB
C++

#include "EGlyphLayer.h"
#include <vtkPointData.h>
#include <vtkDoubleArray.h>
#include <vtkGlyphSource2D.h>
#include <vtkRegularPolygonSource.h>
#include <vtkGlyph2D.h>
#include <vtkActor2D.h>
#include <vtkNamedColors.h>
#include <vtkPolyDataMapper2D.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkProperty2D.h>
#include <vtkVertexGlyphFilter.h>
#include <vtkArrowSource.h>
#include "../CartographicTransformation.h"
#include "../advection/readdata.h"
#include "../advection/interpolate.h"
using namespace std;
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");
readCoordinates();
}
void EGlyphLayer::readCoordinates() {
vtkNew<vtkPoints> points;
this->numLats = uvGrid->lats.size();
this->numLons = uvGrid->lons.size();
this->direction->SetNumberOfComponents(3);
this->direction->SetNumberOfTuples(numLats * numLons);
points->Allocate(numLats * numLons);
int i = 0;
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);
lonIndex++;
}
latIndex++;
}
this->data->SetPoints(points);
this->data->GetPointData()->AddArray(this->direction);
this->data->GetPointData()->SetActiveVectors("direction");
vtkSmartPointer<vtkTransformFilter> transformFilter = createCartographicTransformFilter(uvGrid);
transformFilter->SetInputData(data);
vtkNew<vtkGlyphSource2D> arrowSource;
arrowSource->SetGlyphTypeToArrow();
arrowSource->SetScale(0.2); //TODO: set this properly
arrowSource->Update();
vtkNew<vtkGlyph2D> glyph2D;
glyph2D->SetSourceConnection(arrowSource->GetOutputPort());
glyph2D->SetInputConnection(transformFilter->GetOutputPort());
glyph2D->OrientOn();
glyph2D->ClampingOn();
glyph2D->SetScaleModeToScaleByVector();
glyph2D->SetVectorModeToUseVector();
glyph2D->Update();
vtkNew<vtkPolyDataMapper>(mapper);
mapper->SetInputConnection(glyph2D->GetOutputPort());
mapper->Update();
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
actor->GetProperty()->SetColor(0, 0, 0);
actor->GetProperty()->SetOpacity(0.2);
this->ren->AddActor(actor);
}
void EGlyphLayer::updateData(int t) {
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();
}