Logo Search packages:      
Sourcecode: qtiplot version File versions  Download package

Graph3D.cpp

/***************************************************************************
    File                 : Graph3D.cpp
    Project              : QtiPlot
    --------------------------------------------------------------------
    Copyright            : (C) 2004-2007 by Ion Vasilief
    Email (use @ for *)  : ion_vasilief*yahoo.fr
    Description          : 3D graph widget

 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *  This program is free software; you can redistribute it and/or modify   *
 *  it under the terms of the GNU General Public License as published by   *
 *  the Free Software Foundation; either version 2 of the License, or      *
 *  (at your option) any later version.                                    *
 *                                                                         *
 *  This program is distributed in the hope that it will be useful,        *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 *  GNU General Public License for more details.                           *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the Free Software           *
 *   Foundation, Inc., 51 Franklin Street, Fifth Floor,                    *
 *   Boston, MA  02110-1301  USA                                           *
 *                                                                         *
 ***************************************************************************/
#include "Graph3D.h"
#include "Bar.h"
#include "Cone3D.h"
#include "MyParser.h"
#include "MatrixModel.h"

#include <QApplication>
#include <QMessageBox>
#include <QFileDialog>
#include <QPrinter>
#include <QClipboard>
#include <QPixmap>
#include <QBitmap>
#include <QDateTime>
#include <QCursor>
#include <QImageWriter>

#include <qwt3d_io_gl2ps.h>
#include <qwt3d_coordsys.h>

#include <gsl/gsl_vector.h>
#include <fstream>

UserFunction::UserFunction(const QString& s, SurfacePlot& pw)
: Function(pw), formula(s)
{}

double UserFunction::operator()(double x, double y)
{
      if (formula.isEmpty())
            return 0.0;

      MyParser parser;
      double result=0.0;
      try
      {
            parser.DefineVar("x", &x);
            parser.DefineVar("y", &y);

            parser.SetExpr((const std::string)formula.ascii());
            result=parser.Eval();
      }
      catch(mu::ParserError &e)
      {
            QMessageBox::critical(0,"QtiPlot - Input function error",QString::fromStdString(e.GetMsg()));
      }
      return result;
}

void UserFunction::setMesh (unsigned int columns, unsigned int rows)
{
      Function::setMesh (columns, rows);
      d_columns = columns;
      d_rows = rows;
}

UserParametricSurface::UserParametricSurface(const QString& xFormula, const QString& yFormula,
                                                                   const QString& zFormula, SurfacePlot& pw)
: ParametricSurface(pw),
d_x_formula(xFormula),
d_y_formula(yFormula),
d_z_formula(zFormula)
{}

void UserParametricSurface::setDomain(double ul, double ur, double vl, double vr)
{
      ParametricSurface::setDomain(ul, ur, vl, vr);
      d_ul = ul;
      d_ur = ur;
      d_vl = vl;
      d_vr = vr;
}

void UserParametricSurface::setMesh (unsigned int columns, unsigned int rows)
{
      ParametricSurface::setMesh (columns, rows);
      d_columns = columns;
      d_rows = rows;
}

void UserParametricSurface::setPeriodic (bool u, bool v)
{
      ParametricSurface::setPeriodic (u, v);
      d_u_periodic = u;
      d_v_periodic = v;
}

Triple UserParametricSurface::operator()(double u, double v)
{
      if (d_x_formula.isEmpty() || d_y_formula.isEmpty() || d_z_formula.isEmpty())
            return Triple(0.0, 0.0, 0.0);

      double x = 0.0, y = 0.0, z = 0.0;
      MyParser parser;
      try{
            parser.DefineVar("u", &u);
            parser.DefineVar("v", &v);

            parser.SetExpr((const std::string)d_x_formula.ascii());
            x = parser.Eval();
            parser.SetExpr((const std::string)d_y_formula.ascii());
            y = parser.Eval();
            parser.SetExpr((const std::string)d_z_formula.ascii());
            z = parser.Eval();
      }
      catch(mu::ParserError &e){
            QMessageBox::critical(0, "QtiPlot - Input function error", QString::fromStdString(e.GetMsg()));
      }
      return Triple(x, y, z);
}

Graph3D::Graph3D(const QString& label, QWidget* parent, const char* name, Qt::WFlags f)
: MyWidget(label, parent, name, f)
{
      initPlot();
}

void Graph3D::initPlot()
{
      d_table = 0;
      d_matrix = 0;
    plotAssociation = QString();

      QDateTime dt = QDateTime::currentDateTime ();
      setBirthDate(dt.toString(Qt::LocalDate));

    color_map = QString::null;
    animation_redraw_wait = 50;
    d_timer = new QTimer(this);
    connect(d_timer, SIGNAL(timeout()), this, SLOT(rotate()));
      ignoreFonts = false;

    setGeometry(0, 0, 500, 400);
      sp = new SurfacePlot(this);
      sp->resize(500, 400);
      sp->installEventFilter(this);
      sp->setRotation(30, 0, 15);
      sp->setScale(1, 1, 1);
      sp->setShift(0.15, 0, 0);
      sp->setZoom(0.9);
      sp->setOrtho(false);
      sp->setSmoothMesh(false);

      d_autoscale = true;

      title = QString();
      sp->setTitle(title);

      titleCol = QColor(Qt::black);
      sp->setTitleColor(Qt2GL(titleCol));

      titleFnt = QFont("Times New Roman", 14);
      titleFnt.setBold(true);

      sp->setTitleFont(titleFnt.family(), titleFnt.pointSize(),
                  titleFnt.weight(), titleFnt.italic());

      axesCol=QColor(Qt::black);
      labelsCol=QColor(Qt::black);
      numCol=QColor(Qt::black);
      meshCol=QColor(Qt::black);
      gridCol=QColor(Qt::black);
      bgCol=QColor(255, 255, 255);
      fromColor=QColor(Qt::red);
      toColor=QColor(Qt::blue);

      col_ = 0;

      legendOn = false;
      legendMajorTicks = 5;
      sp->showColorLegend(legendOn);
      sp->legend()->setAutoScale(true);
      sp->legend()->setMajors(legendMajorTicks) ;

      labelsDist=0;

      scaleType=QVector<int>(3);
      for (int j=0;j<3;j++)
            scaleType[j]=0;

      pointStyle = None;
      d_func = 0;
      d_surface = 0;
      alpha = 1.0;
      barsRad = 0.007;
      d_point_size = 5; d_smooth_points = false;
      crossHairRad = 0.03, crossHairLineWidth = 2;
      crossHairSmooth = true, crossHairBoxed = false;
      conesQuality = 32; conesRad = 0.5;

      style_ = NOPLOT;
      initCoord();

#if defined(Q_WS_MAC)
      connect(this, SIGNAL(moved()), this, SLOT(moveSurfacePlot()));
#endif
      connect(sp,SIGNAL(rotationChanged(double, double, double)),this,SLOT(rotationChanged(double, double, double)));
      connect(sp,SIGNAL(zoomChanged(double)),this,SLOT(zoomChanged(double)));
      connect(sp,SIGNAL(scaleChanged(double, double, double)),this,SLOT(scaleChanged(double, double, double)));
      connect(sp,SIGNAL(shiftChanged(double, double, double)),this,SLOT(shiftChanged(double, double, double)));
}

void Graph3D::initCoord()
{
      sp->makeCurrent();
      for (unsigned i=0; i!=sp->coordinates()->axes.size(); ++i){
            sp->coordinates()->axes[i].setMajors(5);
            sp->coordinates()->axes[i].setMinors(5);
      }

      QString s = tr("X axis");
      sp->coordinates()->axes[X1].setLabelString(s);
      sp->coordinates()->axes[X2].setLabelString(s);
      sp->coordinates()->axes[X3].setLabelString(s);
      sp->coordinates()->axes[X4].setLabelString(s);
      labels<<s;

      s = tr("Y axis");
      sp->coordinates()->axes[Y1].setLabelString(s);
      sp->coordinates()->axes[Y2].setLabelString(s);
      sp->coordinates()->axes[Y3].setLabelString(s);
      sp->coordinates()->axes[Y4].setLabelString(s);
      labels<<s;

      s = tr("Z axis");
      sp->coordinates()->axes[Z1].setLabelString(s);
      sp->coordinates()->axes[Z2].setLabelString(s);
      sp->coordinates()->axes[Z3].setLabelString(s);
      sp->coordinates()->axes[Z4].setLabelString(s);
      labels<<s;

      sp->setCoordinateStyle(BOX);
      sp->coordinates()->setLineSmooth(false);
      sp->coordinates()->setAutoScale(false);
}

void Graph3D::addFunction(const QString& s, double xl, double xr, double yl,
                                    double yr, double zl, double zr, int columns, int rows)
{
      if (d_surface)
            delete d_surface;
      else if (d_func)
            delete d_func;

      sp->makeCurrent();
      sp->resize(this->size());

      d_func = new UserFunction(s, *sp);

      d_func->setMesh(columns, rows);
      d_func->setDomain(xl, xr, yl, yr);
      d_func->setMinZ(zl);
      d_func->setMaxZ(zr);
      d_func->create();

      sp->legend()->setLimits(zl, zr);

      if (sp->plotStyle() == NOPLOT){
            sp->setPlotStyle(FILLED);
            style_=FILLED;
            pointStyle = None;
      }
      sp->createCoordinateSystem(Triple(xl, yl, zl), Triple(xr, yr, zr));
      findBestLayout();
      update();
}

void Graph3D::addParametricSurface(const QString& xFormula, const QString& yFormula,
                                    const QString& zFormula, double ul, double ur, double vl, double vr,
                                    int columns, int rows, bool uPeriodic, bool vPeriodic)
{
      if (d_surface)
            delete d_surface;
      else if (d_func)
            delete d_func;

      sp->makeCurrent();
      sp->resize(this->size());

      d_surface = new UserParametricSurface(xFormula, yFormula, zFormula, *sp);
      d_surface->setMesh(columns, rows);
      d_surface->setDomain(ul, ur, vl, vr);
      d_surface->setPeriodic(uPeriodic, vPeriodic);
      d_surface->create();

      double zl, zr;
      sp->coordinates()->axes[Z1].limits(zl, zr);
      sp->legend()->setLimits(zl, zr);

      if (sp->plotStyle() == NOPLOT){
            sp->setPlotStyle(FILLED);
            style_=FILLED;
            pointStyle = None;
      }
      //sp->createCoordinateSystem(Triple(xl, yl, zl), Triple(xr, yr, zr));
      findBestLayout();
      update();
}

void Graph3D::addData(Table* table,const QString& xColName, const QString& yColName)
{
      if (!table)
            return;

      int xcol = table->colIndex(xColName);
      int ycol =  table->colIndex(yColName);

      if (xcol < 0 || ycol < 0)
            return;

      plotAssociation = xColName+"(X)," + yColName+"(Y)";
      d_table=table;
      int r=table->numRows();
      int i, xmesh=0, ymesh=2;
      for (i = 0; i < r; i++){
            if (!table->text(i,xcol).isEmpty() && !table->text(i,ycol).isEmpty())
                  xmesh++;
      }

      if (xmesh == 0)
            xmesh++;

      double **data = Matrix::allocateMatrixData(xmesh, ymesh);
      gsl_vector * x = gsl_vector_alloc (xmesh);
      gsl_vector * y = gsl_vector_alloc (xmesh);

      for (int j = 0; j < ymesh; j++){
            int k=0;
            for (i = 0; i < r; i++){
                  if (!table->text(i,xcol).isEmpty() && !table->text(i,ycol).isEmpty()){
                        gsl_vector_set (x, k, table->cell(i, xcol));

                        double yv = table->cell(i, ycol);
                        gsl_vector_set (y, k, yv);
                        data[k][j] = yv;
                        k++;
                  }
            }
      }

      double maxy=gsl_vector_max(y);
      double maxz=0.6*maxy;
      sp->makeCurrent();
      sp->legend()->setLimits(gsl_vector_min(y),maxy);
      sp->loadFromData(data, xmesh, ymesh, gsl_vector_min(x),gsl_vector_max(x),0,maxz);

      if (d_autoscale)
            findBestLayout();

      gsl_vector_free (x);
      gsl_vector_free (y);
      Matrix::freeMatrixData(data, xmesh);
}

void Graph3D::addData(Table* table,const QString& xColName,const QString& yColName,
            double xl, double xr, double yl, double yr, double zl, double zr)
{
      d_table=table;
      int r=table->numRows();
      int xcol=table->colIndex(xColName);
      int ycol=table->colIndex(yColName);

      plotAssociation = xColName + "(X)," + yColName + "(Y)";

      int i, j, xmesh=0, ymesh=2;
      double xv, yv;

      for (i = 0; i < r; i++){
            if (!table->text(i,xcol).isEmpty() && !table->text(i,ycol).isEmpty()){
                  xv=table->cell(i, xcol);
                  if (xv>=xl && xv <= xr)
                        xmesh++;
            }
      }

      if (xmesh == 0)
            xmesh++;

      double **data = Matrix::allocateMatrixData(xmesh, ymesh);
      for ( j = 0; j < ymesh; j++){
            int k=0;
            for ( i = 0; i < r; i++){
                  if (!table->text(i,xcol).isEmpty() && !table->text(i,ycol).isEmpty()){
                        xv=table->cell(i,xcol);
                        if (xv>=xl && xv <= xr){
                              yv=table->cell(i,ycol);
                              if (yv > zr)
                                    data[k][j] = zr;
                              else if (yv < zl)
                                    data[k][j] = zl;
                              else
                                    data[k][j] = yv;
                              k++;
                        }
                  }
            }
      }
      sp->makeCurrent();
      sp->loadFromData(data, xmesh, ymesh, xl, xr, yl, yr);
      sp->createCoordinateSystem(Triple(xl, yl, zl), Triple(xr, yr, zr));
      sp->legend()->setLimits(zl, zr);
      sp->legend()->setMajors(legendMajorTicks);

      Matrix::freeMatrixData(data, xmesh);
}

void Graph3D::addMatrixData(Matrix* m)
{
      if (!m || d_matrix == m)
            return;

      bool first_time = false;
      if(!d_matrix)
            first_time = true;

      d_matrix = m;
      plotAssociation = "matrix<" + QString(m->objectName()) + ">";

      int cols = m->numCols();
      int rows = m->numRows();

      double **data_matrix = Matrix::allocateMatrixData(cols, rows);
      for (int i = 0; i < cols; i++ ){
            for (int j = 0; j < rows; j++)
                  data_matrix[i][j] = m->cell(j, i);
      }

      sp->makeCurrent();
      sp->loadFromData(data_matrix, cols, rows, m->xStart(), m->xEnd(), m->yStart(), m->yEnd());

      double start, end;
      sp->coordinates()->axes[Z1].limits (start, end);
      sp->legend()->setLimits(start, end);
      sp->legend()->setMajors(legendMajorTicks);

      Matrix::freeMatrixData(data_matrix, cols);

      if (d_autoscale || first_time)
            findBestLayout();
      update();
}

void Graph3D::addMatrixData(Matrix* m, double xl, double xr,
            double yl, double yr, double zl, double zr)
{
      d_matrix = m;
      plotAssociation = "matrix<" + QString(m->objectName()) + ">";

      updateScalesFromMatrix(xl, xr, yl, yr, zl, zr);
}

void Graph3D::insertNewData(Table* table, const QString& colName)
{
      int zCol=table->colIndex(colName);
      int yCol=table->colY(zCol);
      int xCol=table->colX(zCol);

      addData(table, xCol, yCol, zCol, Trajectory);
      update();
}

void Graph3D::changeDataColumn(Table* table, const QString& colName, int type)
{
      if (!table)
            return;

      resetNonEmptyStyle();

      if (type == Ribbon) {
            int ycol = table->colIndex(colName);
            int xcol = table->colX(ycol);

            addData(table, table->colName(xcol), colName);
            setFilledMeshStyle();
      } else {
            int zCol=table->colIndex(colName);
            int yCol=table->colY(zCol);
            int xCol=table->colX(zCol);

            addData(table, xCol, yCol, zCol, type);
      }

    resetAxesLabels();
}

void Graph3D::addData(Table* table, int xCol, int yCol, int zCol, int type)
{
      loadData(table, xCol, yCol, zCol);

      if (d_autoscale)
            findBestLayout();

      if (type == Scatter)
            setDotStyle();
      else if (type == Trajectory)
            setWireframeStyle();
      else
            setBarStyle();
}

void Graph3D::loadData(Table* table, int xCol, int yCol, int zCol,
            double xl, double xr, double yl, double yr, double zl, double zr)
{
      if (!table || xCol < 0 || yCol < 0 || zCol < 0)
            return;

      d_table = table;

      plotAssociation = table->colName(xCol) + "(X),";
      plotAssociation += table->colName(yCol) + "(Y),";
      plotAssociation += table->colName(zCol) + "(Z)";

      bool check_limits = true;
      if (xl == xr && yl == yr && zl == zr)
            check_limits = false;

      Qwt3D::TripleField data;
      Qwt3D::CellField cells;
      int index = 0;
      for (int i = 0; i < table->numRows(); i++){
            if (!table->text(i, xCol).isEmpty() && !table->text(i, yCol).isEmpty() && !table->text(i, zCol).isEmpty()){
                  double x = table->cell(i, xCol);
                  double y = table->cell(i, yCol);
                  double z = table->cell(i, zCol);

                  if (check_limits && (x < xl || x > xr || y < yl || y > yr || z < zl || z > zr))
                        continue;

                  data.push_back (Triple(x, y, z));
                  Qwt3D::Cell cell;
                  cell.push_back(index);
                  if (index > 0)
                cell.push_back(index-1);
                  cells.push_back (cell);
                  index ++;
            }
      }

      sp->loadFromData (data, cells);
      if (check_limits)
            sp->createCoordinateSystem(Triple(xl, yl, zl), Triple(xr, yr, zr));

      double start, end;
      sp->coordinates()->axes[Z1].limits (start, end);
      sp->legend()->setLimits(start, end);
      sp->legend()->setMajors(legendMajorTicks);
}

void Graph3D::updateData(Table* table)
{
      if (d_func)// function plot
            return;

      QString name = plotAssociation;
      int pos=name.find("_",0);
      int posX=name.find("(",pos);
      QString xColName=name.mid(pos+1,posX-pos-1);

      pos=name.find(",", posX);
      posX=name.find("(", pos);
      QString yColName=name.mid(pos+1, posX-pos-1);

      int xCol=table->colIndex(xColName);
      int yCol=table->colIndex(yColName);

      if (name.contains("(Z)", true)) {
            pos=name.find(",", posX);
            posX=name.find("(", pos);
            QString zColName=name.mid(pos+1, posX-pos-1);
            int zCol=table->colIndex(zColName);
            resetNonEmptyStyle();
            loadData(table, xCol, yCol, zCol);
      } else
            updateDataXY(table, xCol, yCol);

      if (d_autoscale)
            findBestLayout();
      update();
}

void Graph3D::updateDataXY(Table* table, int xCol, int yCol)
{
      int r=table->numRows();
      int i, j, xmesh=0, ymesh=2;

      for (i = 0; i < r; i++)
      {
            if (!table->text(i,xCol).isEmpty() && !table->text(i,yCol).isEmpty())
                  xmesh++;
      }

      if (xmesh<2)
      {
            sp->setPlotStyle(NOPLOT);
            update();
            return;
      }

      double **data = Matrix::allocateMatrixData(xmesh, ymesh);
      gsl_vector * x = gsl_vector_alloc (xmesh);
      gsl_vector * y = gsl_vector_alloc (xmesh);

      for ( j = 0; j < ymesh; j++)
      {
            int k=0;
            for ( i = 0; i < r; i++)
            {
                  if (!table->text(i,xCol).isEmpty() && !table->text(i,yCol).isEmpty())
                  {
                        double xv=table->cell(i,xCol);
                        double yv=table->cell(i,yCol);

                        gsl_vector_set (x, k, xv);
                        gsl_vector_set (y, k, yv);

                        data[k][j] =yv;
                        k++;
                  }
            }
      }

      double minx=gsl_vector_min (x);
      double maxx=gsl_vector_max(x);
      double minz=gsl_vector_min (y);
      double maxz=gsl_vector_max(y);
      double miny, maxy;

      sp->makeCurrent();
      resetNonEmptyStyle();
      sp->coordinates()->axes[Y1].limits (miny,maxy); //actual Y scale limits
      sp->loadFromData(data, xmesh, ymesh, minx, maxx, miny, maxy);
      sp->legend()->setLimits(minz,maxz);
      sp->legend()->setMajors(legendMajorTicks);

      gsl_vector_free (x);gsl_vector_free (y);
      Matrix::freeMatrixData(data, xmesh);
}

void Graph3D::updateMatrixData(Matrix* m)
{
      int cols=m->numCols();
      int rows=m->numRows();

      double **data = Matrix::allocateMatrixData(cols, rows);
      for (int i = 0; i < cols; i++ ){
            for (int j = 0; j < rows; j++)
                  data[i][j] = m->cell(j, i);
      }
      sp->loadFromData(data, cols, rows, m->xStart(), m->xEnd(), m->yStart(), m->yEnd());

      Qwt3D::Axis z_axis = sp->coordinates()->axes[Z1];
      double start, end;
      z_axis.limits (start, end);
      z_axis.setMajors(z_axis.majors());
      z_axis.setMajors(z_axis.minors());

      sp->legend()->setLimits(start, end);
      sp->legend()->setMajors(legendMajorTicks);

      Matrix::freeMatrixData(data, cols);
      if (d_autoscale)
            findBestLayout();
      update();
}

void Graph3D::resetNonEmptyStyle()
{
      if (sp->plotStyle() != Qwt3D::NOPLOT )
            return; // the plot was not previousely emptied

      if (style_== Qwt3D::USER)
      {// reseting the right user plot style
            switch (pointStyle)
            {
                  case None:
                        break;

                  case Dots :
                        sp->setPlotStyle(Dot(d_point_size, d_smooth_points));
                        break;

                  case VerticalBars :
                        sp->setPlotStyle(Bar(barsRad));
                        break;

                  case HairCross :
                        sp->setPlotStyle(CrossHair(crossHairRad, crossHairLineWidth, crossHairSmooth, crossHairBoxed));
                        break;

                  case Cones :
                        sp->setPlotStyle(Cone3D(conesRad, conesQuality));
                        break;
            }
      }
      else
            sp->setPlotStyle(style_);
}

void Graph3D::update()
{
      sp->makeCurrent();

      resetAxesLabels();

      sp->updateData();
      sp->updateGL();
}

void Graph3D::setLabelsDistance(int val)
{
      if (labelsDist != val){
            labelsDist = val;
            sp->coordinates()->adjustLabels(val);
            sp->makeCurrent();
            sp->updateGL();
        emit modified();
      }
}

QFont Graph3D::numbersFont()
{
      return sp->coordinates()->axes[X1].numberFont();
}

void Graph3D::setNumbersFont(const QFont& font)
{
      sp->coordinates()->setNumberFont (font);
      sp->makeCurrent();
      sp->updateGL();
}

void Graph3D::setNumbersFont(const QStringList& lst)
{
      QFont fnt=QFont(lst[1],lst[2].toInt(),lst[3].toInt(),lst[4].toInt());
      sp->coordinates()->setNumberFont(fnt);
}

void Graph3D::setXAxisLabelFont(const QFont& fnt)
{
      sp->coordinates()->axes[X1].setLabelFont(fnt);
      sp->coordinates()->axes[X2].setLabelFont(fnt);
      sp->coordinates()->axes[X3].setLabelFont(fnt);
      sp->coordinates()->axes[X4].setLabelFont(fnt);
}

void Graph3D::setYAxisLabelFont(const QFont& fnt)
{
      sp->coordinates()->axes[Y1].setLabelFont(fnt);
      sp->coordinates()->axes[Y2].setLabelFont(fnt);
      sp->coordinates()->axes[Y3].setLabelFont(fnt);
      sp->coordinates()->axes[Y4].setLabelFont(fnt);
}

void Graph3D::setZAxisLabelFont(const QFont& fnt)
{
      sp->coordinates()->axes[Z1].setLabelFont(fnt);
      sp->coordinates()->axes[Z2].setLabelFont(fnt);
      sp->coordinates()->axes[Z3].setLabelFont(fnt);
      sp->coordinates()->axes[Z4].setLabelFont(fnt);
}

void Graph3D::setXAxisLabelFont(const QStringList& lst)
{
      QFont fnt=QFont(lst[1],lst[2].toInt(),lst[3].toInt(),lst[4].toInt());
      sp->coordinates()->axes[X1].setLabelFont(fnt);
      sp->coordinates()->axes[X2].setLabelFont(fnt);
      sp->coordinates()->axes[X3].setLabelFont(fnt);
      sp->coordinates()->axes[X4].setLabelFont(fnt);
}

void Graph3D::setYAxisLabelFont(const QStringList& lst)
{
      QFont fnt=QFont(lst[1],lst[2].toInt(),lst[3].toInt(),lst[4].toInt());
      sp->coordinates()->axes[Y1].setLabelFont(fnt);
      sp->coordinates()->axes[Y2].setLabelFont(fnt);
      sp->coordinates()->axes[Y3].setLabelFont(fnt);
      sp->coordinates()->axes[Y4].setLabelFont(fnt);
}

void Graph3D::setZAxisLabelFont(const QStringList& lst)
{
      QFont fnt=QFont(lst[1],lst[2].toInt(),lst[3].toInt(),lst[4].toInt());
      sp->coordinates()->axes[Z1].setLabelFont(fnt);
      sp->coordinates()->axes[Z2].setLabelFont(fnt);
      sp->coordinates()->axes[Z3].setLabelFont(fnt);
      sp->coordinates()->axes[Z4].setLabelFont(fnt);
}

QStringList Graph3D::axisTickLengths()
{
      QStringList lst;
      double majorl,minorl;

      sp->coordinates()->axes[X1].ticLength (majorl,minorl);
      lst<<QString::number(majorl);
      lst<<QString::number(minorl);

      sp->coordinates()->axes[Y1].ticLength (majorl,minorl);
      lst<<QString::number(majorl);
      lst<<QString::number(minorl);

      sp->coordinates()->axes[Z1].ticLength (majorl,minorl);
      lst<<QString::number(majorl);
      lst<<QString::number(minorl);

      return lst;
}

void Graph3D::setTickLengths(const QStringList& lst)
{
      double majorl, minorl;
      QStringList tick_length = lst;
      if (int(lst.count()) > 6)
            tick_length.remove(tick_length.first());

      majorl=tick_length[0].toDouble();
      minorl=tick_length[1].toDouble();
      sp->coordinates()->axes[X1].setTicLength (majorl,minorl);
      sp->coordinates()->axes[X2].setTicLength (majorl,minorl);
      sp->coordinates()->axes[X3].setTicLength (majorl,minorl);
      sp->coordinates()->axes[X4].setTicLength (majorl,minorl);

      majorl=tick_length[2].toDouble();
      minorl=tick_length[3].toDouble();
      sp->coordinates()->axes[Y1].setTicLength (majorl,minorl);
      sp->coordinates()->axes[Y2].setTicLength (majorl,minorl);
      sp->coordinates()->axes[Y3].setTicLength (majorl,minorl);
      sp->coordinates()->axes[Y4].setTicLength (majorl,minorl);

      majorl=tick_length[4].toDouble();
      minorl=tick_length[5].toDouble();
      sp->coordinates()->axes[Z1].setTicLength (majorl,minorl);
      sp->coordinates()->axes[Z2].setTicLength (majorl,minorl);
      sp->coordinates()->axes[Z3].setTicLength (majorl,minorl);
      sp->coordinates()->axes[Z4].setTicLength (majorl,minorl);
}

void Graph3D::setXAxisTickLength(double majorLength, double minorLength)
{
      double majorl, minorl;
      sp->coordinates()->axes[X1].ticLength (majorl,minorl);
      if (majorl != majorLength || minorl != minorLength){
            sp->coordinates()->axes[X1].setTicLength (majorLength,minorLength);
            sp->coordinates()->axes[X2].setTicLength (majorLength,minorLength);
            sp->coordinates()->axes[X3].setTicLength (majorLength,minorLength);
            sp->coordinates()->axes[X4].setTicLength (majorLength,minorLength);
            }
}

void Graph3D::setYAxisTickLength(double majorLength, double minorLength)
{
      double majorl, minorl;
      sp->coordinates()->axes[Y1].ticLength (majorl,minorl);
      if (majorl != majorLength || minorl != minorLength){
            sp->coordinates()->axes[Y1].setTicLength (majorLength,minorLength);
            sp->coordinates()->axes[Y2].setTicLength (majorLength,minorLength);
            sp->coordinates()->axes[Y3].setTicLength (majorLength,minorLength);
            sp->coordinates()->axes[Y4].setTicLength (majorLength,minorLength);
      }
}

void Graph3D::setZAxisTickLength(double majorLength, double minorLength)
{
      double majorl, minorl;
      sp->coordinates()->axes[Z1].ticLength (majorl,minorl);
      if (majorl != majorLength || minorl != minorLength){
            sp->coordinates()->axes[Z1].setTicLength (majorLength,minorLength);
            sp->coordinates()->axes[Z2].setTicLength (majorLength,minorLength);
            sp->coordinates()->axes[Z3].setTicLength (majorLength,minorLength);
            sp->coordinates()->axes[Z4].setTicLength (majorLength,minorLength);
      }
}

void Graph3D::setAxisTickLength(int axis, double majorLength, double minorLength)
{
      double majorl, minorl;
      switch(axis)
      {
            case 0:
                  sp->coordinates()->axes[X1].ticLength (majorl,minorl);
                  if (majorl != majorLength || minorl != minorLength){
                        sp->coordinates()->axes[X1].setTicLength (majorLength,minorLength);
                        sp->coordinates()->axes[X2].setTicLength (majorLength,minorLength);
                        sp->coordinates()->axes[X3].setTicLength (majorLength,minorLength);
                        sp->coordinates()->axes[X4].setTicLength (majorLength,minorLength);
                  }
                  break;

            case 1:
                  sp->coordinates()->axes[Y1].ticLength (majorl,minorl);
                  if (majorl != majorLength || minorl != minorLength){
                        sp->coordinates()->axes[Y1].setTicLength (majorLength,minorLength);
                        sp->coordinates()->axes[Y2].setTicLength (majorLength,minorLength);
                        sp->coordinates()->axes[Y3].setTicLength (majorLength,minorLength);
                        sp->coordinates()->axes[Y4].setTicLength (majorLength,minorLength);
                  }
                  break;

            case 2:
                  sp->coordinates()->axes[Z1].ticLength (majorl,minorl);
                  if (majorl != majorLength || minorl != minorLength){
                        sp->coordinates()->axes[Z1].setTicLength (majorLength,minorLength);
                        sp->coordinates()->axes[Z2].setTicLength (majorLength,minorLength);
                        sp->coordinates()->axes[Z3].setTicLength (majorLength,minorLength);
                        sp->coordinates()->axes[Z4].setTicLength (majorLength,minorLength);
                  }
                  break;
      }
      sp->updateGL();
}

void Graph3D::rotationChanged(double, double, double)
{
      emit modified();
}

void Graph3D::scaleChanged(double, double, double)
{
      emit modified();
}

void Graph3D::shiftChanged(double, double, double)
{
      emit modified();
}

void Graph3D::zoomChanged(double)
{
      emit modified();
}

void Graph3D::resetAxesLabels()
{
      sp->coordinates()->axes[X1].setLabelString(labels[0]);
      sp->coordinates()->axes[X2].setLabelString(labels[0]);
      sp->coordinates()->axes[X3].setLabelString(labels[0]);
      sp->coordinates()->axes[X4].setLabelString(labels[0]);

      sp->coordinates()->axes[Y1].setLabelString(labels[1]);
      sp->coordinates()->axes[Y2].setLabelString(labels[1]);
      sp->coordinates()->axes[Y3].setLabelString(labels[1]);
      sp->coordinates()->axes[Y4].setLabelString(labels[1]);

      sp->coordinates()->axes[Z1].setLabelString(labels[2]);
      sp->coordinates()->axes[Z2].setLabelString(labels[2]);
      sp->coordinates()->axes[Z3].setLabelString(labels[2]);
      sp->coordinates()->axes[Z4].setLabelString(labels[2]);
}

void Graph3D::setAxesLabels(const QStringList& l)
{
      QString label = l[0];
      sp->coordinates()->axes[X1].setLabelString(label);
      sp->coordinates()->axes[X2].setLabelString(label);
      sp->coordinates()->axes[X3].setLabelString(label);
      sp->coordinates()->axes[X4].setLabelString(label);

      label = l[1];
      sp->coordinates()->axes[Y1].setLabelString(label);
      sp->coordinates()->axes[Y2].setLabelString(label);
      sp->coordinates()->axes[Y3].setLabelString(label);
      sp->coordinates()->axes[Y4].setLabelString(label);

      label = l[2];
      sp->coordinates()->axes[Z1].setLabelString(label);
      sp->coordinates()->axes[Z2].setLabelString(label);
      sp->coordinates()->axes[Z3].setLabelString(label);
      sp->coordinates()->axes[Z4].setLabelString(label);

      labels = l;
}

void Graph3D::setXAxisLabel(const QString& label)
{
    if (labels[0] != label){
        sp->coordinates()->axes[X1].setLabelString(label);
        sp->coordinates()->axes[X2].setLabelString(label);
        sp->coordinates()->axes[X3].setLabelString(label);
        sp->coordinates()->axes[X4].setLabelString(label);
        labels[0]=label;
    }

      sp->makeCurrent();
      sp->updateGL();
      emit modified();
}

void Graph3D::setYAxisLabel(const QString& label)
{
    if (labels[1] != label){
        sp->coordinates()->axes[Y1].setLabelString(label);
        sp->coordinates()->axes[Y2].setLabelString(label);
        sp->coordinates()->axes[Y3].setLabelString(label);
        sp->coordinates()->axes[Y4].setLabelString(label);
        labels[1]=label;
    }

      sp->makeCurrent();
      sp->updateGL();
      emit modified();
}

void Graph3D::setZAxisLabel(const QString& label)
{
    if (labels[2] != label){
        sp->coordinates()->axes[Z1].setLabelString(label);
        sp->coordinates()->axes[Z2].setLabelString(label);
        sp->coordinates()->axes[Z3].setLabelString(label);
        sp->coordinates()->axes[Z4].setLabelString(label);
        labels[2]=label;
    }

      sp->makeCurrent();
      sp->updateGL();
      emit modified();
}

QFont Graph3D::xAxisLabelFont()
{
      return sp->coordinates()->axes[X1].labelFont();
}

QFont Graph3D::yAxisLabelFont()
{
      return sp->coordinates()->axes[Y1].labelFont();
}

QFont Graph3D::zAxisLabelFont()
{
      return sp->coordinates()->axes[Z1].labelFont();
}

double Graph3D::xStart()
{
      double start,stop;
      sp->coordinates()->axes[X1].limits (start,stop);
      return start;
}

double Graph3D::xStop()
{
      double start,stop;
      sp->coordinates()->axes[X1].limits (start,stop);
      return stop;
}

double Graph3D::yStart()
{
      double start,stop;
      sp->coordinates()->axes[Y1].limits (start,stop);
      return start;
}

double Graph3D::yStop()
{
      double start,stop;
      sp->coordinates()->axes[Y1].limits (start,stop);
      return stop;
}

double Graph3D::zStart()
{
      double start,stop;
      sp->coordinates()->axes[Z1].limits (start,stop);
      return start;
}

double Graph3D::zStop()
{
      double start,stop;
      sp->coordinates()->axes[Z1].limits(start, stop);
      return stop;
}

QStringList Graph3D::scaleLimits()
{
      QStringList limits;
      double start, stop;
      int majors, minors;

      sp->coordinates()->axes[X1].limits (start,stop);
      majors=sp->coordinates()->axes[X1].majors();
      minors=sp->coordinates()->axes[X1].minors();

      limits<<QString::number(start);
      limits<<QString::number(stop);
      limits<<QString::number(majors);
      limits<<QString::number(minors);
      limits<<QString::number(scaleType[0]);

      sp->coordinates()->axes[Y1].limits (start,stop);
      majors=sp->coordinates()->axes[Y1].majors();
      minors=sp->coordinates()->axes[Y1].minors();

      limits<<QString::number(start);
      limits<<QString::number(stop);
      limits<<QString::number(majors);
      limits<<QString::number(minors);
      limits<<QString::number(scaleType[1]);

      sp->coordinates()->axes[Z1].limits (start,stop);
      majors=sp->coordinates()->axes[Z1].majors();
      minors=sp->coordinates()->axes[Z1].minors();

      limits<<QString::number(start);
      limits<<QString::number(stop);
      limits<<QString::number(majors);
      limits<<QString::number(minors);
      limits<<QString::number(scaleType[2]);

      return limits;
}

QStringList Graph3D::scaleTicks()
{
      QStringList limits;
      int majors,minors;

      majors=sp->coordinates()->axes[X1].majors();
      minors=sp->coordinates()->axes[X1].minors();
      limits<<QString::number(majors);
      limits<<QString::number(minors);

      majors=sp->coordinates()->axes[Y1].majors();
      minors=sp->coordinates()->axes[Y1].minors();
      limits<<QString::number(majors);
      limits<<QString::number(minors);

      majors=sp->coordinates()->axes[Z1].majors();
      minors=sp->coordinates()->axes[Z1].minors();
      limits<<QString::number(majors);
      limits<<QString::number(minors);

      return limits;
}

void Graph3D::updateScale(int axis, const QStringList& options)
{
      QString st = QString::number(scaleType[axis]);
      double start, stop, xl, xr, yl, yr;
      int majors, minors, newMaj, newMin;

      sp->makeCurrent();
      switch(axis)
      {
            case 0:
                  majors=sp->coordinates()->axes[X1].majors ();
              minors=sp->coordinates()->axes[X1].minors ();
                  sp->coordinates()->axes[X1].limits(xl,xr);
                  if (xl !=options[0].toDouble() || xr != options[1].toDouble())
                  {
                        xl=options[0].toDouble();
                        xr=options[1].toDouble();
                        sp->coordinates()->axes[Y1].limits(yl,yr);
                        sp->coordinates()->axes[Z1].limits(start,stop);

                        if (d_func){
                              d_func->setDomain(xl,xr,yl,yr);
                              d_func->create ();
                              sp->createCoordinateSystem(Triple(xl, yl, start), Triple(xr, yr, stop));
                        } else if (d_surface){
                              d_surface->restrictRange (ParallelEpiped(Triple(xl, yl, start), Triple(xr, yr, stop)));
                              d_surface->create();
                              sp->createCoordinateSystem(Triple(xl, yl, start), Triple(xr, yr, stop));
                        } else
                              setScales(xl, xr, yl, yr, start, stop);
                  }

                  if(st != options[4]){
                        if (options[4]=="0"){
                              sp->coordinates()->axes[X1].setScale (LINEARSCALE);
                              scaleType[axis]=0;
                        } else {
                              sp->coordinates()->axes[X1].setScale (LOG10SCALE);
                              scaleType[axis]=1;
                        }
                  }

                  newMaj = options[2].toInt();
                  if (majors != newMaj){
                        sp->coordinates()->axes[X1].setMajors(newMaj);
                        sp->coordinates()->axes[X2].setMajors(newMaj);
                        sp->coordinates()->axes[X3].setMajors(newMaj);
                        sp->coordinates()->axes[X4].setMajors(newMaj);
                  }

                  newMin = options[3].toInt();
                  if (minors != newMin){
                        sp->coordinates()->axes[X1].setMinors(newMin);
                        sp->coordinates()->axes[X2].setMinors(newMin);
                        sp->coordinates()->axes[X3].setMinors(newMin);
                        sp->coordinates()->axes[X4].setMinors(newMin);
                  }
                  break;

            case 1:
                  majors = sp->coordinates()->axes[Y1].majors ();
              minors = sp->coordinates()->axes[Y1].minors ();
                  sp->coordinates()->axes[Y1].limits(yl, yr);
                  if (yl != options[0].toDouble() || yr != options[1].toDouble()){
                        yl = options[0].toDouble();
                        yr = options[1].toDouble();
                        sp->coordinates()->axes[X1].limits(xl, xr);
                        sp->coordinates()->axes[Z1].limits(start, stop);

                        if (d_func){
                              d_func->setDomain(xl, xr, yl, yr);
                              d_func->create();
                              sp->createCoordinateSystem(Triple(xl, yl, start), Triple(xr, yr, stop));
                        } else if (d_surface){
                              d_surface->restrictRange (ParallelEpiped(Triple(xl, yl, start), Triple(xr, yr, stop)));
                              d_surface->create();
                              sp->createCoordinateSystem(Triple(xl, yl, start), Triple(xr, yr, stop));
                        } else
                              setScales(xl, xr, yl, yr, start, stop);
                  }

                  newMaj = options[2].toInt();
                  if (majors != newMaj ){
                        sp->coordinates()->axes[Y1].setMajors(newMaj);
                        sp->coordinates()->axes[Y2].setMajors(newMaj);
                        sp->coordinates()->axes[Y3].setMajors(newMaj);
                        sp->coordinates()->axes[Y4].setMajors(newMaj);
                  }

            newMin = options[3].toInt();
                  if (minors != newMin){
                        sp->coordinates()->axes[Y1].setMinors(newMin);
                        sp->coordinates()->axes[Y2].setMinors(newMin);
                        sp->coordinates()->axes[Y3].setMinors(newMin);
                        sp->coordinates()->axes[Y4].setMinors(newMin);
                  }

                  if(st != options[4]){
                        if (options[4]=="0"){
                              sp->coordinates()->axes[Y1].setScale (LINEARSCALE);
                              scaleType[axis]=0;
                        } else {
                              sp->coordinates()->axes[Y1].setScale (LOG10SCALE);
                              scaleType[axis]=1;
                        }
                  }
                  break;

            case 2:
                  majors=sp->coordinates()->axes[Z1].majors();
                  minors=sp->coordinates()->axes[Z1].minors();
                  sp->coordinates()->axes[Z1].limits(start,stop);
                  if (start != options[0].toDouble() || stop != options[1].toDouble())
                  {
                        start=options[0].toDouble();
                        stop=options[1].toDouble();
                        sp->coordinates()->axes[X1].limits(xl,xr);
                  sp->coordinates()->axes[Y1].limits(yl,yr);
                        if (d_func){
                              d_func->setMinZ(start);
                              d_func->setMaxZ(stop);
                              d_func->create ();
                              sp->createCoordinateSystem(Triple(xl, yl, start), Triple(xr, yr, stop));
                        } else if (d_surface){
                              d_surface->restrictRange (ParallelEpiped(Triple(xl, yl, start), Triple(xr, yr, stop)));
                              d_surface->create();
                              sp->createCoordinateSystem(Triple(xl, yl, start), Triple(xr, yr, stop));
                        } else
                              setScales(xl, xr, yl, yr, start, stop);
                        sp->legend()->setLimits(start,stop);
                  }

                  newMaj= options[2].toInt();
                  if (majors != newMaj ){
                        sp->coordinates()->axes[Z1].setMajors(newMaj);
                        sp->coordinates()->axes[Z2].setMajors(newMaj);
                        sp->coordinates()->axes[Z3].setMajors(newMaj);
                        sp->coordinates()->axes[Z4].setMajors(newMaj);
                  }

                  newMin = options[3].toInt();
                  if (minors != newMin){
                        sp->coordinates()->axes[Z1].setMinors(newMin);
                        sp->coordinates()->axes[Z2].setMinors(newMin);
                        sp->coordinates()->axes[Z3].setMinors(newMin);
                        sp->coordinates()->axes[Z4].setMinors(newMin);
                  }
                  if(st != options[4]){
                  if (options[4]=="0"){
                        sp->coordinates()->axes[Z1].setScale (LINEARSCALE);
                        scaleType[axis]=0;
                  } else {
                        sp->coordinates()->axes[Z1].setScale (LOG10SCALE);
                      scaleType[axis]=1;
                  }
              }
                  break;
      }
      update();
      emit modified();
}

void Graph3D::setScales(double xl, double xr, double yl, double yr, double zl, double zr)
{
      QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));

      if (d_matrix)
            updateScalesFromMatrix(xl, xr, yl, yr, zl, zr);
    else if (d_func){
        d_func->setDomain(xl, xr, yl, yr);
        d_func->setMinZ(zl);
        d_func->setMaxZ(zr);
        d_func->create ();
        sp->createCoordinateSystem(Triple(xl, yl, zl), Triple(xr, yr, zr));
    } else if (d_table){
            QString name = plotAssociation;

            int pos = name.find("_", 0);
            int posX = name.find("(", pos);
            QString xColName = name.mid(pos+1, posX-pos-1);
            int xCol = d_table->colIndex(xColName);

            pos = name.find(",", posX);
            posX = name.find("(", pos);
            QString yColName = name.mid(pos+1, posX-pos-1);
            int yCol = d_table->colIndex(yColName);

            if (name.endsWith("(Z)",true)){
                  pos = name.find(",",posX);
                  posX = name.find("(",pos);
                  QString zColName = name.mid(pos+1,posX-pos-1);
                  int zCol = d_table->colIndex(zColName);

                  loadData(d_table, xCol, yCol, zCol, xl, xr, yl, yr, zl, zr);
            } else if (name.endsWith("(Y)",true))
                  updateScales(xl, xr, yl, yr, zl, zr, xCol, yCol);
      }
    resetAxesLabels();
      QApplication::restoreOverrideCursor();
}

void Graph3D::updateScalesFromMatrix(double xl, double xr, double yl,
            double yr, double zl, double zr)
{
      double xStart = qMin(d_matrix->xStart(), d_matrix->xEnd());
      double xEnd = qMax(d_matrix->xStart(), d_matrix->xEnd());
      double yStart = qMin(d_matrix->yStart(), d_matrix->yEnd());
      double yEnd = qMax(d_matrix->yStart(), d_matrix->yEnd());

      double dx = fabs((xEnd - xStart)/double(d_matrix->numCols()-1));
      double dy = fabs((yEnd - yStart)/double(d_matrix->numRows()-1));

      int nc = int(fabs(xr - xl)/dx)+1;
      int nr = int(fabs(yr - yl)/dy)+1;

    double x_begin = qMin(xl, xr);
      double y_begin = qMin(yl, yr);

      double **data_matrix = Matrix::allocateMatrixData(nc, nr);
      for (int i = 0; i < nc; i++){
            double x = x_begin + i*dx;
            for (int j = 0; j < nr; j++){
                  double y = y_begin + j*dy;
                  if (x >= xStart && x <= xEnd && y >= yStart && y <= yEnd){
                        int k = abs((y - yStart)/dy);
                        int l = abs((x - xStart)/dx);
                        double val = d_matrix->cell(k, l);
                        if (val > zr)
                              data_matrix[i][j] = zr;
                        else if (val < zl)
                              data_matrix[i][j] = zl;
                        else
                              data_matrix[i][j] = val;
                  } else
                        data_matrix[i][j] = 0.0;
            }
      }
      sp->loadFromData(data_matrix, nc, nr, xl, xr, yl, yr);
      Matrix::freeMatrixData(data_matrix, nc);

      sp->createCoordinateSystem(Triple(xl, yl, zl), Triple(xr, yr, zr));
      sp->legend()->setLimits(zl, zr);
      sp->legend()->setMajors(legendMajorTicks);
      update();
}

void Graph3D::updateScales(double xl, double xr, double yl, double yr,double zl, double zr,
            int xcol, int ycol)
{
      int r=d_table->numRows();
      int xmesh=0, ymesh=2;
      double xv, yv;

      for (int i = 0; i < r; i++){
            if (!d_table->text(i,xcol).isEmpty() && !d_table->text(i,ycol).isEmpty()){
                  xv=d_table->cell(i,xcol);
                  if (xv >= xl && xv <= xr)
                        xmesh++;
            }
      }

      if (xmesh == 0)
            xmesh++;

      double **data = Matrix::allocateMatrixData(xmesh, ymesh);

      for (int j = 0; j < ymesh; j++){
            int k=0;
            for (int i = 0; i < r; i++){
                  if (!d_table->text(i,xcol).isEmpty() && !d_table->text(i,ycol).isEmpty()){
                        xv=d_table->cell(i,xcol);
                        if (xv >= xl && xv <= xr){
                              yv=d_table->cell(i,ycol);
                              if (yv > zr)
                                    data[k][j] = zr;
                              else if (yv < zl)
                                    data[k][j] = zl;
                              else
                                    data[k][j] = yv;
                              k++;
                        }
                  }
            }
      }

      sp->loadFromData(data, xmesh, ymesh, xl, xr, yl, yr);
      sp->createCoordinateSystem(Triple(xl, yl, zl), Triple(xr, yr, zr));
      Matrix::freeMatrixData(data, xmesh);
}

void Graph3D::setTicks(const QStringList& options)
{
      int min,maj;
      if (int(options.count()) == 6)
      {
            maj=options[0].toInt();
            sp->coordinates()->axes[X1].setMajors(maj);
            sp->coordinates()->axes[X2].setMajors(maj);
            sp->coordinates()->axes[X3].setMajors(maj);
            sp->coordinates()->axes[X4].setMajors(maj);

            min=options[1].toInt();
            sp->coordinates()->axes[X1].setMinors(min);
            sp->coordinates()->axes[X2].setMinors(min);
            sp->coordinates()->axes[X3].setMinors(min);
            sp->coordinates()->axes[X4].setMinors(min);

            maj=options[2].toInt();
            sp->coordinates()->axes[Y1].setMajors(maj);
            sp->coordinates()->axes[Y2].setMajors(maj);
            sp->coordinates()->axes[Y3].setMajors(maj);
            sp->coordinates()->axes[Y4].setMajors(maj);

            min=options[3].toInt();
            sp->coordinates()->axes[Y1].setMinors(min);
            sp->coordinates()->axes[Y2].setMinors(min);
            sp->coordinates()->axes[Y3].setMinors(min);
            sp->coordinates()->axes[Y4].setMinors(min);

            maj=options[4].toInt();
            sp->coordinates()->axes[Z1].setMajors(maj);
            sp->coordinates()->axes[Z2].setMajors(maj);
            sp->coordinates()->axes[Z3].setMajors(maj);
            sp->coordinates()->axes[Z4].setMajors(maj);

            min=options[5].toInt();
            sp->coordinates()->axes[Z1].setMinors(min);
            sp->coordinates()->axes[Z2].setMinors(min);
            sp->coordinates()->axes[Z3].setMinors(min);
            sp->coordinates()->axes[Z4].setMinors(min);
      }
      else
      {
            maj=options[1].toInt();
            sp->coordinates()->axes[X1].setMajors(maj);
            sp->coordinates()->axes[X2].setMajors(maj);
            sp->coordinates()->axes[X3].setMajors(maj);
            sp->coordinates()->axes[X4].setMajors(maj);

            min=options[2].toInt();
            sp->coordinates()->axes[X1].setMinors(min);
            sp->coordinates()->axes[X2].setMinors(min);
            sp->coordinates()->axes[X3].setMinors(min);
            sp->coordinates()->axes[X4].setMinors(min);

            maj=options[3].toInt();
            sp->coordinates()->axes[Y1].setMajors(maj);
            sp->coordinates()->axes[Y2].setMajors(maj);
            sp->coordinates()->axes[Y3].setMajors(maj);
            sp->coordinates()->axes[Y4].setMajors(maj);

            min=options[4].toInt();
            sp->coordinates()->axes[Y1].setMinors(min);
            sp->coordinates()->axes[Y2].setMinors(min);
            sp->coordinates()->axes[Y3].setMinors(min);
            sp->coordinates()->axes[Y4].setMinors(min);

            maj=options[5].toInt();
            sp->coordinates()->axes[Z1].setMajors(maj);
            sp->coordinates()->axes[Z2].setMajors(maj);
            sp->coordinates()->axes[Z3].setMajors(maj);
            sp->coordinates()->axes[Z4].setMajors(maj);

            min=options[6].toInt();
            sp->coordinates()->axes[Z1].setMinors(min);
            sp->coordinates()->axes[Z2].setMinors(min);
            sp->coordinates()->axes[Z3].setMinors(min);
            sp->coordinates()->axes[Z4].setMinors(min);
      }
}

void Graph3D::setMeshColor(const QColor& meshColor)
{
      if (meshCol != meshColor){
            sp->setMeshColor(Qt2GL(meshColor));
            meshCol=meshColor;
      }
}

void Graph3D::setAxesColor(const QColor& axesColor)
{
      if(axesCol != axesColor){
            sp->coordinates()->setAxesColor(Qt2GL(axesColor));
            axesCol=axesColor;
      }
}

void Graph3D::setNumbersColor(const QColor& numColor)
{
      if(numCol !=numColor){
            sp->coordinates()->setNumberColor(Qt2GL(numColor));
            numCol=numColor;
      }
}

void Graph3D::setLabelsColor(const QColor& labelColor)
{
      if(labelsCol !=labelColor){
            sp->coordinates()->setLabelColor(Qt2GL(labelColor));
            labelsCol=labelColor;
      }
}

void Graph3D::setBackgroundColor(const QColor& bgColor)
{
      if(bgCol !=bgColor){
            sp->setBackgroundColor(Qt2GL(bgColor));
            bgCol=bgColor;
      }
}

void Graph3D::setGridColor(const QColor& gridColor)
{
      if(gridCol !=gridColor){
            sp->coordinates()->setGridLinesColor(Qt2GL(gridColor));
            gridCol=gridColor;
      }
}

void Graph3D::setColors(const QStringList& colors)
{
      meshCol=QColor(colors[1]);
      sp->setMeshColor(Qt2GL(meshCol));

      axesCol=QColor(colors[2]);
      sp->coordinates()->setAxesColor(Qt2GL(axesCol));

      numCol=QColor(colors[3]);
      sp->coordinates()->setNumberColor(Qt2GL(numCol));

      labelsCol=QColor(colors[4]);
      sp->coordinates()->setLabelColor(Qt2GL(labelsCol));

      bgCol=QColor(colors[5]);
      sp->setBackgroundColor(Qt2GL(bgCol));

      gridCol=QColor(colors[6]);
      sp->coordinates()->setGridLinesColor(Qt2GL(gridCol));

      if ((int)colors.count()>7){
            QColor min=QColor(colors[7]);
            QColor max=QColor(colors[8]);
            alpha = colors[9].toDouble();
            if ((int)colors.count() == 11)
            setDataColorMap(colors[10]);
        else
                setDataColors(min,max);
      }
}

void Graph3D::scaleFonts(double factor)
{
      QFont font = sp->coordinates()->axes[X1].numberFont();
      font.setPointSizeFloat(font.pointSizeFloat()*factor);
      sp->coordinates()->setNumberFont (font);

      titleFnt.setPointSizeFloat(factor*titleFnt.pointSizeFloat());
      sp->setTitleFont(titleFnt.family(),titleFnt.pointSize(),titleFnt.weight(),titleFnt.italic());

      font = xAxisLabelFont();
      font.setPointSizeFloat(factor*font.pointSizeFloat());
      setXAxisLabelFont(font);

      font = yAxisLabelFont();
      font.setPointSizeFloat(factor*font.pointSizeFloat());
      setYAxisLabelFont(font);

      font = zAxisLabelFont();
      font.setPointSizeFloat(factor*font.pointSizeFloat());
      setZAxisLabelFont(font);
}

void Graph3D::moveSurfacePlot()
{
    // hack used to solve strange behavior of SurfacePlot on Mac OS X
      sp->hide();
      sp->show();
}

void Graph3D::resizeEvent ( QResizeEvent *e)
{
      QSize size=e->size();

      sp->makeCurrent();
      sp->resize(size);

      if (!ignoreFonts && this->isVisible()){
            QSize oldSize=e->oldSize();
            double ratio=(double)size.height()/(double)oldSize.height();
            scaleFonts(ratio);
      }

      sp->updateGL();
      emit resizedWindow(this);
      emit modified();
}

void Graph3D::contextMenuEvent(QContextMenuEvent *e)
{
      emit showContextMenu();
      e->accept();
}

void Graph3D::setFramed()
{
      if (sp->coordinates()->style() == FRAME)
            return;

      sp->makeCurrent();
      sp->setCoordinateStyle(FRAME);
}

void Graph3D::setBoxed()
{
      if (sp->coordinates()->style() == BOX)
            return;

      sp->makeCurrent();
      sp->setCoordinateStyle(BOX);
}

void Graph3D::setNoAxes()
{
      if (sp->coordinates()->style() == NOCOORD)
            return;

      sp->makeCurrent();
      sp->setCoordinateStyle(NOCOORD);
}

void Graph3D::setPolygonStyle()
{
      if (sp->plotStyle() == FILLED)
            return;

      sp->makeCurrent();
      sp->setPlotStyle(FILLED);
      sp->updateData();
      sp->updateGL();

      style_=FILLED;
      pointStyle = None;
}

void Graph3D::setFilledMeshStyle()
{
      if (sp->plotStyle() == FILLEDMESH)
            return;

      sp->makeCurrent();
      sp->setPlotStyle(FILLEDMESH);
      sp->updateData();
      sp->updateGL();

      style_=FILLEDMESH;
      pointStyle = None;
}

void Graph3D::setHiddenLineStyle()
{
      if (sp->plotStyle() == HIDDENLINE)
            return;

      sp->makeCurrent();
      sp->setPlotStyle(HIDDENLINE);
      sp->showColorLegend(false);
      sp->updateData();
      sp->updateGL();

      style_=HIDDENLINE;
      pointStyle = None;
      legendOn=false;
}

void Graph3D::setWireframeStyle()
{
      if (sp->plotStyle() == WIREFRAME)
            return;

      sp->makeCurrent();
      sp->setPlotStyle(WIREFRAME);
      sp->showColorLegend(false);
      sp->updateData();
      sp->updateGL();

      pointStyle = None;
      style_=WIREFRAME;
      legendOn=false;
}

void Graph3D::setDotStyle()
{
      pointStyle=Dots;
      style_=Qwt3D::USER;

      sp->makeCurrent();
      sp->setPlotStyle(Dot(d_point_size, d_smooth_points));
      sp->updateData();
      sp->updateGL();
}

void Graph3D::setConeStyle()
{
    QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));

      pointStyle=Cones;
      style_=Qwt3D::USER;

      sp->makeCurrent();
      sp->setPlotStyle(Cone3D(conesRad, conesQuality));
      sp->updateData();
      sp->updateGL();

      QApplication::restoreOverrideCursor();
}

void Graph3D::setCrossStyle()
{
      pointStyle=HairCross;
      style_=Qwt3D::USER;

      sp->makeCurrent();
      sp->setPlotStyle(CrossHair(crossHairRad, crossHairLineWidth,crossHairSmooth,crossHairBoxed));
      sp->updateData();
      sp->updateGL();
}

void Graph3D::clearData()
{
      if (d_matrix)
            d_matrix = 0;
      else if (d_table)
            d_table = 0;
      else if (d_func){
            delete d_func;
            d_func = 0;
      }
      plotAssociation = QString();

      sp->makeCurrent();
      sp->loadFromData (0, 0, 0, false, false);
      sp->updateData();
      sp->updateGL();
}

void Graph3D::setBarStyle()
{
      QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));

      pointStyle=VerticalBars;
      style_=Qwt3D::USER;

      sp->makeCurrent();
      sp->setPlotStyle(Bar(barsRad));
      sp->updateData();
      sp->updateGL();
      QApplication::restoreOverrideCursor();
}

void Graph3D::setFloorData()
{
      if (sp->floorStyle() == FLOORDATA)
            return;

      sp->makeCurrent();
      sp->setFloorStyle(FLOORDATA);
      sp->updateData();
      sp->updateGL();
}

void Graph3D::setFloorIsolines()
{
      if (sp->floorStyle() == FLOORISO)
            return;

      sp->makeCurrent();
      sp->setFloorStyle(FLOORISO);
      sp->updateData();
      sp->updateGL();
}

void Graph3D::setEmptyFloor()
{
      if (sp->floorStyle() == NOFLOOR)
            return;

      sp->makeCurrent();
      sp->setFloorStyle(NOFLOOR);
      sp->updateData();
      sp->updateGL();
}

void Graph3D::setMeshLineWidth(double lw)
{
      if (sp->meshLineWidth() == lw)
            return;

      sp->makeCurrent();
      sp->setMeshLineWidth(lw);
      sp->updateData();
      sp->updateGL();
}

int Graph3D::grids()
{
      return sp->coordinates()->grids();
}

void Graph3D::setGrid(Qwt3D::SIDE s, bool b)
{
      if (!sp)
            return;

      int sum = sp->coordinates()->grids();

      if (b)
            sum |= s;
      else
            sum &= ~s;

      sp->coordinates()->setGridLines(sum!=Qwt3D::NOSIDEGRID, false, sum);
      sp->updateGL();
      emit modified();
}

void Graph3D::setGrid(int grids)
{
      if (!sp)
            return;

      sp->coordinates()->setGridLines(true, false, grids);
}

void Graph3D::setLeftGrid(bool b)
{
      setGrid(Qwt3D::LEFT,b);
}
void Graph3D::setRightGrid(bool b)
{
      setGrid(Qwt3D::RIGHT,b);
}
void Graph3D::setCeilGrid(bool b)
{
      setGrid(Qwt3D::CEIL,b);
}
void Graph3D::setFloorGrid(bool b)
{
      setGrid(Qwt3D::FLOOR,b);
}
void Graph3D::setFrontGrid(bool b)
{
      setGrid(Qwt3D::FRONT,b);
}
void Graph3D::setBackGrid(bool b)
{
      setGrid(Qwt3D::BACK,b);
}

void Graph3D::print()
{
      QPrinter printer;
      printer.setOrientation(QPrinter::Landscape);
      printer.setColorMode (QPrinter::Color);
      printer.setFullPage(false);

      if (printer.setup())
      {
            if (IO::save (sp,"qtiplot.png","PNG"))
            {
                  QPixmap p;
                  p.load ("qtiplot.png","PNG", QPixmap::Color );

                  QPainter paint(&printer);
                  paint.drawPixmap(QPoint(0,0),p);
                  paint.end();

                  QFile f("qtiplot.png");
                  f.remove();
            }
            else
                  QMessageBox::about(0,tr("QtiPlot - IO Error"),
                              tr("Could not print: <h4>" + QString(name()) + "</h4>."));
      }
}

void Graph3D::copyImage()
{
    QApplication::clipboard()->setPixmap(sp->renderPixmap(), QClipboard::Clipboard);
    sp->updateData();
}

void Graph3D::exportImage(const QString& fileName, int quality, bool transparent)
{
      if (transparent){
        QPixmap pic = sp->renderPixmap();
        sp->updateData();

        QBitmap mask(pic.size());
            mask.fill(Qt::color1);
            QPainter p;
            p.begin(&mask);
            p.setPen(Qt::color0);

            QColor background = QColor (Qt::white);
            QRgb backgroundPixel = background.rgb ();
            QImage image = pic.convertToImage();
            for (int y=0; y<image.height(); y++){
                  for ( int x=0; x<image.width(); x++ ){
                        QRgb rgb = image.pixel(x, y);
                        if (rgb == backgroundPixel) // we want the frame transparent
                              p.drawPoint( x, y );
                  }
            }
            p.end();
            pic.setMask(mask);
            pic.save(fileName, 0, quality);
      } else {
        QImage im = sp->grabFrameBuffer(true);
        QImageWriter iw(fileName);
        iw.setQuality(quality);
        iw.write(im);
    }
}

void Graph3D::exportPDF(const QString& fileName)
{
      exportVector(fileName);
}

void Graph3D::exportVector(const QString& fileName)
{
      if ( fileName.isEmpty() ){
            QMessageBox::critical(this, tr("QtiPlot - Error"), tr("Please provide a valid file name!"));
        return;
      }

    QString format = "PDF";
    if (fileName.endsWith(".eps", Qt::CaseInsensitive))
        format = "EPS";
    else if (fileName.endsWith(".ps", Qt::CaseInsensitive))
        format = "PS";
      else if (fileName.endsWith(".svg", Qt::CaseInsensitive))
        format = "SVG";

    VectorWriter * gl2ps = (VectorWriter*)IO::outputHandler(format);
    if (gl2ps)
      gl2ps->setTextMode(VectorWriter::NATIVE);

    IO::save(sp, fileName, format);
}

void Graph3D::exportToFile(const QString& fileName)
{
      if ( fileName.isEmpty() ){
            QMessageBox::critical(this, tr("QtiPlot - Error"), tr("Please provide a valid file name!"));
        return;
      }

      if (fileName.contains(".eps") || fileName.contains(".pdf") ||
            fileName.contains(".ps") || fileName.contains(".svg")){
            exportVector(fileName);
            return;
      } else {
            QList<QByteArray> list = QImageWriter::supportedImageFormats();
      for(int i=0 ; i<list.count() ; i++){
                  if (fileName.contains( "." + list[i].toLower())){
                        exportImage(fileName);
                        return;
                  }
            }
      QMessageBox::critical(this, tr("QtiPlot - Error"), tr("File format not handled, operation aborted!"));
      }
}

02039 bool Graph3D::eventFilter(QObject *object, QEvent *e)
{
      if (e->type() == QEvent::MouseButtonDblClick && object == (QObject *)this->sp)
      {
            emit showOptionsDialog();
            return TRUE;
      }
      return MyWidget::eventFilter(object, e);
}

double Graph3D::barsRadius()
{
      if (sp->plotStyle() == Qwt3D::USER && sp->plotStyle() != Qwt3D::POINTS)
            return barsRad;
      else
            return 0.0;
}

void Graph3D::setBarRadius(double rad)
{
      if (barsRad == rad)
            return;

      barsRad = rad;
}

void Graph3D::setDotOptions(double size, bool smooth)
{
      d_point_size = size;
      d_smooth_points = smooth;
}

void Graph3D::setConeOptions(double rad, int quality)
{
      conesRad = rad;
      conesQuality = quality;
}

void Graph3D::setCrossOptions(double rad, double linewidth, bool smooth, bool boxed)
{
      crossHairRad = rad;
      crossHairLineWidth=linewidth;
      crossHairSmooth = smooth;
      crossHairBoxed = boxed;
}

void Graph3D::setStyle(const QStringList& st)
{
      if (st[1] =="nocoord")
            sp->setCoordinateStyle(NOCOORD);
      else if (st[1] =="frame")
            sp->setCoordinateStyle(FRAME);
      else if (st[1] =="box")
            sp->setCoordinateStyle(BOX);

      if (st[2] =="nofloor")
            sp->setFloorStyle(NOFLOOR);
      else if (st[2] =="flooriso")
            sp->setFloorStyle(FLOORISO);
      else if (st[2] =="floordata")
            sp->setFloorStyle(FLOORDATA);

      if (st[3] =="filledmesh")
            setFilledMeshStyle();
      else if (st[3] =="filled")
            setPolygonStyle();
      else if (st[3] =="points") {
            d_point_size = st[4].toDouble();
            d_smooth_points = false;
            if (st[5] == "1")
                  d_smooth_points = true;
            setDotStyle();
      } else if (st[3] =="wireframe")
            setWireframeStyle();
      else if (st[3] =="hiddenline")
            setHiddenLineStyle();
      else if (st[3] =="bars") {
            barsRad = (st[4]).toDouble();
            setBarStyle();
      } else if (st[3] =="cones") {
            conesRad = (st[4]).toDouble();
            conesQuality = (st[5]).toInt();
            setConeStyle();
      } else if (st[3] =="cross") {
            crossHairRad = (st[4]).toDouble();
            crossHairLineWidth = (st[5]).toDouble();
            crossHairSmooth=false;
            if (st[6] == "1")
                  crossHairSmooth=true;
            crossHairBoxed=false;
            if (st[7] == "1")
                  crossHairBoxed=true;
            setCrossStyle();
      }
}

void Graph3D::customPlotStyle(int style)
{
      sp->makeCurrent();
      if (sp->plotStyle() == style)
            return;

      switch (style)
      {
            case WIREFRAME  :
                  {
                        sp->setPlotStyle(WIREFRAME);
                        style_= WIREFRAME ;
                        pointStyle = None;

                        legendOn = false;
                        sp->showColorLegend(legendOn);
                        break;
                  }

            case FILLED :
                  {
                        sp->setPlotStyle(FILLED );
                        style_= FILLED;
                        pointStyle = None;
                        break;
                  }

            case FILLEDMESH  :
                  {
                        sp->setPlotStyle(FILLEDMESH);
                        style_= FILLEDMESH;
                        pointStyle = None;
                        break;
                  }

            case HIDDENLINE:
                  {
                        sp->setPlotStyle(HIDDENLINE);
                        style_= HIDDENLINE;
                        pointStyle = None;
                        legendOn = false;
                        sp->showColorLegend(legendOn);
                        break;
                  }

            case Qwt3D::POINTS:
                  {
                        d_point_size = 5;
                        d_smooth_points = true;
                        pointStyle=Dots;
                        style_ = Qwt3D::USER;

                        Dot d(d_point_size, d_smooth_points);
                        sp->setPlotStyle(d);
                        break;
                  }

            case Qwt3D::USER:
                  {
                        pointStyle = VerticalBars;
                        style_ = Qwt3D::USER;
                        sp->setPlotStyle(Bar(barsRad));
                        break;
                  }
      }

      sp->updateData();
      sp->updateGL();
}

void Graph3D::setRotation(double xVal, double yVal, double zVal)
{
      sp->setRotation(xVal, yVal, zVal);
}

void Graph3D::setZoom(double val)
{
    if (sp->zoom() == val)
        return;

    sp->setZoom(val);
}

void Graph3D::setScale(double  xVal, double  yVal, double  zVal)
{
    if (sp->xScale() == xVal && sp->yScale() == yVal && sp->zScale() == zVal)
        return;

      sp->setScale(xVal, yVal, zVal);
}

void Graph3D::setShift(double  xVal,double  yVal,double  zVal)
{
      sp->setShift(xVal, yVal, zVal);
}

Qwt3D::PLOTSTYLE Graph3D::plotStyle()
{
      return sp->plotStyle();
}

Qwt3D::FLOORSTYLE Graph3D::floorStyle()
{
      return sp->floorStyle();
}

Qwt3D::COORDSTYLE Graph3D::coordStyle()
{
      return sp->coordinates()->style();
}

QString Graph3D::formula()
{
      if (d_func)
            return d_func->function();
      else
            return plotAssociation;
}

QString Graph3D::saveToString(const QString& geometry, bool)
{
      QString s="<SurfacePlot>\n";
      s+= QString(name())+"\t";
      s+= birthDate() + "\n";
      s+= geometry;
      s+= "SurfaceFunction\t";

      sp->makeCurrent();
      if (d_func)
            s += d_func->function() + ";" + QString::number(d_func->columns()) + ";" + QString::number(d_func->rows()) + "\t";
      else if (d_surface){
            s += d_surface->xFormula() + "," + d_surface->yFormula() + "," + d_surface->zFormula() + ",";
            s += QString::number(d_surface->uStart(), 'e', 15) + ",";
            s += QString::number(d_surface->uEnd(), 'e', 15) + ",";
            s += QString::number(d_surface->vStart(), 'e', 15) + ",";
            s += QString::number(d_surface->vEnd(), 'e', 15) + ",";
            s += QString::number(d_surface->columns()) + ",";
            s += QString::number(d_surface->rows()) + ",";
            s += QString::number(d_surface->uPeriodic()) + ",";
            s += QString::number(d_surface->vPeriodic());
      } else {
            s += plotAssociation;
            s += "\t";
      }

      double start,stop;
      sp->coordinates()->axes[X1].limits(start,stop);
      s+=QString::number(start)+"\t";
      s+=QString::number(stop)+"\t";
      sp->coordinates()->axes[Y1].limits(start,stop);
      s+=QString::number(start)+"\t";
      s+=QString::number(stop)+"\t";
      sp->coordinates()->axes[Z1].limits(start,stop);
      s+=QString::number(start)+"\t";
      s+=QString::number(stop)+"\n";

      QString st;
      if (sp->coordinates()->style() == Qwt3D::NOCOORD)
            st="nocoord";
      else if (sp->coordinates()->style() == Qwt3D::BOX)
            st="box";
      else
            st="frame";
      s+="Style\t"+st+"\t";

      switch(sp->floorStyle ())
      {
            case NOFLOOR:
                  st="nofloor";
                  break;

            case FLOORISO:
                  st="flooriso";
                  break;

            case FLOORDATA:
                  st="floordata";
                  break;
      }
      s+=st+"\t";

      switch(sp->plotStyle())
      {
            case USER:
                  if (pointStyle == VerticalBars)
                        st="bars\t"+QString::number(barsRad);
                  else if (pointStyle == Dots){
                        st="points\t"+QString::number(d_point_size);
                        st+="\t"+QString::number(d_smooth_points);
                  } else if (pointStyle == Cones) {
                        st="cones\t"+QString::number(conesRad);
                        st+="\t"+QString::number(conesQuality);
                  } else if (pointStyle == HairCross) {
                        st="cross\t"+QString::number(crossHairRad);
                        st+="\t"+QString::number(crossHairLineWidth);
                        st+="\t"+QString::number(crossHairSmooth);
                        st+="\t"+QString::number(crossHairBoxed);
                  }
                  break;

            case WIREFRAME:
                  st="wireframe";
                  break;

            case HIDDENLINE:
                  st="hiddenline";
                  break;

            case FILLED:
                  st="filled";
                  break;

            case FILLEDMESH:
                  st="filledmesh";
                  break;

            default:
                  ;
      }
      s+=st+"\n";

      s+="grids\t";
      s+=QString::number(sp->coordinates()->grids())+"\n";

      s+="title\t";
      s+=title+"\t";
      s+=titleCol.name()+"\t";
      s+=titleFnt.family()+"\t";
      s+=QString::number(titleFnt.pointSize())+"\t";
      s+=QString::number(titleFnt.weight())+"\t";
      s+=QString::number(titleFnt.italic())+"\n";

      s+="colors\t";
      s+=meshCol.name()+"\t";
      s+=axesCol.name()+"\t";
      s+=numCol.name()+"\t";
      s+=labelsCol.name()+"\t";
      s+=bgCol.name()+"\t";
      s+=gridCol.name()+"\t";
      s+=fromColor.name()+"\t";
      s+=toColor.name()+"\t";
      s+=QString::number(alpha) + "\t" + color_map + "\n";

      s+="axesLabels\t";
      s+=labels.join("\t")+"\n";

      s+="tics\t";
      QStringList tl=scaleTicks();
      s+=tl.join("\t")+"\n";

      s+="tickLengths\t";
      tl=axisTickLengths();
      s+=tl.join("\t")+"\n";

      s+="options\t";
      s+=QString::number(legendOn)+"\t";
      s+=QString::number(sp->resolution())+"\t";
      s+=QString::number(labelsDist)+"\n";

      s+="numbersFont\t";
      QFont fnt=sp->coordinates()->axes[X1].numberFont();
      s+=fnt.family()+"\t";
      s+=QString::number(fnt.pointSize())+"\t";
      s+=QString::number(fnt.weight())+"\t";
      s+=QString::number(fnt.italic())+"\n";

      s+="xAxisLabelFont\t";
      fnt=sp->coordinates()->axes[X1].labelFont();
      s+=fnt.family()+"\t";
      s+=QString::number(fnt.pointSize())+"\t";
      s+=QString::number(fnt.weight())+"\t";
      s+=QString::number(fnt.italic())+"\n";

      s+="yAxisLabelFont\t";
      fnt=sp->coordinates()->axes[Y1].labelFont();
      s+=fnt.family()+"\t";
      s+=QString::number(fnt.pointSize())+"\t";
      s+=QString::number(fnt.weight())+"\t";
      s+=QString::number(fnt.italic())+"\n";

      s+="zAxisLabelFont\t";
      fnt=sp->coordinates()->axes[Z1].labelFont();
      s+=fnt.family()+"\t";
      s+=QString::number(fnt.pointSize())+"\t";
      s+=QString::number(fnt.weight())+"\t";
      s+=QString::number(fnt.italic())+"\n";

      s+="rotation\t";
      s+=QString::number(sp->xRotation())+"\t";
      s+=QString::number(sp->yRotation())+"\t";
      s+=QString::number(sp->zRotation())+"\n";

      s+="zoom\t";
      s+=QString::number(sp->zoom())+"\n";

      s+="scaling\t";
      s+=QString::number(sp->xScale())+"\t";
      s+=QString::number(sp->yScale())+"\t";
      s+=QString::number(sp->zScale())+"\n";

      s+="shift\t";
      s+=QString::number(sp->xShift())+"\t";
      s+=QString::number(sp->yShift())+"\t";
      s+=QString::number(sp->zShift())+"\n";

      s+="LineWidth\t";
      s+=QString::number(sp->meshLineWidth())+"\n";
      s+="WindowLabel\t" + windowLabel() + "\t" + QString::number(captionPolicy()) + "\n";
      s+="Orthogonal\t" + QString::number(sp->ortho())+"\n";
      s+="</SurfacePlot>\n";
      return s;
}

QString Graph3D::saveAsTemplate(const QString& geometryInfo)
{
      QString s = saveToString(geometryInfo);
      QStringList lst = s.split("\n", QString::SkipEmptyParts);
      QStringList l = lst[3].split("\t");
      l[1] = QString();
      lst[3] = l.join("\t");
      return lst.join("\n");
}

void Graph3D::showColorLegend(bool show)
{
      if (legendOn == show)
            return;

      sp->makeCurrent();
      sp->showColorLegend(show);

      legendOn=show;
      sp->updateGL();
      emit modified();
}

void Graph3D::setResolution(int r)
{
      if (sp->resolution() == r)
            return;

      sp->makeCurrent();
      sp->setResolution(r);
      sp->updateData();
      sp->updateGL();
      emit modified();
}

void Graph3D::setTitle(const QStringList& lst)
{
      title=lst[1];
      sp->setTitle(title);

      titleCol=QColor(lst[2]);
      sp->setTitleColor(Qt2GL(titleCol));

      titleFnt=QFont(lst[3],lst[4].toInt(),lst[5].toInt(),lst[6].toInt());
      sp->setTitleFont(titleFnt.family(),titleFnt.pointSize(),titleFnt.weight(),titleFnt.italic());
}

void Graph3D::setTitle(const QString& s,const QColor& color,const QFont& font)
{
      if (title != s){
            title=s;
            sp->setTitle(title);
      }

      titleCol=color;
      sp->setTitleColor(Qt2GL(color));

      if (titleFnt != font){
            titleFnt=font;
            sp->setTitleFont(font.family(),font.pointSize(),font.weight(),font.italic());
      }
}

void Graph3D::setTitleFont(const QFont& font)
{
      if (titleFnt != font)
      {
            titleFnt=font;
            sp->setTitleFont(font.family(),font.pointSize(),font.weight(),font.italic());
      }
}

void Graph3D::setOptions(const QStringList& lst)
{
      legendOn=false;
      if (lst[1].toInt() == 1)
            legendOn=true;
      sp->showColorLegend(legendOn);
      sp->setResolution(lst[2].toInt());
      setLabelsDistance(lst[3].toInt());
}


void Graph3D::setOptions(bool legend, int r, int dist)
{
      sp->showColorLegend(legend);
      legendOn = legend;
      sp->setResolution(r);
      setLabelsDistance(dist);
}

QColor Graph3D::minDataColor()
{
      return fromColor;
}

QColor Graph3D::maxDataColor()
{
      return toColor;
}

void Graph3D::setDataColors(const QColor& cMin, const QColor& cMax)
{
      if (cMin == fromColor && cMax == toColor)
            return;

      fromColor=cMin;
      toColor=cMax;

      Qwt3D::ColorVector cv;

      int size=255;
      double dsize = size;

      double r1=cMax.red()/dsize;
      double r2=cMin.red()/dsize;

      double stepR = (r1-r2)/dsize;

      double g1=cMax.green()/dsize;
      double g2=cMin.green()/dsize;

      double stepG = (g1-g2)/dsize;

      double b1=cMax.blue()/dsize;
      double b2=cMin.blue()/dsize;

      double stepB = (b1-b2)/dsize;

      RGBA rgb;
      for (int i=0; i<size; i++) {
            rgb.r = r1-i*stepR;
            rgb.g = g1-i*stepG;
            rgb.b = b1-i*stepB;
            rgb.a = alpha;

            cv.push_back(rgb);
      }

      col_ = new StandardColor(sp);
      col_->setColorVector(cv);
      sp->setDataColor(col_);

      if (legendOn) {
            sp->showColorLegend(false);
            sp->showColorLegend(legendOn);
      }
}

void Graph3D::changeTransparency(double t)
{
      if (alpha == t)
            return;

      alpha = t;

      Qwt3D::StandardColor* color=(StandardColor*) sp->dataColor ();
      color->setAlpha(t);

    sp->showColorLegend(legendOn);
      sp->updateData();
      sp->updateGL();
      emit modified();
}

void Graph3D::setTransparency(double t)
{
      if (alpha == t)
            return;

      alpha = t;

      Qwt3D::StandardColor* color=(StandardColor*) sp->dataColor ();
      color->setAlpha(t);
}

void Graph3D::showWorksheet()
{
      if (d_table)
            d_table->showMaximized();
      else if (d_matrix)
            d_matrix->showMaximized();
}

void Graph3D::setAntialiasing(bool smooth)
{
    sp->makeCurrent();
      sp->setSmoothMesh(smooth);
      sp->coordinates()->setLineSmooth(smooth);
      sp->updateData();
      sp->updateGL();
}

/*!
Turns 3D animation on or off
*/
02644 void Graph3D::animate(bool on)
{
if ( on )
    d_timer->start( animation_redraw_wait ); // Wait this many msecs before redraw
else
    d_timer->stop();
}

02652 void Graph3D::rotate()
{
if (!sp)
   return;

sp->setRotation(int(sp->xRotation() + 1) % 360, int(sp->yRotation() + 1) % 360, int(sp->zRotation() + 1) % 360);
}

void Graph3D::setDataColorMap(const QString& fileName)
{
if (color_map == fileName)
   return;

ColorVector cv;
if (!openColorMap(cv, fileName))
   return;

color_map = fileName;

col_ = new StandardColor(sp);
col_->setColorVector(cv);

sp->setDataColor(col_);
sp->updateData();
sp->showColorLegend(legendOn);
sp->updateGL();
}

bool Graph3D::openColorMap(ColorVector& cv, QString fname)
{
if (fname.isEmpty())
   return false;

using std::ifstream;
ifstream file(QWT3DLOCAL8BIT(fname));
if (!file)
   return false;

RGBA rgb;
cv.clear();

while ( file ) {
      file >> rgb.r >> rgb.g >> rgb.b;
      file.ignore(10000,'\n');
      if (!file.good())
         break;
      else {
          rgb.a = 1;
          rgb.r /= 255;
          rgb.g /= 255;
          rgb.b /= 255;
          cv.push_back(rgb);
          }
      }
return true;
}

void Graph3D::findBestLayout()
{
      double start, end;
      sp->coordinates()->axes[X1].limits (start, end);
      double xScale = 1/fabs(end-start);

      sp->coordinates()->axes[Y1].limits (start, end);
      double yScale = 1/fabs(end-start);

      sp->coordinates()->axes[Z1].limits (start, end);
      double zScale = 1/fabs(end-start);

      double d = (sp->hull().maxVertex-sp->hull().minVertex).length();
      sp->setScale(xScale, yScale, zScale);
      sp->setZoom(d/sqrt(3));

      double majl = 0.1/yScale;
      setAxisTickLength(0, majl, 0.6*majl);
      majl = 0.1/xScale;
      setAxisTickLength(1, majl, 0.6*majl);
      setAxisTickLength(2, majl, 0.6*majl);
}

void Graph3D::copy(Graph3D* g)
{
      if (!g)
        return;

      pointStyle = g->pointType();
      style_ = g->plotStyle();
      if (g->plotStyle() == Qwt3D::USER ){
            switch (pointStyle){
                  case None :
                        sp->setPlotStyle(g->plotStyle());
                  break;

                  case Dots :
                        d_point_size = g->pointsSize();
                        d_smooth_points = g->smoothPoints();
                        sp->setPlotStyle(Dot(d_point_size, d_smooth_points));
                  break;

                  case VerticalBars :
                        setBarRadius(g->barsRadius());
                        sp->setPlotStyle(Bar(barsRad));
                        break;

                  case HairCross :
                        setCrossOptions(g->crossHairRadius(), g->crossHairLinewidth(), g->smoothCrossHair(), g->boxedCrossHair());
                        sp->setPlotStyle(CrossHair(crossHairRad, crossHairLineWidth, crossHairSmooth, crossHairBoxed));
                        break;

                  case Cones :
                        setConeOptions(g->coneRadius(), g->coneQuality());
                        sp->setPlotStyle(Cone3D(conesRad, conesQuality));
                        break;
            }
      } else
            customPlotStyle(style_);

      sp->setCoordinateStyle(g->coordStyle());
      sp->setFloorStyle(g->floorStyle());

      setGrid(g->grids());
      setTitle(g->plotTitle(),g->titleColor(),g->titleFont());
      setTransparency(g->transparency());
      if (!g->colorMap().isEmpty())
            setDataColorMap(g->colorMap());
      else
            setDataColors(g->minDataColor(),g->maxDataColor());

      setMeshColor(g->meshColor());
      setAxesColor(g->axesColor());
      setNumbersColor(g->numColor());
      setLabelsColor(g->labelColor());
      setBackgroundColor(g->bgColor());
      setGridColor(g->gridColor());

      setAxesLabels(g->axesLabels());
      setTicks(g->scaleTicks());
      setTickLengths(g->axisTickLengths());
      setOptions(g->isLegendOn(), g->resolution(), g->labelsDistance());
      setNumbersFont(g->numbersFont());
      setXAxisLabelFont(g->xAxisLabelFont());
      setYAxisLabelFont(g->yAxisLabelFont());
      setZAxisLabelFont(g->zAxisLabelFont());
      setRotation(g->xRotation(),g->yRotation(),g->zRotation());
      setZoom(g->zoom());
      setScale(g->xScale(),g->yScale(),g->zScale());
      setShift(g->xShift(),g->yShift(),g->zShift());
      setMeshLineWidth(g->meshLineWidth());

      bool smooth = g->antialiasing();
    sp->setSmoothMesh(smooth);
      sp->coordinates()->setLineSmooth(smooth);

      setOrthogonal(g->isOrthogonal());

      sp->updateData();
      sp->updateGL();
      animate(g->isAnimated());
}

Graph3D::~Graph3D()
{
      if (d_surface)
            delete d_surface;
      if (d_func)
            delete d_func;

      delete sp;
}

Generated by  Doxygen 1.6.0   Back to index