Feat: Improved organisation of Cartographic transformation
This commit is contained in:
parent
346e44da48
commit
3356b5561a
|
|
@ -3,4 +3,5 @@ src/.DS_Store
|
|||
src/.cache
|
||||
src/build
|
||||
.idea
|
||||
src/cmake-build-debug
|
||||
src/cmake-build-debug
|
||||
compile_commands.json
|
||||
|
|
@ -46,7 +46,7 @@ add_executable(VtkBase MACOSX_BUNDLE main.cpp
|
|||
commands/TimerCallbackCommand.cpp
|
||||
helperClasses/SpawnPointCallback.h
|
||||
helperClasses/SpawnPointCallback.cpp
|
||||
helperClasses/NormalisedCartographicCamera.cpp
|
||||
helperClasses/CartographicTransformation.cpp
|
||||
)
|
||||
|
||||
execute_process(
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
build/compile_commands.json
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
#include "CartographicTransformation.h"
|
||||
#include <vtkMatrix4x4.h>
|
||||
#include <vtkTransform.h>
|
||||
#include <vtkTransformFilter.h>
|
||||
|
||||
vtkSmartPointer<vtkCamera> createNormalisedCamera() {
|
||||
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
|
||||
camera->ParallelProjectionOn(); // Enable parallel projection
|
||||
|
||||
camera->SetPosition(0, 0, 1000); // Place the camera above the center
|
||||
camera->SetFocalPoint(0, 0, 0); // Look at the center
|
||||
camera->SetViewUp(0, 1, 0); // Set the up vector to be along the Y-axis
|
||||
camera->SetParallelScale(1); // x,y in [-1, 1]
|
||||
|
||||
return camera;
|
||||
}
|
||||
|
||||
vtkSmartPointer<vtkMatrix4x4> getCartographicTransformMatrix() {
|
||||
const double XMin = -15.875;
|
||||
const double XMax = 12.875;
|
||||
const double YMin = 46.125;
|
||||
const double YMax = 62.625;
|
||||
|
||||
double eyeTransform[] = {
|
||||
2/(XMax-XMin), 0, 0, -(XMax+XMin)/(XMax-XMin),
|
||||
0, 2/(YMax-YMin), 0, -(YMax+YMin)/(YMax-YMin),
|
||||
0, 0, 1, 0,
|
||||
0, 0, 0, 1
|
||||
};
|
||||
|
||||
auto matrix = vtkSmartPointer<vtkMatrix4x4>::New();
|
||||
matrix->DeepCopy(eyeTransform);
|
||||
return matrix;
|
||||
}
|
||||
|
||||
// Assumes Normalised camera is used
|
||||
vtkSmartPointer<vtkTransformFilter> createCartographicTransformFilter() {
|
||||
vtkNew<vtkTransform> transform;
|
||||
|
||||
transform->SetMatrix(getCartographicTransformMatrix());
|
||||
|
||||
vtkSmartPointer<vtkTransformFilter> transformFilter = vtkSmartPointer<vtkTransformFilter>::New();
|
||||
transformFilter->SetTransform(transform);
|
||||
|
||||
return transformFilter;
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
#include <vtkCamera.h>
|
||||
#include <vtkTransformFilter.h>
|
||||
|
||||
#ifndef VTKBASE_NORMALISEDCARTOGRAPHICCAMERA_H
|
||||
#define VTKBASE_NORMALISEDCARTOGRAPHICCAMERA_H
|
||||
|
||||
#endif //VTKBASE_NORMALISEDCARTOGRAPHICCAMERA_H
|
||||
|
||||
/**
|
||||
* Constructs a orthographically projected camera that looks at the square x,y in [-1, 1] with z = 0 and w = 1.
|
||||
* The space [-1,1] x [-1,1] x {0} will be referred to as the normalised space.
|
||||
* @return pointer to camera
|
||||
*/
|
||||
vtkSmartPointer<vtkCamera> createNormalisedCamera();
|
||||
|
||||
/**
|
||||
* Constructs a 4x4 projection matrix that maps homogenious (longitude, latitude, 0, 1) points
|
||||
* to the normalised space.
|
||||
* TODO: This transformation has room for improvement see:
|
||||
* https://github.com/MakeNEnjoy/interactive-track-and-trace/issues/12
|
||||
* @return pointer to 4x4 matrix
|
||||
*/
|
||||
vtkSmartPointer<vtkMatrix4x4> getCartographicTransformMatrix();
|
||||
|
||||
/**
|
||||
* Convenience function that converts the 4x4 projection matrix into a vtkTransformFilter
|
||||
* @return pointer to transform filter
|
||||
*/
|
||||
vtkSmartPointer<vtkTransformFilter> createCartographicTransformFilter();
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
#include <vtkVertexGlyphFilter.h>
|
||||
#include <netcdf>
|
||||
#include <vtkArrowSource.h>
|
||||
#include "NormalisedCartographicCamera.h"
|
||||
#include "CartographicTransformation.h"
|
||||
|
||||
using namespace netCDF;
|
||||
using namespace std;
|
||||
|
|
@ -65,7 +65,7 @@ void EGlyphLayer::readCoordinates() {
|
|||
this->direction->SetNumberOfTuples(numLats*numLons);
|
||||
points->Allocate(numLats*numLons);
|
||||
|
||||
auto camera = createNormalisedCartographicCamera();
|
||||
auto camera = createNormalisedCamera();
|
||||
ren->SetActiveCamera(camera);
|
||||
|
||||
int i = 0;
|
||||
|
|
@ -73,7 +73,7 @@ void EGlyphLayer::readCoordinates() {
|
|||
for (double lon : lons) {
|
||||
cout << "lon: " << lon << " lat: " << lat << endl;
|
||||
direction->SetTuple3(i, 0.45, 0.90, 0); //FIXME: read this info from file
|
||||
points->InsertPoint(i++, lon, lat, 0); // FIXME: counts on fixed window geometry to map properly; refactor to make use of active window geometry.
|
||||
points->InsertPoint(i++, lon, lat, 0);
|
||||
// see also https://vtk.org/doc/nightly/html/classvtkPolyDataMapper2D.html
|
||||
}
|
||||
}
|
||||
|
|
@ -81,6 +81,9 @@ void EGlyphLayer::readCoordinates() {
|
|||
this->data->GetPointData()->AddArray(this->direction);
|
||||
this->data->GetPointData()->SetActiveVectors("direction");
|
||||
|
||||
vtkSmartPointer<vtkTransformFilter> transformFilter = createCartographicTransformFilter();
|
||||
transformFilter->SetInputData(data);
|
||||
|
||||
vtkNew<vtkGlyphSource2D> arrowSource;
|
||||
arrowSource->SetGlyphTypeToArrow();
|
||||
arrowSource->SetScale(0.2); //TODO: set this properly
|
||||
|
|
@ -88,7 +91,7 @@ void EGlyphLayer::readCoordinates() {
|
|||
|
||||
vtkNew<vtkGlyph2D> glyph2D;
|
||||
glyph2D->SetSourceConnection(arrowSource->GetOutputPort());
|
||||
glyph2D->SetInputData(this->data);
|
||||
glyph2D->SetInputConnection(transformFilter->GetOutputPort());
|
||||
glyph2D->OrientOn();
|
||||
glyph2D->ClampingOn();
|
||||
glyph2D->SetScaleModeToScaleByVector();
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
#include <vtkRenderWindow.h>
|
||||
#include <vtkCamera.h>
|
||||
|
||||
#include "NormalisedCartographicCamera.h"
|
||||
#include "CartographicTransformation.h"
|
||||
|
||||
|
||||
vtkSmartPointer<SpawnPointCallback> LGlyphLayer::createSpawnPointCallback() {
|
||||
|
|
@ -42,20 +42,25 @@ LGlyphLayer::LGlyphLayer() {
|
|||
this->data = vtkSmartPointer<vtkPolyData>::New();
|
||||
this->data->SetPoints(this->points);
|
||||
|
||||
auto camera = createNormalisedCamera();
|
||||
ren->SetActiveCamera(camera);
|
||||
|
||||
auto transform = createCartographicTransformFilter();
|
||||
|
||||
vtkSmartPointer<vtkTransformFilter> transformFilter = createCartographicTransformFilter();
|
||||
transformFilter->SetInputData(data);
|
||||
|
||||
vtkNew<vtkGlyphSource2D> circleSource;
|
||||
circleSource->SetGlyphTypeToCircle();
|
||||
circleSource->SetScale(1);
|
||||
circleSource->SetScale(0.05);
|
||||
circleSource->Update();
|
||||
|
||||
vtkNew<vtkGlyph2D> glyph2D;
|
||||
glyph2D->SetSourceConnection(circleSource->GetOutputPort());
|
||||
glyph2D->SetInputData(this->data);
|
||||
glyph2D->SetInputConnection(transformFilter->GetOutputPort());
|
||||
glyph2D->SetColorModeToColorByScalar();
|
||||
glyph2D->Update();
|
||||
|
||||
auto camera = createNormalisedCartographicCamera();
|
||||
ren->SetActiveCamera(camera);
|
||||
|
||||
vtkNew<vtkPolyDataMapper> mapper;
|
||||
mapper->SetInputConnection(glyph2D->GetOutputPort());
|
||||
mapper->Update();
|
||||
|
|
@ -68,13 +73,11 @@ LGlyphLayer::LGlyphLayer() {
|
|||
|
||||
// creates a few points so we can test the updateData function
|
||||
void LGlyphLayer::spoofPoints() {
|
||||
// this->points->InsertNextPoint(200, 200 , 0);
|
||||
this->points->InsertNextPoint(-4.125, 61.375 , 0);
|
||||
this->points->InsertNextPoint(4.896555178870355, 52.373557841669516, 0);
|
||||
// this->points->InsertNextPoint(48.2, 111.01, 0);
|
||||
// this->points->InsertNextPoint(331, 331, 0);
|
||||
// this->points->InsertNextPoint(0, 50, 0);
|
||||
// this->points->InsertNextPoint(200, 200 , 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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,43 +0,0 @@
|
|||
#include "NormalisedCartographicCamera.h"
|
||||
#include <vtkMatrix4x4.h>
|
||||
|
||||
vtkSmartPointer<vtkCamera> createNormalisedCartographicCamera() {
|
||||
const double XMin = -15.875;
|
||||
const double XMax = 12.875;
|
||||
const double YMin = 46.125;
|
||||
const double YMax = 62.625;
|
||||
|
||||
double farClipPlane = 100;
|
||||
double nearClipPlane = 1;
|
||||
double eyeTransform[] = {
|
||||
2/(XMax-XMin), 0, 0, -(XMax+XMin)/(XMax-XMin),
|
||||
0, 2/(YMax-YMin), 0, -(YMax+YMin)/(YMax-YMin),
|
||||
0, 0, 2/(nearClipPlane-farClipPlane), -(farClipPlane+nearClipPlane)/(farClipPlane-nearClipPlane),
|
||||
0, 0, 0, 1
|
||||
};
|
||||
|
||||
vtkSmartPointer<vtkCamera> camera = vtkSmartPointer<vtkCamera>::New();
|
||||
camera->ParallelProjectionOn(); // Enable parallel projection
|
||||
camera->UseExplicitProjectionTransformMatrixOn();
|
||||
|
||||
//// // Calculate the center and the size of the view
|
||||
double centerX = (XMax + XMin) / 2.0;
|
||||
double centerY = (YMax + YMin) / 2.0;
|
||||
double width = XMax - XMin;
|
||||
double height = YMax - YMin;
|
||||
//// // Set the camera position, focal point, and view up
|
||||
// camera->SetPosition(centerX, centerY, 1000); // Place the camera above the center
|
||||
// camera->SetFocalPoint(centerX, centerY, 0); // Look at the center
|
||||
// camera->SetViewUp(0, 1, 0); // Set the up vector to be along the Y-axis
|
||||
////
|
||||
//// // Set parallel scale
|
||||
// double parallelScale = std::max(width, height) / 2.0;
|
||||
// camera->SetParallelScale(parallelScale);
|
||||
|
||||
vtkNew<vtkMatrix4x4> projectionMatrix;
|
||||
projectionMatrix->DeepCopy(eyeTransform);
|
||||
camera->SetExplicitProjectionTransformMatrix(projectionMatrix);
|
||||
// camera->SetScreenBottomLeft(XMin, YMin, 0);
|
||||
// camera->SetScreenTopRight(XMax, YMax, 0);
|
||||
return camera;
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
#include <vtkCamera.h>
|
||||
|
||||
#ifndef VTKBASE_NORMALISEDCARTOGRAPHICCAMERA_H
|
||||
#define VTKBASE_NORMALISEDCARTOGRAPHICCAMERA_H
|
||||
|
||||
#endif //VTKBASE_NORMALISEDCARTOGRAPHICCAMERA_H
|
||||
|
||||
vtkSmartPointer<vtkCamera> createNormalisedCartographicCamera();
|
||||
|
|
@ -7,6 +7,8 @@
|
|||
#include <vtkCommand.h>
|
||||
#include <vtkRenderWindow.h>
|
||||
|
||||
#include "CartographicTransformation.h"
|
||||
|
||||
void convertDisplayToWorld(vtkRenderer* renderer, int x, int y, double *worldPos) {
|
||||
double displayPos[3] = {static_cast<double>(x), static_cast<double>(y), 0.0};
|
||||
renderer->SetDisplayPoint(displayPos);
|
||||
|
|
@ -36,6 +38,7 @@ void SpawnPointCallback::Execute(vtkObject *caller, unsigned long evId, void *ca
|
|||
ren->SetDisplayPoint(displayPos);
|
||||
ren->DisplayToWorld();
|
||||
ren->GetWorldPoint(worldPos);
|
||||
inverseCartographicProjection->MultiplyPoint(worldPos, worldPos);
|
||||
cout << "clicked on lon = " << worldPos[0] << " and lat = " << worldPos[1] << endl;
|
||||
|
||||
vtkIdType id = points->InsertNextPoint(worldPos[0], worldPos[1], 0);
|
||||
|
|
@ -52,7 +55,10 @@ void SpawnPointCallback::Execute(vtkObject *caller, unsigned long evId, void *ca
|
|||
}
|
||||
|
||||
|
||||
SpawnPointCallback::SpawnPointCallback() : data(nullptr), points(nullptr) {}
|
||||
SpawnPointCallback::SpawnPointCallback() : data(nullptr), points(nullptr), inverseCartographicProjection(nullptr) {
|
||||
inverseCartographicProjection = getCartographicTransformMatrix();
|
||||
inverseCartographicProjection->Invert();
|
||||
}
|
||||
|
||||
SpawnPointCallback *SpawnPointCallback::New() {
|
||||
return new SpawnPointCallback;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <vtkRenderWindowInteractor.h>
|
||||
#include <vtkPoints.h>
|
||||
#include <vtkPolyData.h>
|
||||
#include <vtkMatrix4x4.h>
|
||||
|
||||
class SpawnPointCallback : public vtkCallbackCommand {
|
||||
|
||||
|
|
@ -18,14 +19,12 @@ public:
|
|||
void setData(const vtkSmartPointer<vtkPolyData> &data);
|
||||
|
||||
void setRen(const vtkSmartPointer<vtkRenderer> &ren);
|
||||
|
||||
private:
|
||||
vtkSmartPointer<vtkPolyData> data;
|
||||
vtkSmartPointer<vtkPoints> points;
|
||||
vtkSmartPointer<vtkRenderer> ren;
|
||||
public:
|
||||
vtkSmartPointer<vtkMatrix4x4> inverseCartographicProjection;
|
||||
|
||||
private:
|
||||
void Execute(vtkObject *caller, unsigned long evId, void *callData) override;
|
||||
bool dragging = false;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue