#include <QMessageBox>
#include <QPainter>
#include <QScreen>
#include <QDesktopWidget>

#include <cfloat>
#include <math.h>

#include "QFitsWidget3D.h"
#include "QFitsMainWindow.h"
#include "QFitsMainView.h"
#include "QFitsSingleBuffer.h"
#include "QFitsWidget2D.h"
#include "QFitsView2D.h"
#include "QFitsCubeSpectrum.h"
#include "QFitsGlobal.h"
#include "QFitsViewingTools.h"
#include "fits.h"
#include "qtdpuser.h"
#include "lut.h"

#define vtkRenderingCore_AUTOINIT 1(vtkInteractionStyle)
#define vtkRenderingCore_AUTOINIT 3(vtkRenderingCore,vtkRenderingOpenGL,vtkRenderingVolumeOpenGL)
#define vtkRenderingCore_AUTOINIT 2(vtkRenderingFreeType,vtkRenderingFreeTypeOpenGL)
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingOpenGL);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL);
VTK_MODULE_INIT(vtkRenderingFreeType);
VTK_MODULE_INIT(vtkRenderingFreeTypeOpenGL);

#include "vtkImageImport.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkPiecewiseFunction.h"
#include "vtkVolumeProperty.h"
#include "vtkVolumeRayCastCompositeFunction.h"
#include "vtkVolumeRayCastMapper.h"
#include "vtkColorTransferFunction.h"
#include "vtkCamera.h"
#include "vtkCubeAxesActor2D.h"
#include "vtkPointData.h"

//------------------------------------------------------------------------------
//         QFitsWidget3D
//------------------------------------------------------------------------------
QFitsWidget3D::QFitsWidget3D(QFitsBaseBuffer *bb) : QFitsBaseWidget(bb) {
    cubeViewer = new QFitsView3D(this);

connect(fitsMainWindow->mytoolbar, SIGNAL(updateZRange3D(double, double)),
        cubeViewer, SLOT(updateZRange3D(double, double)));
connect(fitsMainWindow->viewingtools->total, SIGNAL(setSlowAndNice()),
        cubeViewer, SLOT(paintSlowAndNice()));
connect(fitsMainWindow->viewingtools->total, SIGNAL(setQuickAndDirty()),
        cubeViewer, SLOT(paintQuickAndDirty()));
}

QFitsWidget3D::~QFitsWidget3D() {
    if (cubeViewer != NULL) {
        delete cubeViewer;
        cubeViewer = NULL;
    }
}

void QFitsWidget3D::setZoom(double zoomValue) {
    getMyBuffer()->setZoomFactor_3Dwire(zoomValue);
    cubeViewer->applyZoom();
}

void QFitsWidget3D::updateScaling() {
    cubeViewer->updateScaling();
}

void QFitsWidget3D::reset() {
    cubeViewer->ResetCamera();
}

void QFitsWidget3D::newData3D() {
    cubeViewer->newData();
}

void QFitsWidget3D::setupColours()
{
    cubeViewer->updateColourtable();
}

void QFitsWidget3D::setImageCenter(double x, double y) {
    cubeViewer->setImageCenter(x, y);
}

void QFitsWidget3D::resizeEvent(QResizeEvent *r) {
    cubeViewer->setGeometry(0, 0, r->size().width(), r->size().height());
    QFitsBaseWidget::resizeEvent(r); // ???
}

// handled now by QFitsBaseWidget!
//void QFitsWidget3D::calculateScaling(Fits *fits) {
//    return myParent->getState()->calculateScaling(fits);
//}
//------------------------------------------------------------------------------
//         QFitsView3D
//------------------------------------------------------------------------------
QFitsView3D::QFitsView3D(QFitsWidget3D *parent) :
                                      QVTKWidget(parent)
{
    myParent = parent;
    setFocusPolicy(Qt::StrongFocus);
    initialized = false;
    scalingDirty = true;
    colourtableDirty = true;

    importer = vtkImageImport::New();
    importer->SetDataScalarTypeToUnsignedChar();
    importer->SetNumberOfScalarComponents(1);

    colorTransferFunction = vtkColorTransferFunction::New();
    opacityTransferFunction = vtkPiecewiseFunction::New();
    opacityTransferFunction->AddPoint(20, 0.0);
    opacityTransferFunction->AddPoint(255, 0.5);
    //opacityTransferFunction->AddPoint(20, 0.1);
    //opacityTransferFunction->AddPoint(255, 0.9);

    volProperty = vtkVolumeProperty::New();
    volProperty->SetColor(colorTransferFunction);
    volProperty->SetScalarOpacity(opacityTransferFunction);
    volProperty->ShadeOn();
    volProperty->SetInterpolationTypeToLinear();

    compositeFunction = vtkVolumeRayCastCompositeFunction::New();

    volMapper = vtkVolumeRayCastMapper::New();
    volMapper->SetVolumeRayCastFunction(compositeFunction);
    volMapper->SetInputConnection(importer->GetOutputPort());

    vol = vtkVolume::New();
    vol->SetMapper(volMapper);
    vol->SetProperty(volProperty);

    renderer = vtkRenderer::New();
    renderer->SetBackground(0.0, 0.0, 0.0); // black Background
    //renderer->SetBackground(1.0, 1.0, 1.0); // white Background
    renderer->AddViewProp(vol);
    GetRenderWindow()->AddRenderer(renderer);

    camera = renderer->GetActiveCamera();
    camera->ParallelProjectionOn();

    // generate axes
    axes = vtkCubeAxesActor2D::New();
    axes->SetInputConnection(importer->GetOutputPort());
    axes->SetLabelFormat("%6.4g");
    axes->SetFontFactor(0.8);
    axes->UseRangesOn();    // we define our ranges ourselves
    axes->SetCamera(camera);
    axes->SetFlyModeToClosestTriad();
//    renderer->AddViewProp(axes); // Alex: For some reason hides the volume data!!! (since VTK 6.1)

    iren = GetInteractor();

    connect(this, SIGNAL(updateMagnifier(QPixmap&)),
            fitsMainWindow->viewingtools->magnifier, SLOT(setDirectPixmap(QPixmap&)));
}


QFitsView3D::~QFitsView3D()
{
}

void QFitsView3D::updateScaling() {
    scalingDirty = true;
    if (this->isVisible()) {
        // wenn mal average angezeigt wird -->uncomment
        //main_view->plotwidget->plotter->setYRange(myParent->getMyBuffer()->min, myParent->getMyBuffer()->max);

       newData();
    }
}

void QFitsView3D::paintQuickAndDirty() {
    GetRenderWindow()->SetDesiredUpdateRate(30);
}

void QFitsView3D::paintSlowAndNice() {
    GetRenderWindow()->SetDesiredUpdateRate(0.0001);
    update();
}

void QFitsView3D::mousePressEvent(QMouseEvent* event) {
    switch(event->button())
    {
        case Qt::RightButton: {
            QMouseEvent newevent(QEvent::MouseButtonPress, event->localPos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
            QVTKWidget::mousePressEvent(&newevent);
    }
            break;
        case Qt::MidButton:
            ResetCamera();
            break;
        case Qt::LeftButton:
            fitsMainWindow->main_view->setCurrentBufferFromWidget(myParent->getMyBuffer());
            paintQuickAndDirty();
            break;
        default:
            break;
    }
}

void QFitsView3D::mouseMoveEvent(QMouseEvent* event) {
    if (event->buttons() == Qt::RightButton) {
        // moved + right button
            QMouseEvent newevent(QEvent::MouseMove, event->localPos(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier);
            QVTKWidget::mouseMoveEvent(&newevent);
    } else if (event->buttons() == Qt::LeftButton) {
        // moved + left button: change colormap
            myParent->getMyBuffer()->setBrightnessContrast((int)((float)(event->x()) / (float)width() * 1000.),
                                                                      (int)((float)(event->y()) / (float)height() * 1000.));
    } else {
        QPoint epos = mapToGlobal(event->pos());
        QPixmap p = QApplication::screens().at(0)->grabWindow(QApplication::desktop()->winId(), epos.x() - 15, epos.y() - 15, 30, 30);
        emit updateMagnifier(p);
    }
}

void QFitsView3D::mouseReleaseEvent(QMouseEvent* event) {
    switch(event->button())
    {
        case Qt::LeftButton:
            paintSlowAndNice();
            break;
        default:
            break;
    }
}

void QFitsView3D::calcZoomedRanges(int *x1, int *x2, int *y1, int *y2, int *z1, int *z2) {
    QFitsSingleBuffer *sb = myParent->getMyBuffer();
    if (sb->getFirstView3D()) {
        sb->setFirstView3D(false);

        if ((sb->getWidthVisible() == -1) && (sb->getHeightVisible() == -1)) {
            sb->setWidthVisible(sb->Naxis(1));
            sb->setHeightVisible(sb->Naxis(2));
        }

        // this buffer has been viewed the first time in 3D or has been loaded directly from command line
        // if the total spatial area is bigger than 10'000 pixels scale it down
        double area = sb->getWidthVisible() * sb->getHeightVisible();
        if (area > 10000.) {
            // set area to max. 10000 pixels
            sb->setWidthVisible(sb->getWidthVisible() * 100. / sqrt(area));
            sb->setHeightVisible(sb->getHeightVisible() * 100. / sqrt(area));
        }

        calcZoomedVisibleArea();
    }

    double  xCen = sb->getXcenter(),
            yCen = sb->getYcenter();

//    sb->transCoordImage2Widget(&xCen, &yCen, sb->getZoomFactor_3Dwire());

    *x1 = xCen - sb->getWidthVisible() / 2.;
    if (*x1 < 1) {
        *x1 = 1;
    }
    *x2 = *x1 + sb->getWidthVisible() - 1;
    if (*x2 > sb->Naxis(1)) {
        *x2 = sb->Naxis(1);
        *x1 = *x2 - sb->getWidthVisible() + 1;
        if (*x1 < 1) {
            *x1 = 1;
        }
    }

    *y1 = yCen - sb->getHeightVisible() / 2;
    if (*y1 < 1) {
        *y1 = 1;
    }
    *y2 = *y1 + sb->getHeightVisible() - 1;
    if (*y2 > sb->Naxis(2)) {
        *y2 = sb->Naxis(2);
        *y1 = *y2 - sb->getHeightVisible() + 1;
        if (*y1 < 1) {
            *y1 = 1;
        }
    }

    *z1 = (int)(sb->getCubeCenter(QFV::Wavelength) - sb->getLineWidth(QFV::Wavelength) + 0.5);
    *z2 = (int)(sb->getCubeCenter(QFV::Wavelength) + sb->getLineWidth(QFV::Wavelength) + 0.5);

    if (*z1 < 1) {
        *z1 = 1;
    }
    if (*z2 > sb->Naxis(3)) {
        *z2 = sb->Naxis(3);
    }

//    sb->setXcenter(*x1+(int)((*x2-*x1)/2.+.5));
//    sb->setYcenter(*y1+(int)((*y2-*y1)/2.+.5));
    sb->setWidthVisible(*x2-*x1+1);
    sb->setHeightVisible(*y2-*y1+1);

    fitsMainWindow->updateTotalVisibleRect();

    // wenn man in View3D-modus im spectrum-fenster "C" drückt ohne die Maus zu
    // bewegen, wird ein subspectrum von breite 3 ausgewählt, dies wird erst
    // angezeigt, wenn die maus bewegt wird... update() oder repaint() wird
    // nicht ausgeführt
    fitsMainWindow->spectrum->update();
    fitsMainWindow->mytoolbar->setCube3D_zmin(QString::number(*z1, 'g', 4));
    fitsMainWindow->mytoolbar->setCube3D_zmax(QString::number(*z2, 'g', 4));
}

void QFitsView3D::newData() {
    myParent->getMyBuffer()->setDirty(true);

    update();
}

void QFitsView3D::newData2() {
    myParent->getMyBuffer()->setDirty(true);
    scalingDirty = true;

    update();
}

void QFitsView3D::updateZRange3D(double min, double max) {
    zmin = min;
    zmax = max;
}

void QFitsView3D::updateData() {
    QFitsSingleBuffer *sb = myParent->getMyBuffer();
    if (isVisible() && (sb != NULL) && (sb->getDpData()->type == typeFits)) {
        QReadLocker locker(&buffersLock);

        Fits *f = sb->getDpData()->fvalue;
        if (f != NULL) {
            // undo any possibly applied rotation and flipping
            if (sb->getFlipX()) {
                emit flipX();
            }
            if (sb->getFlipY()) {
                emit flipY();
            }
            while (sb->getRotation() != 0) {
                emit decRot();
            }

            // calculate dimensions of desired subcube
            int x1, x2, y1, y2, z1, z2;
            calcZoomedRanges(&x1, &x2, &y1, &y2, &z1, &z2);

            // update ranges of axes
            double ranges[6];
            ranges[0] = x1;
            ranges[1] = x2;
            ranges[2] = y1;
            ranges[3] = y2;
            // flip z-axis for correct display (longest wave length is furthest)
            ranges[4] = zmax;
            ranges[5] = zmin;

            // take into account WCS if available
            double crpix, crval, cdelt;

            if (f->GetFloatKey("CRPIX1", &crpix)) {
                if (f->GetFloatKey("CRVAL1", &crval)) {
                    if (f->GetFloatKey("CDELT1", &cdelt)) {
                        ranges[0] = crval + cdelt*(ranges[0] - crpix);
                        ranges[1] = crval + cdelt*(ranges[1] - crpix);
                    }
                }
            }

            if (f->GetFloatKey("CRPIX2", &crpix)) {
                if (f->GetFloatKey("CRVAL2", &crval)) {
                    if (f->GetFloatKey("CDELT2", &cdelt)) {
                        ranges[2] = crval + cdelt*(ranges[2] - crpix);
                        ranges[3] = crval + cdelt*(ranges[3] - crpix);
                    }
                }
            }

            // ranges[4] and ranges[5] don't have to be converted here, this is
            // already done in Toolbar.cpp

            dp_debug("RANGES: %d %d   %d %d   %d %d", ranges[0], ranges[1], ranges[2], ranges[3], ranges[4], ranges[5]);
            axes->SetRanges(ranges);

            if (scalingDirty) {
                // extract desired subcube
                QReadLocker locker(&buffersLock);
                f->extractRange(subcube, x1, x2, y1, y2, z1, z2);

                // converts Fits from double to unsigned char (if it is double)
                myParent->calculateScaling(&subcube);

                fitsMainWindow->mytoolbar->updateImageMinMax(sb);

                scalingDirty = false;
            } else {
                // extract desired subcube
                Fits tmp;
//                QReadLocker locker(&buffersLock);
                f->extractRange(tmp, x1, x2, y1, y2, z1, z2);

                // convert Fits eventually from double to unsigned char (if it is double)
                tmp.normub(subcube, sb->getSpecPhysMinY(), sb->getSpecPhysMaxY());
            }

            newColourtable();

            // flip data in z-axis for correct display (longest wave length is furthest)
            subcube.flip(3);

            if (initialized) {
                // refocus camera to the center of the subcube
                camera->SetFocalPoint((double)subcube.Naxis(1)/2, (double)subcube.Naxis(2)/2, (double)subcube.Naxis(3)/2);
            }

            sb->setDirty(false);

            fitsMainWindow->setMagnifierCenterPos(0, 0);
        }
    } else {
        sb->setDirty(true);
    }
}

void QFitsView3D::paintEvent(QPaintEvent *e) {
    QFitsSingleBuffer *sb = myParent->getMyBuffer();
    if ((sb != NULL) && (sb->getDpData()->type == typeFits)) {
        Fits *f = sb->getDpData()->fvalue;
        if (f == NULL) {
            return;
        }

        // if the dimensions of the subcube to be displayed changed,
        // extract the corresponding subcube and center it
        bool wasUpdated = false;
        if (sb->getDirty() || scalingDirty || colourtableDirty) {
            updateData();
            wasUpdated = true;
        }
//bool write = false;
//if (!write) {
//    dp_debug("INIT SIZE: %d %d %d", subcube.Naxis(1), subcube.Naxis(2), subcube.Naxis(3));
//     FILE *fh = fopen("gaga.data", "w");
//     int ss = subcube.Naxis(1)*subcube.Naxis(2)*subcube.Naxis(3);
//     int c = 0;
//     while (c < ss) {
//         putc( subcube.i1data[c], fh );
//         c++;
//     }
//     fclose(fh);
//    write = true;
//}
        // point Fits-cube to vtk-structure
        importer->SetWholeExtent(0, subcube.Naxis(1)-1,
                                 0, subcube.Naxis(2)-1,
                                 0, subcube.Naxis(3)-1);
        importer->SetDataExtentToWholeExtent();
        importer->SetImportVoidPointer(subcube.i1data);
        importer->Update();

        if (wasUpdated) {
            //updateAxes();
            wasUpdated = false;
        }

        if (!initialized) {
            previousBuffer = myParent->getBufferIndex();
            sb->setCamSettings(new cameraSettings());
            ResetCamera(false, true, true);

            initialized = true;
        } else {
            if (previousBuffer != myParent->getBufferIndex()) {
                // buffer changed by one way or the other

                // copy camera-settings to previousBuffer.camera-settings
                myParent->getBuffer(previousBuffer)->getCamSettings()->getSettings(camera);

                // create new camera settings
                if (sb->getCamSettings() == NULL) {
                    sb->setCamSettings(new cameraSettings());
                    ResetCamera(false, true, true);
                } else {
                    // copy currentBuffer.camera-settings to camera-settings
                    sb->getCamSettings()->setSettings(camera);
                    updateColourtable();
                    ResetCamera(false, false, false);
                }
                previousBuffer = myParent->getBufferIndex();
            }
        }

        this->QVTKWidget::paintEvent(e);

        fitsMainWindow->updateTotalVisibleRect();
    }
}

void QFitsView3D::keyPressEvent( QKeyEvent *e ) {
    fitsMainWindow->main_view->keyPressEvent(e);
}

// this code was copied from vtkRenderer::ResetCamera()
// (a direct call to rendererer->ResetCamera() produced a segmentation fault...)
void QFitsView3D::ResetCamera(bool reinitialise, bool setPosition, bool defReset)
{
    double x = subcube.Naxis(1);
    double y = subcube.Naxis(2);
    double z = subcube.Naxis(3);
    double bounds[6], center[3], distance, vn[3], *vup, w1, w2, w3, radius;

    bounds[0] = 0;
    bounds[1] = x;
    bounds[2] = 0;
    bounds[3] = y;
    bounds[4] = 0;
    bounds[5] = z;

    center[0] = (bounds[0] + bounds[1])/2.0;
    center[1] = (bounds[2] + bounds[3])/2.0;
    center[2] = (bounds[4] + bounds[5])/2.0;

    w1 = bounds[1] - bounds[0];
    w2 = bounds[3] - bounds[2];
    w3 = bounds[5] - bounds[4];
    w1 *= w1;
    w2 *= w2;
    w3 *= w3;

    radius = w1 + w2 + w3;

    // If we have just a single point, pick a radius of 1.0
    radius = (radius==0)?(1.0):(radius);

    // compute the radius of the enclosing sphere
    radius = sqrt(radius)*0.5;

    // default so that the bounding sphere fits within the view fustrum

    // compute the distance from the intersection of the view frustum with the
    // bounding sphere. Basically in 2D draw a circle representing the bounding
    // sphere in 2D then draw a horizontal line going out from the center of
    // the circle. That is the camera view. Then draw a line from the camera
    // position to the point where it intersects the circle. (it will be tangent
    // to the circle at this point, this is important, only go to the tangent
    // point, do not draw all the way to the view plane). Then draw the radius
    // from the tangent point to the center of the circle. You will note that
    // this forms a right triangle with one side being the radius, another being
    // the target distance for the camera, then just find the target dist using
    // a sin.

    distance = radius/sin(camera->GetViewAngle()*M_PI/360.0);

    // check view-up vector against view plane normal
    vup = camera->GetViewUp();

    camera->GetViewPlaneNormal(vn);

    // abs of dot-product
    if (fabs((vup[0]*vn[0] + vup[1]*vn[1] + vup[2]*vn[2])) > 0.999) {
        // Resetting view-up since view plane normal is parallel
        camera->SetViewUp(-vup[2], vup[0], vup[1]);
    }


if (setPosition) {
//    camera->SetPosition(center[0]+distance*vn[0],
//                                    center[1]+distance*vn[1],
//                                    center[2]+distance*vn[2]);
//    camera->SetPosition(center[0],
//                        center[1],
//                        center[2]+distance*vn[2]);
    camera->SetPosition(center[0],
                        center[1],
                        center[2]+distance);
}

    // update the camera
    camera->SetFocalPoint(center[0],center[1],center[2]);

    // commented this one out, made also a segmentation fault
    // renderer->ResetCameraClippingRange( bounds );

    // setup default parallel scale
    camera->SetParallelScale(radius);

    if (!initialized) {
        // save initial view angles
        double *xxx;
        xxx = camera->GetViewUp();
        default_cam_viewUp[0] = xxx[0];
        default_cam_viewUp[1] = xxx[1];
        default_cam_viewUp[2] = xxx[2];

        xxx = camera->GetPosition();
        default_cam_position[0] = xxx[0];
        default_cam_position[1] = xxx[1];
        default_cam_position[2] = xxx[2];
        iren->Initialize();
    } else {
        if (defReset) {
            // reset view angles
            camera->SetRoll(0.0); // set z to zero
            camera->SetViewUp(default_cam_viewUp);
            camera->SetPosition(default_cam_position);
        }
        if (reinitialise) {
            camera->SetViewUp(0.0, 1.0, 0.0);
            camera->SetRoll(0.0); // set z to zero
                camera->SetPosition(default_cam_position);
                camera->SetPosition(center[0],
                        center[1],
                        center[2]+distance);
//            iren->ReInitialize();
        }
        if (!(!reinitialise && !setPosition && !defReset)) {
            iren->ReInitialize();
            iren->Render();
        }
    }
}

// slot: called when colormap is inverted or changed
void QFitsView3D::updateColourtable() {
    colourtableDirty = true;
    newColourtable();
}

void QFitsView3D::newColourtable() {
    if (isVisible() && colourtableDirty) {

        // delete old colorTransferFunction
        colorTransferFunction->RemoveAllPoints();

        // create new colorTransferFunction
        int i = 0;
        QRgb color;
        for (i = 0; i < 256; ++i) {
            color = myParent->getMyBuffer()->getImage()->color(i);
            colorTransferFunction->AddRGBPoint(i, 1./(i+1) * qRed(color),
                                                  1./(i+1) * qGreen(color),
                                                  1./(i+1) * qBlue(color));
        }

        if (initialized) {
            iren->Render();
        }

        colourtableDirty = false;
    }
}

void QFitsView3D::enterEvent(QEvent *e)
{
    setFocus();
    myParent->enterBuffer();
}

void QFitsView3D::leaveEvent (QEvent *e)
{
    myParent->leaveBuffer();
}

// slot: called when rectangle in TotalView is moved
void QFitsView3D::setImageCenter(double x, double y) {
    QFitsSingleBuffer *sb = myParent->getMyBuffer();
    if (isVisible()) {
        sb->setXcenter(x);
        sb->setYcenter(y);

        fitsMainWindow->updateTotalVisibleRect();

        scalingDirty = true;
        newData();
    }
}

void QFitsView3D::calcZoomedVisibleArea() {
    QFitsSingleBuffer *sb = myParent->getMyBuffer();

    double zoomFactor = sb->getZoomFactor_3Dwire();
    if (zoomFactor > 1.) {
        // > 100%
        sb->setWidthVisible(sb->Naxis(1) / zoomFactor);
        sb->setHeightVisible(sb->Naxis(2) / zoomFactor);
    } else {
        // = 100% (can't be smaller than 100%)
        sb->setWidthVisible(sb->Naxis(1));
        sb->setHeightVisible(sb->Naxis(2));
    }
}

void QFitsView3D::applyZoom() {
    QFitsSingleBuffer *sb = myParent->getMyBuffer();
    if (sb != NULL) {
        calcZoomedVisibleArea();

        // calculate new size and recalculate distance of camera
        updateData();
        ResetCamera(false, false, false);

        newData2();
    }
}

//------------------------------------------------------------------------------
//         cameraSettings
//------------------------------------------------------------------------------
cameraSettings::cameraSettings() {
}

cameraSettings::~cameraSettings() {
}

void cameraSettings::getSettings(vtkCamera* camera) {
    camera->GetPosition(pos1, pos2, pos3);
    camera->GetFocalPoint(focal1, focal2, focal3);
    camera->GetViewUp (viewup1, viewup2, viewup3);
 }

void cameraSettings::setSettings(vtkCamera* camera) {
    camera->SetPosition(pos1, pos2, pos3);
    camera->SetFocalPoint(focal1, focal2, focal3);
    camera->SetViewUp (viewup1, viewup2, viewup3);
}
