prepared new files
This commit is contained in:
parent
7eae1a76f9
commit
fda34360ba
|
|
@ -0,0 +1,179 @@
|
|||
#include "LGlyphLayer.h"
|
||||
#include "../commands/SpawnPointCallback.h"
|
||||
#include <vtkActor2D.h>
|
||||
#include <vtkGlyph2D.h>
|
||||
#include <vtkLookupTable.h>
|
||||
#include <vtkGlyphSource2D.h>
|
||||
#include <vtkNamedColors.h>
|
||||
#include <vtkPointData.h>
|
||||
#include <vtkPolyDataMapper2D.h>
|
||||
#include <vtkProperty.h>
|
||||
#include <vtkProperty2D.h>
|
||||
#include <vtkVertexGlyphFilter.h>
|
||||
#include <vtkInteractorStyle.h>
|
||||
#include <vtkInteractorStyleUser.h>
|
||||
#include <vtkTransform.h>
|
||||
#include <vtkTransformFilter.h>
|
||||
#include <vtkPolyDataMapper.h>
|
||||
#include <vtkRenderWindow.h>
|
||||
#include <vtkCamera.h>
|
||||
|
||||
#include "../CartographicTransformation.h"
|
||||
|
||||
vtkSmartPointer<SpawnPointCallback> LGlyphLayer::createSpawnPointCallback() {
|
||||
auto newPointCallBack = vtkSmartPointer<SpawnPointCallback>::New();
|
||||
newPointCallBack->setData(this->data);
|
||||
newPointCallBack->setPoints(this->points);
|
||||
newPointCallBack->setRen(this->ren);
|
||||
newPointCallBack->setUVGrid(this->uvGrid);
|
||||
newPointCallBack->setBeached(this->particlesBeached);
|
||||
newPointCallBack->setAge(this->particlesAge);
|
||||
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.
|
||||
|
||||
/**
|
||||
* 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 [1,1,1,0.25] in n steps.
|
||||
*/
|
||||
vtkSmartPointer<vtkLookupTable> buildLut(int n) {
|
||||
vtkNew<vtkLookupTable> lut;
|
||||
lut->SetNumberOfColors(n);
|
||||
lut->SetTableRange(0, n);
|
||||
lut->SetScaleToLinear();
|
||||
lut->Build();
|
||||
for (int i=0; i < n; i++) {
|
||||
lut->SetTableValue(i, 1, 1, 1, 1-(0.75*i/(n-1)));
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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();
|
||||
vtkNew<vtkPolyData> data;
|
||||
data->SetPoints(this->points);
|
||||
|
||||
this->particlesBeached = vtkSmartPointer<vtkIntArray>::New();
|
||||
this->particlesBeached->SetName("particlesBeached");
|
||||
this->particlesBeached->SetNumberOfComponents(0);
|
||||
|
||||
this->particlesAge = vtkSmartPointer<vtkIntArray>::New();
|
||||
this->particlesAge->SetName("particlesAge");
|
||||
this->particlesAge->SetNumberOfComponents(0);
|
||||
|
||||
data->GetPointData()->AddArray(this->particlesBeached);
|
||||
data->GetPointData()->AddArray(this->particlesAge);
|
||||
data->GetPointData()->SetActiveScalars("particlesAge");
|
||||
|
||||
advector = std::move(advectionKernel);
|
||||
this->uvGrid = uvGrid;
|
||||
|
||||
vtkSmartPointer<vtkTransformFilter> transformFilter = createCartographicTransformFilter(uvGrid);
|
||||
transformFilter->SetInputData(data);
|
||||
|
||||
vtkNew<vtkGlyphSource2D> circleSource;
|
||||
circleSource->SetGlyphTypeToCircle();
|
||||
circleSource->SetScale(0.02);
|
||||
circleSource->Update();
|
||||
|
||||
vtkNew<vtkGlyph2D> glyph2D;
|
||||
glyph2D->SetSourceConnection(circleSource->GetOutputPort());
|
||||
glyph2D->SetInputConnection(transformFilter->GetOutputPort());
|
||||
glyph2D->SetScaleModeToDataScalingOff();
|
||||
glyph2D->Update();
|
||||
|
||||
vtkNew<vtkPolyDataMapper> mapper;
|
||||
mapper->SetInputConnection(glyph2D->GetOutputPort());
|
||||
mapper->SetColorModeToMapScalars();
|
||||
mapper->SetLookupTable(buildLut(512));
|
||||
mapper->UseLookupTableScalarRangeOn();
|
||||
mapper->Update();
|
||||
|
||||
vtkNew<vtkActor> actor;
|
||||
actor->SetMapper(mapper);
|
||||
|
||||
this->ren->AddActor(actor);
|
||||
}
|
||||
|
||||
void LGlyphLayer::spoofPoints() {
|
||||
for (int i=0; i < 330; i+=5) {
|
||||
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();
|
||||
}
|
||||
|
||||
void LGlyphLayer::updateData(int t) {
|
||||
const int SUPERSAMPLINGRATE = 4;
|
||||
double point[3], oldX, oldY;
|
||||
bool modifiedData = false;
|
||||
|
||||
// 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);
|
||||
if (beachedFor < this->beachedAtNumberOfTimes-1) {
|
||||
|
||||
oldX = point[0]; oldY = point[1];
|
||||
|
||||
// supersampling
|
||||
for (int i=0; i < SUPERSAMPLINGRATE; i++) {
|
||||
std::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 (oldX == point[0] and oldY == point[1]) {
|
||||
this->particlesBeached->SetValue(n, beachedFor+1);
|
||||
} else {
|
||||
this->particlesBeached->SetValue(n, std::max(beachedFor-1, 0));
|
||||
this->points->SetPoint(n, point);
|
||||
modifiedData = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (modifiedData) {
|
||||
this->particlesAge->Modified();
|
||||
this->points->Modified();
|
||||
}
|
||||
}
|
||||
|
||||
void LGlyphLayer::addObservers(vtkSmartPointer<vtkRenderWindowInteractor> interactor) {
|
||||
auto newPointCallBack = createSpawnPointCallback();
|
||||
interactor->AddObserver(vtkCommand::LeftButtonPressEvent, newPointCallBack);
|
||||
interactor->AddObserver(vtkCommand::LeftButtonReleaseEvent, newPointCallBack);
|
||||
interactor->AddObserver(vtkCommand::MouseMoveEvent, newPointCallBack);
|
||||
}
|
||||
|
||||
|
||||
void LGlyphLayer::setDt(int dt) {
|
||||
this->dt = dt;
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef LCOLLAYER_H
|
||||
#define LCOLLAYER_H
|
||||
|
||||
#include "Layer.h"
|
||||
#include "../advection/kernel/AdvectionKernel.h"
|
||||
#include "../commands/SpawnPointCallback.h"
|
||||
#include <vtkPolyData.h>
|
||||
#include <vtkInteractorStyle.h>
|
||||
|
||||
/** Implements the Layer class for the case of a Lagrangian visualization.
|
||||
* Specifically, this class models the Lagrangian particles in the simulation using the 'glyph' mark and 'transparency' channel to denote age.
|
||||
*/
|
||||
class LColLayer : public Layer {
|
||||
private:
|
||||
vtkSmartPointer<vtkPoints> points;
|
||||
vtkSmartPointer<vtkPolyData> data;
|
||||
vtkSmartPointer<vtkIntArray> particlesBeached;
|
||||
vtkSmartPointer<vtkIntArray> particlesAge;
|
||||
std::unique_ptr<AdvectionKernel> advector;
|
||||
std::shared_ptr<UVGrid> uvGrid;
|
||||
int dt = 3600;
|
||||
int beachedAtNumberOfTimes = 20;
|
||||
|
||||
public:
|
||||
/** Constructor.
|
||||
*/
|
||||
LColLayer(std::shared_ptr<UVGrid> uvGrid, std::unique_ptr<AdvectionKernel> advectionKernel);
|
||||
|
||||
/**
|
||||
* This function spoofs a few points in the dataset. Mostly used for testing.
|
||||
*/
|
||||
void spoofPoints();
|
||||
|
||||
/**
|
||||
* updates the glyphs to reflect the given timestamp in the dataset.
|
||||
* @param t : the time at which to fetch the data.
|
||||
*/
|
||||
void updateData(int t) override;
|
||||
|
||||
vtkSmartPointer<SpawnPointCallback> createSpawnPointCallback();
|
||||
|
||||
void addObservers(vtkSmartPointer<vtkRenderWindowInteractor> interactor) override;
|
||||
|
||||
|
||||
/**
|
||||
* Sets a custom DT value, needed for advect calls to the simulation logic.
|
||||
*/
|
||||
void setDt(int dt);
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue