Merge pull request #23 from MakeNEnjoy/djairo-vtk-camera

Djairo vtk camera
This commit is contained in:
Robin Sachsenweger Ballantyne 2024-05-06 17:00:08 +02:00 committed by GitHub
commit 31d5faec06
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 327 additions and 93 deletions

View File

@ -17,6 +17,8 @@ find_package(VTK COMPONENTS
FiltersProgrammable FiltersProgrammable
FiltersSources FiltersSources
ImagingSources ImagingSources
ImagingGeneral
ImagingCore
InteractionStyle InteractionStyle
IOImage IOImage
RenderingContextOpenGL2 RenderingContextOpenGL2
@ -35,20 +37,23 @@ endif()
find_package(netCDF REQUIRED) find_package(netCDF REQUIRED)
add_executable(VtkBase MACOSX_BUNDLE main.cpp add_executable(VtkBase MACOSX_BUNDLE main.cpp
layers/BackgroundImage.cpp CartographicTransformation.cpp
layers/BackgroundImage.h commands/CameraMoveCallback.cpp
layers/EGlyphLayer.cpp commands/CameraMoveCallback.h
layers/EGlyphLayer.h commands/SpawnPointCallback.cpp
layers/Layer.cpp commands/SpawnPointCallback.h
layers/Layer.h
layers/LGlyphLayer.cpp
layers/LGlyphLayer.h
Program.cpp
Program.h
commands/TimerCallbackCommand.h
commands/TimerCallbackCommand.cpp commands/TimerCallbackCommand.cpp
commands/SpawnPointCallback.h commands/TimerCallbackCommand.h
commands/SpawnPointCallback.cpp layers/BackgroundImage.cpp
layers/BackgroundImage.h
layers/EGlyphLayer.cpp
layers/EGlyphLayer.h
layers/Layer.cpp
layers/Layer.h
layers/LGlyphLayer.cpp
layers/LGlyphLayer.h
Program.cpp
Program.h
CartographicTransformation.cpp CartographicTransformation.cpp
advection/AdvectionKernel.h advection/AdvectionKernel.h
advection/EulerAdvectionKernel.cpp advection/EulerAdvectionKernel.cpp

View File

@ -19,7 +19,8 @@
#include "Program.h" #include "Program.h"
#include "commands/TimerCallbackCommand.h" #include "commands/TimerCallbackCommand.h"
#include "commands/SpawnPointCallback.h" #include "CartographicTransformation.h"
#include "commands/CameraMoveCallback.h"
void Program::setWinProperties() { void Program::setWinProperties() {
this->win->SetWindowName("Simulation"); this->win->SetWindowName("Simulation");
@ -42,17 +43,29 @@ void Program::setupTimer(int dt) {
this->interact->CreateRepeatingTimer(17); // 60 fps == 1000 / 60 == 16.7 ms per frame this->interact->CreateRepeatingTimer(17); // 60 fps == 1000 / 60 == 16.7 ms per frame
} }
void Program::setupCameraCallback() {
auto callback = vtkSmartPointer<CameraMoveCallback>::New(this->cam);
this->interact->AddObserver(vtkCommand::MouseWheelForwardEvent, callback);
this->interact->AddObserver(vtkCommand::MouseWheelBackwardEvent, callback);
this->interact->AddObserver(vtkCommand::KeyPressEvent, callback);
}
Program::Program(int timerDT) { Program::Program(int timerDT) {
this->win = vtkSmartPointer<vtkRenderWindow>::New(); this->win = vtkSmartPointer<vtkRenderWindow>::New();
this->interact = vtkSmartPointer<vtkRenderWindowInteractor>::New(); this->interact = vtkSmartPointer<vtkRenderWindowInteractor>::New();
this->cam = createNormalisedCamera();
this->win->SetNumberOfLayers(0); this->win->SetNumberOfLayers(0);
setWinProperties(); setWinProperties();
setupTimer(timerDT); setupTimer(timerDT);
setupCameraCallback();
} }
void Program::addLayer(Layer *layer) { void Program::addLayer(Layer *layer) {
layer->setCamera(this->cam);
this->layers.push_back(layer); this->layers.push_back(layer);
this->win->AddRenderer(layer->getLayer()); this->win->AddRenderer(layer->getLayer());
this->win->SetNumberOfLayers(this->win->GetNumberOfLayers() + 1); this->win->SetNumberOfLayers(this->win->GetNumberOfLayers() + 1);
@ -68,6 +81,7 @@ void Program::removeLayer(Layer *layer) {
} }
} }
void Program::updateData(int t) { void Program::updateData(int t) {
win->Render(); win->Render();
for (Layer *l: layers) { for (Layer *l: layers) {

View File

@ -6,7 +6,6 @@
#include <vtkRenderer.h> #include <vtkRenderer.h>
#include "layers/Layer.h" #include "layers/Layer.h"
#include "commands/SpawnPointCallback.h"
/** This class manages the upper levels of the vtk pipeline; it has attributes for the vtkrenderWindow and a vector of Layers to represent a variable number of vtkRenderers. /** This class manages the upper levels of the vtk pipeline; it has attributes for the vtkrenderWindow and a vector of Layers to represent a variable number of vtkRenderers.
* It can also set up a vtkTimer by connecting an instance of TimerCallbackCommand with its contained vtkRenderWindowInteractor. * It can also set up a vtkTimer by connecting an instance of TimerCallbackCommand with its contained vtkRenderWindowInteractor.
@ -25,6 +24,11 @@ private:
*/ */
vtkSmartPointer<vtkRenderWindowInteractor> interact; vtkSmartPointer<vtkRenderWindowInteractor> interact;
/** The camera used by all layers for this program.
*/
vtkSmartPointer<vtkCamera> cam;
/** This function sets some default properties on the vtkRenderWindow. Extracted to its' own function to keep the constructor from becoming cluttered. /** This function sets some default properties on the vtkRenderWindow. Extracted to its' own function to keep the constructor from becoming cluttered.
*/ */
void setWinProperties(); void setWinProperties();
@ -33,8 +37,14 @@ private:
*/ */
void setupTimer(int dt); void setupTimer(int dt);
/** This function adds all interactors of each layer to the interactor/window
*/
void setupInteractions(); void setupInteractions();
/** This function sets up the camera's associated movement callbacks..
*/
void setupCameraCallback();
public: public:
/** Constructor. /** Constructor.
*/ */

View File

@ -0,0 +1,104 @@
#include "CameraMoveCallback.h"
#include <vtkVertex.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkCommand.h>
#include <vtkRenderWindow.h>
using std::string;
void CameraMoveCallback::Execute(vtkObject *caller, unsigned long evId,
void *callData) {
// Note the use of reinterpret_cast to cast the caller to the expected type.
auto intr = reinterpret_cast<vtkRenderWindowInteractor *>(caller);
switch (evId) {
case vtkCommand::KeyPressEvent:
if (not strcmp("minus", intr->GetKeySym())) {
zoom(false);
} else if (not strcmp("equal", intr->GetKeySym())) {
zoom(true);
} else {
pan(intr->GetKeySym());
}
break;
case vtkCommand::MouseWheelForwardEvent:
zoom(true);
break;
case vtkCommand::MouseWheelBackwardEvent:
zoom(false);
break;
default:
break;
}
// also calls the render function when the camera's position has not actually changed. This is a negligble inefficiency.
intr->GetRenderWindow()->Render();
}
void CameraMoveCallback::clampCamera(double pos[3]) {
double scale = this->cam->GetParallelScale();
// only check the x,y coords of the camera; we don't care about z
for (int i=0; i < 2; i++) {
//boundary cond: scale+|pos| < 1.
if (abs(pos[i])+scale > 1.01) {
if (pos[i] >= 0) {
pos[i] = 1 - scale;
} else {
pos[i] = scale - 1;
}
}
}
this->cam->SetPosition(pos);
this->cam->SetFocalPoint(pos[0], pos[1], 0);
}
void CameraMoveCallback::zoom(const bool in) {
double scale = this->cam->GetParallelScale();
if (in) {
if (scale >= 0.2)
scale -= 0.1;
} else {
if (scale <= 0.9)
scale += 0.1;
}
this->cam->SetParallelScale(scale);
clampCamera(this->cam->GetPosition());
}
// we use the interactor's getKeySym instead of getKeyCode because getKeyCode is platform-dependent.
void CameraMoveCallback::pan(const string dir) {
double pos[3];
this->cam->GetPosition(pos);
if (dir == "Left" or dir == "h") {
pos[0] -= 0.1;
} else if (dir == "Up" or dir == "k" ) {
pos[1] += 0.1;
} else if (dir == "Right" or dir == "l" ) {
pos[0] += 0.1;
} else if (dir == "Down" or dir == "j" ) {
pos[1] -= 0.1;
}
clampCamera(pos);
}
CameraMoveCallback::CameraMoveCallback() : cam(nullptr) {}
CameraMoveCallback *CameraMoveCallback::New(vtkCamera *cam) {
auto me = new CameraMoveCallback;
me->setCam(cam);
return me;
}
void CameraMoveCallback::setCam(const vtkSmartPointer<vtkCamera> &cam) {
this->cam = cam;
}

View File

@ -0,0 +1,56 @@
#ifndef VTKBASE_CAMERAMOVECALLBACK_H
#define VTKBASE_CAMERAMOVECALLBACK_H
#include <vtkCallbackCommand.h>
#include <vtkCamera.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkMatrix4x4.h>
class CameraMoveCallback : public vtkCallbackCommand {
public:
/** Create new instance using the vtk New template.
*/
static CameraMoveCallback *New(vtkCamera *cam);
/** Constructor.
*/
CameraMoveCallback();
/** Sets the camera to operate on.
*/
void setCam(const vtkSmartPointer<vtkCamera> &cam);
private:
/** The camera to operate on.
*/
vtkSmartPointer<vtkCamera> cam;
/** Event callback. Should be subscribed to keyPressEvent and MouseWheelForward/MouseWheelBackward events.
*/
void Execute(vtkObject *caller, unsigned long evId, void *callData) override;
/** Zooms the camera in or out.
* @param in : whether to zoom in or out.
*/
void zoom(const bool in);
/** Pans the camera in a direction, determined by the parameter.
* 'h' and 'left' : pan left
* 'j' and 'up' : pan up
* 'k' and 'down' : pan down
* 'l' and 'right' : pan right
* @param dir : string of the pressed keycode.
*/
void pan(const std::string dir);
/** Edits the camera such that it only ever renders within the [-1,1] normalised coordinate field.
* Does so by making sure that the position of the camera (on the x,y axes), combined with the parallel scale, is never > 1.
* @param pos : pointer to new desired camera position. This will be changed if it would cause points outside [-1,1] to be displayed.
*/
void clampCamera(double *pos);
};
#endif

View File

@ -17,40 +17,40 @@ void convertDisplayToWorld(vtkRenderer *renderer, int x, int y, double *worldPos
} }
void SpawnPointCallback::Execute(vtkObject *caller, unsigned long evId, void *callData) { void SpawnPointCallback::Execute(vtkObject *caller, unsigned long evId, void *callData) {
// Note the use of reinterpret_cast to cast the caller to the expected type. // Note the use of reinterpret_cast to cast the caller to the expected type.
auto interactor = reinterpret_cast<vtkRenderWindowInteractor *>(caller); auto interactor = reinterpret_cast<vtkRenderWindowInteractor *>(caller);
if (evId == vtkCommand::LeftButtonPressEvent) { if (evId == vtkCommand::LeftButtonPressEvent) {
dragging = true; dragging = true;
} }
if (evId == vtkCommand::LeftButtonReleaseEvent) { if (evId == vtkCommand::LeftButtonReleaseEvent) {
dragging = false; dragging = false;
} }
if (!dragging) { if (!dragging) {
return; return;
} }
int x, y; int x, y;
interactor->GetEventPosition(x, y); interactor->GetEventPosition(x, y);
double worldPos[4] = {2, 0, 0, 0}; double worldPos[4] = {2, 0 ,0, 0};
double displayPos[3] = {static_cast<double>(x), static_cast<double>(y), 0.0}; double displayPos[3] = {static_cast<double>(x), static_cast<double>(y), 0.0};
ren->SetDisplayPoint(displayPos); ren->SetDisplayPoint(displayPos);
ren->DisplayToWorld(); ren->DisplayToWorld();
ren->GetWorldPoint(worldPos); ren->GetWorldPoint(worldPos);
inverseCartographicProjection->MultiplyPoint(worldPos, worldPos); inverseCartographicProjection->MultiplyPoint(worldPos, worldPos);
cout << "clicked on lon = " << worldPos[0] << " and lat = " << worldPos[1] << endl; // cout << "clicked on lon = " << worldPos[0] << " and lat = " << worldPos[1] << endl;
vtkIdType id = points->InsertNextPoint(worldPos[0], worldPos[1], 0); vtkIdType id = points->InsertNextPoint(worldPos[0], worldPos[1], 0);
data->SetPoints(points); data->SetPoints(points);
vtkSmartPointer<vtkVertex> vertex = vtkSmartPointer<vtkVertex>::New(); vtkSmartPointer<vtkVertex> vertex = vtkSmartPointer<vtkVertex>::New();
vertex->GetPointIds()->SetId(0, id); vertex->GetPointIds()->SetId(0, id);
vtkSmartPointer<vtkCellArray> vertices = vtkSmartPointer<vtkCellArray>::New(); vtkSmartPointer<vtkCellArray> vertices = vtkSmartPointer<vtkCellArray>::New();
vertices->InsertNextCell(vertex); vertices->InsertNextCell(vertex);
data->SetVerts(vertices); data->SetVerts(vertices);
ren->GetRenderWindow()->Render(); ren->GetRenderWindow()->Render();
} }

View File

@ -2,12 +2,13 @@
#include "../Program.h" #include "../Program.h"
// TODO: add getter/setters to attributes for customizability.
TimerCallbackCommand::TimerCallbackCommand() : dt(3600), maxTime(3600*24*365), time(0) {} TimerCallbackCommand::TimerCallbackCommand() : dt(3600), maxTime(3600*24*365), time(0) {}
TimerCallbackCommand* TimerCallbackCommand::New(Program *program) { TimerCallbackCommand* TimerCallbackCommand::New(Program *program) {
TimerCallbackCommand *cb = new TimerCallbackCommand(); TimerCallbackCommand *cb = new TimerCallbackCommand();
cb->setProgram(program); cb->setProgram(program);
cb->setPaused(false); cb->setPaused(true);
return cb; return cb;
} }
@ -17,19 +18,17 @@ void TimerCallbackCommand::Execute(vtkObject* caller, unsigned long eventId, voi
if (eventId == vtkCommand::KeyPressEvent and not strcmp("space", intr->GetKeySym())) { if (eventId == vtkCommand::KeyPressEvent and not strcmp("space", intr->GetKeySym())) {
this->paused = ! this->paused; this->paused = ! this->paused;
} else if (eventId == vtkCommand::TimerEvent and not this->paused) { } else if (eventId == vtkCommand::TimerEvent and not this->paused) {
this->time += this->dt; this->time += this->dt;
if (this->time >= this->maxTime) { if (this->time >= this->maxTime) {
return; return;
// TODO: how do we deal with reaching the end of the simulated dataset? Do we just stop simulating, loop back around? What about the location of the particles in this case? Just some ideas to consider, but we should iron this out pretty soon. // TODO: how do we deal with reaching the end of the simulated dataset? Do we just stop simulating, loop back around? What about the location of the particles in this case? Just some ideas to consider, but we should iron this out pretty soon.
}
this->program->updateData(this->time);
} }
this->program->updateData(this->time);
}
} }
void TimerCallbackCommand::setProgram(Program *program) { void TimerCallbackCommand::setProgram(Program *program) {
this->program = program; this->program = program;
} }

View File

@ -1,8 +1,17 @@
#include "BackgroundImage.h" #include "BackgroundImage.h"
#include <vtkImageDataGeometryFilter.h>
#include <vtkImageChangeInformation.h>
#include <vtkImageSliceMapper.h>
#include <vtkCamera.h> #include <vtkCamera.h>
#include <vtkImageActor.h> #include <vtkImageActor.h>
#include <vtkImageData.h> #include <vtkImageData.h>
#include <vtkImageMapper3D.h>
#include <vtkImageReader2.h> #include <vtkImageReader2.h>
#include <vtkImageShiftScale.h>
#include <vtkMatrix4x4.h>
#include <vtkPolyDataMapper.h>
#include <vtkTransform.h>
#include <vtkTransformFilter.h>
using std::string; using std::string;
@ -14,41 +23,61 @@ BackgroundImage::BackgroundImage(string imagePath) : imagePath(imagePath) {
} }
void BackgroundImage::updateImage() { vtkSmartPointer<vtkMatrix4x4> BackgroundImage::getMatrix(const double x0, const double y0, const int xMax, const int yMax) {
vtkSmartPointer<vtkImageData> imageData; double eyeTransform[] = {
2/(xMax-x0), 0, 0, -(xMax+x0)/(xMax-x0),
0, 2/(yMax-y0), 0, -(yMax+y0)/(yMax-y0),
0, 0, 1, 0,
0, 0, 0, 1
};
auto matrix = vtkSmartPointer<vtkMatrix4x4>::New();
matrix->DeepCopy(eyeTransform);
return matrix;
}
void BackgroundImage::updateImage() {
// read image data
vtkSmartPointer<vtkImageReader2> imageReader; vtkSmartPointer<vtkImageReader2> imageReader;
imageReader.TakeReference(this->readerFactory->CreateImageReader2(this->imagePath.c_str())); imageReader.TakeReference(this->readerFactory->CreateImageReader2(this->imagePath.c_str()));
imageReader->SetFileName(this->imagePath.c_str()); imageReader->SetFileName(this->imagePath.c_str());
imageReader->Update(); imageReader->Update();
imageData = imageReader->GetOutput();
vtkNew<vtkImageActor> imageActor; // translate image such that the middle is at (0,0)
imageActor->SetInputData(imageData); vtkNew<vtkImageChangeInformation> imageCenterer;
imageCenterer->SetInputConnection(imageReader->GetOutputPort());
imageCenterer->CenterImageOn();
imageCenterer->Update();
this->ren->AddActor(imageActor); // get some info from the data we'll need in a second
vtkSmartPointer<vtkImageData> imageData = imageCenterer->GetOutput();
double origin[3];
// camera stuff
// essentially sets the camera to the middle of the background, and points it at the background
// TODO: extract this to its own function, separate from the background class.
double origin[3], spacing[3];
int extent[6]; int extent[6];
imageData->GetOrigin(origin); imageData->GetOrigin(origin);
imageData->GetSpacing(spacing);
imageData->GetExtent(extent); imageData->GetExtent(extent);
vtkCamera *camera = this->ren->GetActiveCamera(); // map the imageData to a vtkPolydata so we can use a vtkTransform
camera->ParallelProjectionOn(); vtkNew<vtkImageDataGeometryFilter> imageDataGeometryFilter;
imageDataGeometryFilter->SetInputData(imageData);
imageDataGeometryFilter->Update();
double xc = origin[0] + 0.5 * (extent[0] + extent[1]) * spacing[0]; // setup the vtkTransform - this is where use the data from imageData we got earlier
double yc = origin[1] + 0.5 * (extent[2] + extent[3]) * spacing[1]; vtkNew<vtkTransform> transform;
double yd = (extent[3] - extent[2] + 1) * spacing[1]; transform->SetMatrix(getMatrix(origin[0], origin[1], extent[1]+origin[0], extent[3]+origin[1]));
double d = camera->GetDistance(); vtkSmartPointer<vtkTransformFilter> transformFilter = vtkSmartPointer<vtkTransformFilter>::New();
camera->SetParallelScale(0.5 * yd); transformFilter->SetTransform(transform);
camera->SetFocalPoint(xc, yc, 0.0); transformFilter->SetInputConnection(imageDataGeometryFilter->GetOutputPort());
camera->SetPosition(xc, yc, d); transformFilter->Update();
// Create a mapper and actor
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputConnection(transformFilter->GetOutputPort());
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
this->ren->AddActor(actor);
} }
@ -60,3 +89,4 @@ void BackgroundImage::setImagePath(string imagePath) {
this->imagePath = imagePath; this->imagePath = imagePath;
updateImage(); updateImage();
} }

View File

@ -16,6 +16,15 @@ private:
*/ */
void updateImage(); void updateImage();
/** This function returns a 4x4matrix which maps the given square of [x0,w] x [y0,h] to the range [-1,1].
* @param x0 : x coordinate of leftmost edge of image
* @param y0 : y coordinate of bottommost edge of image
* @param xMax : x coordinate of rightmost edge of image
* @param yMax : y coordinate of topmost edge of image
* @return a 4x4 matrix which transforms the image from its original geometry to the range [-1,1]
*/
vtkSmartPointer<vtkMatrix4x4> getMatrix(const double x0, const double y0, const int xMax, const int yMax);
public: public:
/** Constructor. /** Constructor.

View File

@ -41,9 +41,6 @@ void EGlyphLayer::readCoordinates() {
this->direction->SetNumberOfTuples(numLats * numLons); this->direction->SetNumberOfTuples(numLats * numLons);
points->Allocate(numLats * numLons); points->Allocate(numLats * numLons);
auto camera = createNormalisedCamera();
ren->SetActiveCamera(camera);
int i = 0; int i = 0;
int latIndex = 0; int latIndex = 0;
for (double lat: uvGrid->lats) { for (double lat: uvGrid->lats) {
@ -77,11 +74,7 @@ void EGlyphLayer::readCoordinates() {
glyph2D->SetVectorModeToUseVector(); glyph2D->SetVectorModeToUseVector();
glyph2D->Update(); glyph2D->Update();
// vtkNew<vtkCoordinate> coordinate;
// coordinate->SetCoordinateSystemToWorld();
vtkNew<vtkPolyDataMapper>(mapper); vtkNew<vtkPolyDataMapper>(mapper);
// mapper->SetTransformCoordinate(coordinate);
mapper->SetInputConnection(glyph2D->GetOutputPort()); mapper->SetInputConnection(glyph2D->GetOutputPort());
mapper->Update(); mapper->Update();

View File

@ -5,6 +5,7 @@
#include <vtkGlyphSource2D.h> #include <vtkGlyphSource2D.h>
#include <vtkNamedColors.h> #include <vtkNamedColors.h>
#include <vtkPolyDataMapper2D.h> #include <vtkPolyDataMapper2D.h>
#include <vtkProperty.h>
#include <vtkProperty2D.h> #include <vtkProperty2D.h>
#include <vtkVertexGlyphFilter.h> #include <vtkVertexGlyphFilter.h>
#include <vtkInteractorStyle.h> #include <vtkInteractorStyle.h>
@ -42,9 +43,6 @@ LGlyphLayer::LGlyphLayer(std::shared_ptr<UVGrid> uvGrid, std::unique_ptr<Advecti
advector = std::move(advectionKernel); advector = std::move(advectionKernel);
this->uvGrid = uvGrid; this->uvGrid = uvGrid;
auto camera = createNormalisedCamera();
ren->SetActiveCamera(camera);
vtkSmartPointer<vtkTransformFilter> transformFilter = createCartographicTransformFilter(uvGrid); vtkSmartPointer<vtkTransformFilter> transformFilter = createCartographicTransformFilter(uvGrid);
transformFilter->SetInputData(data); transformFilter->SetInputData(data);
@ -62,7 +60,7 @@ LGlyphLayer::LGlyphLayer(std::shared_ptr<UVGrid> uvGrid, std::unique_ptr<Advecti
vtkNew<vtkPolyDataMapper> mapper; vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputConnection(glyph2D->GetOutputPort()); mapper->SetInputConnection(glyph2D->GetOutputPort());
mapper->Update(); mapper->Update();
vtkNew<vtkActor> actor; vtkNew<vtkActor> actor;
actor->SetMapper(mapper); actor->SetMapper(mapper);
@ -71,11 +69,17 @@ LGlyphLayer::LGlyphLayer(std::shared_ptr<UVGrid> uvGrid, std::unique_ptr<Advecti
// creates a few points so we can test the updateData function // creates a few points so we can test the updateData function
void LGlyphLayer::spoofPoints() { void LGlyphLayer::spoofPoints() {
this->points->InsertNextPoint(-4.125, 61.375, 0); this->points->InsertNextPoint(-4.125, 61.375 , 0);
this->points->InsertNextPoint(6.532949683882039, 53.24308582564463, 0); // Coordinates of Zernike // 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(5.315307819255385, 60.40001057122271, 0); // Coordinates of Bergen
this->points->InsertNextPoint(6.646210231365825, 46.52346296009023, 0); // Coordinates of Lausanne // 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->InsertNextPoint(-6.553894313570932, 62.39522131195857, 0); // Coordinates of the top of the Faroe islands
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->points->Modified(); this->points->Modified();
} }

View File

@ -15,3 +15,8 @@ void Layer::updateData(int t) {
void Layer::addObservers(vtkSmartPointer<vtkRenderWindowInteractor> interactor) { void Layer::addObservers(vtkSmartPointer<vtkRenderWindowInteractor> interactor) {
// By default, do nothing // By default, do nothing
} }
void Layer::setCamera(vtkCamera *camera) {
this->getLayer()->SetActiveCamera(camera);
}

View File

@ -27,6 +27,11 @@ public:
* @param interactor : pointer to the interactor that observers can be added to. * @param interactor : pointer to the interactor that observers can be added to.
*/ */
virtual void addObservers(vtkSmartPointer<vtkRenderWindowInteractor> interactor); virtual void addObservers(vtkSmartPointer<vtkRenderWindowInteractor> interactor);
/** Sets the active camera for the vtkRenderer associated with this layer.
* Used to share one camera between multiple layers.
*/
virtual void setCamera(vtkCamera *camera);
}; };
#endif #endif