implemented LColMap functionality
This commit is contained in:
parent
30892988fd
commit
305a812dfa
|
|
@ -107,6 +107,7 @@ void Program::setActiveTechnique(int idx) {
|
||||||
this->techniques[idx]->bind(this->win, this->interact);
|
this->techniques[idx]->bind(this->win, this->interact);
|
||||||
|
|
||||||
this->activeIdx = idx;
|
this->activeIdx = idx;
|
||||||
|
this->win->Render();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,6 @@ void MainWindow::setupTechniques() {
|
||||||
|
|
||||||
technique1->addLayer(lGlyph);
|
technique1->addLayer(lGlyph);
|
||||||
technique2->addLayer(lCol);
|
technique2->addLayer(lCol);
|
||||||
// technique2->addLayer(lGlyph);
|
|
||||||
|
|
||||||
program->addTechnique(technique1);
|
program->addTechnique(technique1);
|
||||||
program->addTechnique(technique2);
|
program->addTechnique(technique2);
|
||||||
|
|
|
||||||
|
|
@ -255,7 +255,7 @@ public:
|
||||||
MonochromaticButton->setText(QCoreApplication::translate("MainWindow", "Monochromatic", nullptr));
|
MonochromaticButton->setText(QCoreApplication::translate("MainWindow", "Monochromatic", nullptr));
|
||||||
SaturationBox->setTitle(QCoreApplication::translate("MainWindow", "Saturation", nullptr));
|
SaturationBox->setTitle(QCoreApplication::translate("MainWindow", "Saturation", nullptr));
|
||||||
SaturateButton->setText(QCoreApplication::translate("MainWindow", "Fully saturated", nullptr));
|
SaturateButton->setText(QCoreApplication::translate("MainWindow", "Fully saturated", nullptr));
|
||||||
DesaturateButton->setText(QCoreApplication::translate("MainWindow", "Desaturated", nullptr));
|
DesaturateButton->setText(QCoreApplication::translate("MainWindow", "Gradually saturated", nullptr));
|
||||||
GlyphBox->setTitle(QCoreApplication::translate("MainWindow", "Glyph Shape", nullptr));
|
GlyphBox->setTitle(QCoreApplication::translate("MainWindow", "Glyph Shape", nullptr));
|
||||||
CircleButton->setText(QCoreApplication::translate("MainWindow", "Circle", nullptr));
|
CircleButton->setText(QCoreApplication::translate("MainWindow", "Circle", nullptr));
|
||||||
TriangleButton->setText(QCoreApplication::translate("MainWindow", "Triangle", nullptr));
|
TriangleButton->setText(QCoreApplication::translate("MainWindow", "Triangle", nullptr));
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,8 @@ EColLayer::EColLayer(std::shared_ptr<UVGrid> uvGrid) {
|
||||||
this->ren->InteractiveOff();
|
this->ren->InteractiveOff();
|
||||||
|
|
||||||
this->uvGrid = uvGrid;
|
this->uvGrid = uvGrid;
|
||||||
this->numLats = uvGrid->lats.size();
|
this->numLats = uvGrid->latSize;
|
||||||
this->numLons = uvGrid->lons.size();
|
this->numLons = uvGrid->lonSize;
|
||||||
|
|
||||||
this->strength = vtkSmartPointer<vtkDoubleArray>::New();
|
this->strength = vtkSmartPointer<vtkDoubleArray>::New();
|
||||||
this->strength->SetName("strength");
|
this->strength->SetName("strength");
|
||||||
|
|
@ -121,12 +121,6 @@ void EColLayer::readCoordinates() {
|
||||||
l->SetId(1, idx-numLats-1);
|
l->SetId(1, idx-numLats-1);
|
||||||
l->SetId(2, idx-numLats);
|
l->SetId(2, idx-numLats);
|
||||||
l->SetId(3, idx);
|
l->SetId(3, idx);
|
||||||
|
|
||||||
double coords[12];
|
|
||||||
points->GetPoint(idx-1, coords);
|
|
||||||
points->GetPoint(idx-numLats-1, coords+3);
|
|
||||||
points->GetPoint(idx-numLats, coords+6);
|
|
||||||
points->GetPoint(idx, coords+9);
|
|
||||||
data->InsertNextCell(VTK_QUAD, l);
|
data->InsertNextCell(VTK_QUAD, l);
|
||||||
|
|
||||||
// ltake the average of the four surrounding points as the cell's velocity.
|
// ltake the average of the four surrounding points as the cell's velocity.
|
||||||
|
|
|
||||||
|
|
@ -31,39 +31,46 @@ vtkSmartPointer<SpawnPointCallback> LColLayer::createSpawnPointCallback() {
|
||||||
return newPointCallBack;
|
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) {
|
// TODO: edit this function; probably extract all lut builders into a builder pattern or something.
|
||||||
|
vtkSmartPointer<vtkLookupTable> buildLutDens() {
|
||||||
|
int n = 5;
|
||||||
vtkNew<vtkLookupTable> lut;
|
vtkNew<vtkLookupTable> lut;
|
||||||
lut->SetNumberOfColors(n);
|
lut->SetNumberOfColors(n);
|
||||||
lut->SetTableRange(0, n);
|
lut->SetTableRange(1, n+1);
|
||||||
lut->SetScaleToLinear();
|
lut->SetScaleToLinear();
|
||||||
lut->Build();
|
lut->Build();
|
||||||
for (int i=0; i < n; i++) {
|
for (int i=n-1; i >= 0; i--) {
|
||||||
lut->SetTableValue(i, 1, 1, 1, 1-(0.75*i/(n-1)));
|
lut->SetTableValue(i, 0, 1-(0.75*i/(n-1)), 1, 1);
|
||||||
}
|
}
|
||||||
lut->UseAboveRangeColorOn();
|
lut->UseAboveRangeColorOn();
|
||||||
lut->SetAboveRangeColor(1,1,1,0.20);
|
lut->SetAboveRangeColor(1,0,0,1);
|
||||||
|
|
||||||
// We cheat a little here: any particle with an age of -1 is out of bounds, and thus set invisible.
|
|
||||||
lut->UseBelowRangeColorOn();
|
lut->UseBelowRangeColorOn();
|
||||||
lut->SetBelowRangeColor(1,1,1,0);
|
lut->SetBelowRangeColor(1,1,1,0);
|
||||||
|
|
||||||
return lut;
|
return lut;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// There's two separate pipelines going on here: the one where we build a vtkPoints array for the spawnpointcallback,
|
||||||
|
// and the one where we build a vtkPolyData with Cells for the colour map.
|
||||||
|
// TODO: it would make sense to separate these pipelines out to their own functions.
|
||||||
LColLayer::LColLayer(std::shared_ptr<UVGrid> uvGrid, std::unique_ptr<AdvectionKernel> advectionKernel) {
|
LColLayer::LColLayer(std::shared_ptr<UVGrid> uvGrid, std::unique_ptr<AdvectionKernel> advectionKernel) {
|
||||||
|
// general management; probably should be the actual constructor.
|
||||||
this->ren = vtkSmartPointer<vtkRenderer>::New();
|
this->ren = vtkSmartPointer<vtkRenderer>::New();
|
||||||
this->ren->SetLayer(2);
|
this->ren->SetLayer(2);
|
||||||
|
|
||||||
|
this->uvGrid = uvGrid;
|
||||||
|
this->numLats = uvGrid->latSize;
|
||||||
|
this->numLons = uvGrid->lonSize;
|
||||||
|
this->advector = std::move(advectionKernel);
|
||||||
|
|
||||||
|
|
||||||
|
// pipeline 1
|
||||||
this->points = vtkSmartPointer<vtkPoints>::New();
|
this->points = vtkSmartPointer<vtkPoints>::New();
|
||||||
vtkNew<vtkPolyData> data;
|
|
||||||
data->SetPoints(this->points);
|
|
||||||
|
|
||||||
this->particlesBeached = vtkSmartPointer<vtkIntArray>::New();
|
this->particlesBeached = vtkSmartPointer<vtkIntArray>::New();
|
||||||
this->particlesBeached->SetName("particlesBeached");
|
this->particlesBeached->SetName("particlesBeached");
|
||||||
|
|
@ -73,30 +80,70 @@ LColLayer::LColLayer(std::shared_ptr<UVGrid> uvGrid, std::unique_ptr<AdvectionKe
|
||||||
this->particlesAge->SetName("particlesAge");
|
this->particlesAge->SetName("particlesAge");
|
||||||
this->particlesAge->SetNumberOfComponents(1);
|
this->particlesAge->SetNumberOfComponents(1);
|
||||||
|
|
||||||
this->uvGrid = uvGrid;
|
|
||||||
this->numLats = uvGrid->lats.size();
|
// pipeline 2
|
||||||
this->numLons = uvGrid->lons.size();
|
this->data = vtkSmartPointer<vtkPolyData>::New();
|
||||||
|
vtkNew<vtkPoints> cellPoints;
|
||||||
|
cellPoints->Allocate(numLats*numLons);
|
||||||
|
this->data->SetPoints(cellPoints);
|
||||||
|
data->Allocate((numLats-1)*(numLons-1));
|
||||||
|
|
||||||
this->cellParticleDensity = vtkSmartPointer<vtkIntArray>::New();
|
this->cellParticleDensity = vtkSmartPointer<vtkIntArray>::New();
|
||||||
this->cellParticleDensity->SetName("cellParticleDensity");
|
this->cellParticleDensity->SetName("cellParticleDensity");
|
||||||
this->cellParticleDensity->SetNumberOfComponents(1);
|
this->cellParticleDensity->SetNumberOfComponents(1);
|
||||||
this->cellParticleDensity->SetNumberOfTuples((numLats-1)*(numLons-1));
|
this->cellParticleDensity->SetNumberOfTuples((numLats-1)*(numLons-1));
|
||||||
|
|
||||||
data->GetPointData()->AddArray(this->particlesBeached);
|
this->data->GetCellData()->AddArray(this->cellParticleDensity);
|
||||||
data->GetPointData()->AddArray(this->particlesAge);
|
this->data->GetCellData()->SetActiveScalars("cellParticleDensity");
|
||||||
data->GetCellData()->AddArray(this->cellParticleDensity);
|
|
||||||
data->GetPointData()->SetActiveScalars("particlesAge");
|
|
||||||
data->GetCellData()->SetActiveScalars("cellParticleDensity");
|
|
||||||
|
|
||||||
advector = std::move(advectionKernel);
|
|
||||||
this->uvGrid = uvGrid;
|
|
||||||
|
|
||||||
vtkSmartPointer<vtkTransformFilter> transformFilter = createCartographicTransformFilter(uvGrid);
|
vtkSmartPointer<vtkTransformFilter> transformFilter = createCartographicTransformFilter(uvGrid);
|
||||||
transformFilter->SetInputData(data);
|
auto transform = transformFilter->GetTransform();
|
||||||
|
|
||||||
|
int cellId = 0, pointId = 0;
|
||||||
|
int latIndex = 0, lonIndex = 0;
|
||||||
|
for (auto lon : uvGrid->lons) {
|
||||||
|
latIndex = 0;
|
||||||
|
for (auto lat : uvGrid->lats) {
|
||||||
|
double out[3] = {lon, lat, 0};
|
||||||
|
transform->TransformPoint(out, out);
|
||||||
|
cellPoints->InsertPoint(pointId++, out[0], out[1], 0);
|
||||||
|
|
||||||
|
// logic for adding cells
|
||||||
|
if (latIndex > 0 and lonIndex > 0 ) {
|
||||||
|
int idx = latIndex+lonIndex*numLats;
|
||||||
|
vtkNew<vtkIdList> l;
|
||||||
|
l->SetNumberOfIds(4);
|
||||||
|
l->SetId(0, idx-1);
|
||||||
|
l->SetId(1, idx-numLats-1);
|
||||||
|
l->SetId(2, idx-numLats);
|
||||||
|
l->SetId(3, idx);
|
||||||
|
|
||||||
|
this->data->InsertNextCell(VTK_QUAD, l);
|
||||||
|
this->cellParticleDensity->SetTuple1(cellId++, 0);
|
||||||
|
}
|
||||||
|
latIndex++;
|
||||||
|
}
|
||||||
|
lonIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
vtkNew<vtkPolyDataMapper>(mapper);
|
||||||
|
mapper->SetInputData(data);
|
||||||
|
mapper->SetLookupTable(buildLutDens());
|
||||||
|
mapper->UseLookupTableScalarRangeOn();
|
||||||
|
mapper->Update();
|
||||||
|
|
||||||
vtkNew<vtkActor> actor;
|
vtkNew<vtkActor> actor;
|
||||||
actor->SetMapper(mapper);
|
actor->SetMapper(mapper);
|
||||||
|
actor->GetProperty()->SetColor(0, 1, 0);
|
||||||
|
actor->GetProperty()->SetOpacity(0.5);
|
||||||
|
|
||||||
|
// vtkNew<vtkActor> act2;
|
||||||
|
// act2->SetMapper(mapper);
|
||||||
|
// act2->GetProperty()->SetRepresentationToWireframe();
|
||||||
|
// this->ren->AddActor(act2);
|
||||||
|
|
||||||
this->ren->AddActor(actor);
|
this->ren->AddActor(actor);
|
||||||
|
|
||||||
this->callback = createSpawnPointCallback();
|
this->callback = createSpawnPointCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,10 +158,31 @@ void LColLayer::spoofPoints() {
|
||||||
this->points->Modified();
|
this->points->Modified();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// calculates the cellIndex for a given lat,lon pair.
|
||||||
|
int LColLayer::calcIndex(double x, double y) {
|
||||||
|
int lonIndex = std::floor((x - uvGrid->lonMin()) / uvGrid->lonStep());
|
||||||
|
int latIndex = std::floor((y - uvGrid->latMin()) / uvGrid->latStep());
|
||||||
|
|
||||||
|
return latIndex+lonIndex*(uvGrid->latSize-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void printArray(vtkSmartPointer<vtkIntArray> data, int numLons, int numLats, int latsize) {
|
||||||
|
for (int i=0; i < numLons-1; i++) {
|
||||||
|
for (int j=0; j < numLats-1; j++) {
|
||||||
|
int value = data->GetValue(j+i*latsize);
|
||||||
|
if (value > 1)
|
||||||
|
cout << "(" << i << ", " << j << ") ("<< j+i*latsize << "): " << value << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cout << endl;
|
||||||
|
}
|
||||||
|
|
||||||
void LColLayer::updateData(int t) {
|
void LColLayer::updateData(int t) {
|
||||||
const int SUPERSAMPLINGRATE = 4;
|
const int SUPERSAMPLINGRATE = 4;
|
||||||
double point[3], oldX, oldY;
|
double point[3], oldX, oldY;
|
||||||
bool modifiedData = false;
|
bool modifiedData = false;
|
||||||
|
this->cellParticleDensity->Fill(0);
|
||||||
|
|
||||||
// iterate over every point.
|
// iterate over every point.
|
||||||
for (vtkIdType n=0; n < this->points->GetNumberOfPoints(); n++) {
|
for (vtkIdType n=0; n < this->points->GetNumberOfPoints(); n++) {
|
||||||
|
|
@ -152,11 +220,16 @@ void LColLayer::updateData(int t) {
|
||||||
modifiedData = true;
|
modifiedData = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// add point to cellparticleDensity
|
||||||
|
int index = calcIndex(point[0], point[1]);
|
||||||
|
this->cellParticleDensity->SetValue(index, cellParticleDensity->GetValue(index)+1);
|
||||||
}
|
}
|
||||||
if (modifiedData) {
|
if (modifiedData) {
|
||||||
this->particlesAge->Modified();
|
this->particlesAge->Modified();
|
||||||
this->points->Modified();
|
this->points->Modified();
|
||||||
|
this->cellParticleDensity->Modified();
|
||||||
}
|
}
|
||||||
|
// printArray(this->cellParticleDensity, numLons, numLats, uvGrid->latSize-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LColLayer::addObservers(vtkSmartPointer<vtkRenderWindowInteractor> interactor) {
|
void LColLayer::addObservers(vtkSmartPointer<vtkRenderWindowInteractor> interactor) {
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,9 @@ private:
|
||||||
int numLats;
|
int numLats;
|
||||||
int numLons;
|
int numLons;
|
||||||
|
|
||||||
|
|
||||||
|
int calcIndex(double x, double y);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** Constructor.
|
/** Constructor.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -68,10 +68,10 @@ vtkSmartPointer<vtkLookupTable> buildLutOpacity(int n) {
|
||||||
lut->SetScaleToLinear();
|
lut->SetScaleToLinear();
|
||||||
lut->Build();
|
lut->Build();
|
||||||
for (int i=0; i < n; i++) {
|
for (int i=0; i < n; i++) {
|
||||||
lut->SetTableValue(i, 1, 1, 1, 1-(0.75*i/(n-1)));
|
lut->SetTableValue(i, 1, 0, 1, 1-(0.75*i/(n-1)));
|
||||||
}
|
}
|
||||||
lut->UseAboveRangeColorOn();
|
lut->UseAboveRangeColorOn();
|
||||||
lut->SetAboveRangeColor(1,1,1,0.20);
|
lut->SetAboveRangeColor(1,0,1,0.20);
|
||||||
|
|
||||||
// We cheat a little here: any particle with an age of -1 is out of bounds, and thus set invisible.
|
// We cheat a little here: any particle with an age of -1 is out of bounds, and thus set invisible.
|
||||||
lut->UseBelowRangeColorOn();
|
lut->UseBelowRangeColorOn();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue