Logo Search packages:      
Sourcecode: labplot version File versions

Plot.cc

// LabPlot : Plot.cc

#include <math.h>
#include <iostream>
#include <kdebug.h>
#include <klocale.h>
#include "Plot.h"
#include "Plot2DSurface.h"
#include "PlotQWT3D.h"

using namespace std;

//! general Plot class
Plot::Plot(Worksheet *w)
      : worksheet(w)
{
      graphlist = new GraphList();

      bgcolor = QColor(Qt::white);
      gbgcolor = QColor(Qt::white);

      // title (richtext title)
      title = new Label(i18n("Title"),QFont(QString("Adobe Times"),22),QColor(Qt::black));
      title->setPosition(0.4,0.04);

      position.setPoint(0.0,0.0);
      size.setPoint(1.0,1.0);
      p1.setPoint(.11,.15);
      p2.setPoint(.95,.85);

      baseline=0;
      baseline_enabled=0;

      region.setMin(0);
      region.setMax(0);
      region_enabled=1;

      transparent=false;
      clipoffset=10;
}

void Plot::drawStyle(QPainter *p, Style style, int oldx, int oldy, int x, int y,int xmin, int xmax,int ymin, int ymax) {
      bool filled = style.isFilled();
      QColor c = style.FillColor();
      QPen pen( style.Color(), style.Width(),(Qt::PenStyle)style.PenStyle() );
      p->setPen(pen);
      QBrush brush(c,(Qt::BrushStyle)style.Brush());

      // dont draw outside border
      // prevent drawing errors with too large coordinates
      if(oldy>ymax && y>ymax || oldy<ymin && y<ymin)
            return;
      if(oldx>xmax && x>xmax || oldx<xmin && x<xmin)
            return;

        // calculate baseline
        double min = actrange[1].rMin();
      double max = actrange[1].rMax();

      int basey = ymax - (int) ((baseline-min)/(max-min)*(double)(ymax-ymin));
      //kdDebug()<<"BASELINE= "<<baseline<<endl;
      //kdDebug()<<"BASEY = "<<basey<<endl;

      switch(style.Type()) {
            case 0:     // line
                  if (filled) {
                        p->setPen(Qt::NoPen);
                        p->setBrush(brush);
                        QPointArray a;
                        a.setPoints(4,oldx,oldy,x,y,x,basey,oldx,basey);
                        p->drawPolygon(a);
                        p->setPen(pen);
                  }
                  p->drawLine(oldx, oldy, x, y);
                  break;
            case 2:     // steps    : only for 2d
                  if (filled) {
                        p->fillRect(oldx,oldy,(x+oldx)/2-oldx,basey-oldy,brush);
                        p->fillRect((x+oldx)/2,y,x-(x+oldx)/2,basey-y,brush);
                  }
                  p->drawLine(oldx,oldy,(oldx+x)/2,oldy);
                  p->drawLine((oldx+x)/2,oldy,(oldx+x)/2,y);
                  p->drawLine((oldx+x)/2,y,x,y);
                  break;
            case 3:     // boxes    : only for 2d
                  if (filled) {
                        p->fillRect(oldx,oldy,(x+oldx)/2-oldx,basey-oldy,brush);
                        p->fillRect((x+oldx)/2,y,x-(x+oldx)/2,basey-y,brush);
                  }
                  p->drawLine(oldx,oldy,(oldx+x)/2,oldy);
                  p->drawLine((oldx+x)/2,oldy,(oldx+x)/2,y);
                  p->drawLine((oldx+x)/2,oldy,(oldx+x)/2,basey);
                  p->drawLine((oldx+x)/2,y,x,y);
                  break;
            case 4:     // impulses : only for 2d
                  p->drawLine(oldx,oldy,oldx,basey);
                  break;
      }
}

//! draw errorbars for x-y-dy, x-y-dx-dy and x-y-dy1-dy2
// at (x,y) from xleft to xright and ybottom to ytop
void Plot::drawErrorBar(QPainter *p, int x, int y,int xleft, int xright, int ytop,int ybottom) {
      if (xleft != x) {
            p->drawLine(xleft,y,x,y);
            p->drawLine(xleft,y-2,xleft,y+2);
      }
      if (xright != x) {
            p->drawLine(x,y,xright,y);
            p->drawLine(xright,y-2,xright,y+2);
      }
      if (ytop != y) {
            p->drawLine(x,y,x,ytop);
            p->drawLine(x-2,ytop,x+2,ytop);
      }
      if (ybottom != y) {
            p->drawLine(x,y,x,ybottom);
            p->drawLine(x-2,ybottom,x+2,ybottom);
      }
}

void Plot::save(QTextStream *t) {
      *t<<bgcolor.name()<<endl;
      *t<<gbgcolor.name()<<endl;
      *t<<transparent<<endl;
      *t<<clipoffset<<endl;

      for (int i=0;i<3;i++)
            *t<<actrange[i].rMin()<<' '<<actrange[i].rMax()<<endl;

      //save region
      *t<<region.rMin()<<' '<<region.rMax()<<' '<<region_enabled<<endl;

      *t<<position.X()<<' '<<position.Y()<<endl;
      *t<<size.X()<<' '<<size.Y()<<endl;
      *t<<p1.X()<<' '<<p1.Y()<<endl;
      *t<<p2.X()<<' '<<p2.Y()<<endl;

      title->save(t);
      legend.save(t);
      saveAxes(t);

      if (type == PSURFACE) {
            Plot2DSurface *plot = (Plot2DSurface *)this;
            *t<<plot->densityEnabled()<<' '<<plot->contourEnabled()<<endl;
            *t<<plot->Number()<<' '<<plot->Palette()<<endl;
            *t<<plot->ContourColor().name()<<endl;
            *t<<plot->Mesh()<<' '<<plot->ColoredContour()<<' '<<plot->Brush()<<' ';
            *t<<plot->Relative()<<' '<<plot->Threshold()<<endl;
      }
      else if (type == PQWT3D) {
            PlotQWT3D *plot = (PlotQWT3D *)this;
            
            *t<<(int) plot->PlotStyle()<<endl;
            *t<<(int) plot->CoordinateStyle()<<endl;
            *t<<(int) plot->FloorStyle()<<endl;
            *t<<(int) plot->aspectRatio()<<endl;
            *t<<plot->isolines()<<endl;

            Qwt3D::ColorVector cv = plot->getColorVector();
            *t<<cv.size()<<endl;
            for(unsigned int i=0;i<cv.size();i++)
                  *t<<cv[i].r<<' '<<cv[i].g<<' '<<cv[i].b<<' '<<cv[i].a<<endl;
      }

      // dump graphs
      unsigned int i;
      for (i=0;i < graphlist->getNumber();i++) {
            switch (graphlist->getStruct(i)) {
            case GRAPH2D:
                  *t<<"Graph2D "<<i<<endl;
                  graphlist->getGraph2D(i)->save(t);
                  break;
            case GRAPH3D:
                  *t<<"Graph3D "<<i<<endl;
                  graphlist->getGraph3D(i)->save(t);
                  break;
            case GRAPHM:
                  *t<<"GraphM "<<i<<endl;
                  graphlist->getGraphM(i)->save(t);
                  break;
            case GRAPHGRASS:
                  *t<<"GraphGRASS "<<i<<endl;
                  graphlist->getGraphGRASS(i)->save(t);
                  break;
            case GRAPHVTK:
                  *t<<"GraphVTK "<<i<<endl;
                  graphlist->getGraphVTK(i)->save(t);
                  break;
            case GRAPH4D:
                  *t<<"Graph4D "<<i<<endl;
                  graphlist->getGraph4D(i)->save(t);
                  break;
            case GRAPHIMAGE:
                  *t<<"GraphIMAGE "<<i<<endl;
                  graphlist->getGraphIMAGE(i)->save(t);
                  break;
            }
      }
      *t<<"EOG "<<i<<endl;
}

void Plot::open(QTextStream *t, int version) {
      kdDebug()<<"Plot::open()"<<endl;

      QString family, color;
      double x,y;

      *t>>color;
      bgcolor = QColor(color);
      if(version > 3) {
            *t>>color;
            gbgcolor = QColor(color);

            // not used in newer versions
            if (version<11)
                  *t>>x>>x>>x>>x;
            else {
                  int tmp;
                  *t>>tmp;
                  transparent = (bool) tmp;
                  if(version>13) {
                        *t>>clipoffset;
                  }
            }

            for (int i=0;i<3;i++) {
                  *t>>x>>y;   // means min / max
                  actrange[i].setMin(x);
                  actrange[i].setMax(y);
                  kdDebug()<<"Range"<<i<<" min/max = "<<x<<' '<<y<<endl;
            }

            //region
            if (version>9) {
                  int e;
                  *t>>x>>y>>e;
                  region.setMin(x);
                  region.setMax(y);
                  region_enabled=e;
                  kdDebug()<<"Region : "<<x<<' '<<y<<' '<<e<<endl;
            }

            // position & size
            if(version>10) {
                  *t>>x>>y;
                  position.setPoint(x,y);
                  *t>>x>>y;
                  size.setPoint(x,y);
                  *t>>x>>y;
                  p1.setPoint(x,y);
                  *t>>x>>y;
                  p2.setPoint(x,y);
            }
            else {
                  position.setPoint(0,0);
                  size.setPoint(1,1);
                  p1.setPoint(.11,.15);
                  p2.setPoint(.95,.85);
            }
      }

      // title
      kdDebug()<<"Opening title ..."<<endl;
      title->open(t,version);

      // legend
      kdDebug()<<"Opening legend ..."<<endl;
      legend.open(t,version);

      // axes
      kdDebug()<<"Opening axes ..."<<endl;
      openAxes(t,version);

      // plot type specific stuff
      if (type == PSURFACE && version > 5) {
            Plot2DSurface *plot = (Plot2DSurface *)this;
            int de, ce, n, p;
            QString tmp;
            *t>>de>>ce;
            plot->enableDensity(de);
            plot->enableContour(ce);
            *t>>n>>p;
            plot->setNumber(n);
            plot->setPalette(p);
            if (version>12) {
                  *t>>tmp;
                  plot->setContourColor(QColor(tmp));
                  *t>>de>>ce>>n>>p>>tmp;
                  plot->setMesh(de);
                  plot->setColoredContour(ce);
                  plot->setBrush(n);
                  plot->setRelative(p);
                  plot->setThreshold(tmp.toDouble());
            }
      }
      else if (type == PQWT3D && version > 17) {
            PlotQWT3D *plot = (PlotQWT3D *)this;
            int style;
            *t>>style;
            plot->setPlotStyle((Qwt3D::PLOTSTYLE) style);
            *t>>style;
            plot->setCoordinateStyle((Qwt3D::COORDSTYLE) style);
            *t>>style;
            plot->setFloorStyle((Qwt3D::FLOORSTYLE) style);
            *t>>style;
            plot->setAspectRatio((bool)style);
            *t>>style;
            plot->setIsolines(style);
            
            //read colorvector
            Qwt3D::ColorVector cv;
            cv.clear();
            Qwt3D::RGBA rgb;
            
            int size;
            *t>>size;
            for(int i=0;i<size;i++) {
                  *t >> rgb.r >> rgb.g >> rgb.b>>rgb.a;
                  cv.push_back(rgb);
            }
            plot->setColorVector(cv);
      }

      // get the data
      QString gstring;
      kdDebug()<<"Opening Graph ..."<<endl;

      int n;
      *t>>gstring>>n;
      kdDebug()<<"string = "<<gstring<<" / n = "<<n<<endl;
      while (!strncmp("Graph",gstring,5) ) {
            kdDebug()<<" GRAPH "<<gstring<<' '<<n<<endl;

            if (gstring == "Graph2D") {
                  Graph2D *g = new Graph2D();
                  g->open(t,version);
                  worksheet->addGraph2D(g);
            }
            else if (gstring == "Graph3D") {
                  Graph3D *g = new Graph3D();
                  g->open(t,version);
                  worksheet->addGraph3D(g);
            }
            else if (gstring == "Graph4D") {
                  Graph4D *g = new Graph4D();
                  g->open(t,version);
                  worksheet->addGraph4D(g);
            }
            else if (gstring == "GraphM") {
                  GraphM *g = new GraphM();
                  g->open(t,version);
                  worksheet->addGraphM(g,type);
            }
            else if (gstring == "GraphGRASS") {
                  GraphGRASS *g = new GraphGRASS();
                  g->open(t,version);
                  worksheet->addGraphGRASS(g);
            }
            else if (gstring == "GraphVTK") {
                  GraphVTK *g = new GraphVTK();
                  g->open(t,version);
                  worksheet->addGraphVTK(g);
            }
            else if (gstring == "GraphIMAGE") {
                  GraphIMAGE *g = new GraphIMAGE();
                  g->open(t,version);
                  worksheet->addGraphIMAGE(g);
            }
            *t>>gstring>>n;
            kdDebug()<<" GRAPH LINE :  "<<gstring<<' '<<n<<endl;
      }
      kdDebug()<<"Plot::open() OK"<<endl;
}

// called from Plot<Type> with all axes
void Plot::saveAxis(QTextStream *t,Axis *axis,int gridenabled, int borderenabled, int minorgridenabled) {
      *t<<axis->Scale()<<endl;

      //Grid & Border
      *t<<gridenabled<<' '<<borderenabled<<' '<<axis->enabled()<<endl;
      *t<<minorgridenabled<<endl;
      *t<<axis->GridColor().name()<<endl;

      axis->label()->save(t);

      *t<<axis->TicsPos()<<endl;
      *t<<axis->Scaling()<<' '<<axis->Shift()<<endl;
      *t<<axis->TicsLabelPrefix()<<endl;
      *t<<axis->TicsLabelSuffix()<<endl;
      *t<<axis->TicsLabelRotation()<<endl;
      *t<<axis->TicsLabelGap()<<endl;

      //Tics
      QFont tf = axis->TicsFont();
      *t<<tf.family()<<endl;
      *t<<tf.pointSize()<<' '<<tf.weight()<<' '<<tf.italic()<<endl;
      *t<<axis->MajorTics()<<' '<<axis->MinorTics()<<endl;
      *t<<axis->MajorTicsEnabled()<<' '<<axis->MinorTicsEnabled()<<endl;
      *t<<axis->TicsColor().name()<<endl;
      *t<<axis->TicsLabelColor().name()<<endl;
      *t<<axis->BorderColor().name()<<endl;
      *t<<axis->TicsLabelFormat()<<endl;
      *t<<axis->TicsLabelPrecision()<<endl;
      *t<<axis->DateTimeFormat()<<endl;
}

// called from Plot<Type> with all axes
void Plot::openAxis(QTextStream *t,int version,Axis *axis,bool *gridenabled,bool *borderenabled, bool *minorgridenabled) {
      QString family, color;
      int pointsize, weight, italic;
      double x,y;

      QString l;
      int major,minor;
      int majore,minore;
      int ge,be,e;
      int boxed=0;
      double rotation=0;

      int s=0;
      if(version > 7)
            *t>>s;
      axis->setScale((TScale)s);

      *t>>ge>>be>>e;
      *gridenabled=ge;
      *borderenabled=be;
      if(version > 14) {
            *t>>ge;
            *minorgridenabled=ge;
      }

      kdDebug()<<"GRID  enabled : "<<*gridenabled<<endl;
      kdDebug()<<"BORDER enabled : "<<*borderenabled<<endl;

      axis->enable(e);
      if (version > 3) {
            *t>>color;
            axis->setGridColor(QColor(color));
      }
      l=t->readLine();  // needed. don't know why ...

      // open axis label
      l=t->readLine();

      kdDebug()<<"Label = "<<l<<endl;

      if (version > 6) {      // new order
            family=t->readLine();
            *t>>pointsize>>weight>>italic;
            *t>>color;
            *t>>x>>y;
            if(version > 8)
                  *t>>boxed;
            if(version > 16)
                  *t>>rotation;
      }
      else if (version > 3) {
            *t>>color;
            *t>>x>>y;
            axis->label()->setPosition(x,y);

            t->readLine();
            family=t->readLine();
            *t>>pointsize>>weight>>italic;
      }
      else {
            *t>>family>>pointsize>>weight>>italic;
      }

      kdDebug()<<"axis (Font) "<<family<<' '<<pointsize<<endl;

      Label *label = new Label(l,QFont(family,pointsize,weight,italic),QColor(color));
      label->setPosition(x,y);
      label->setBoxed(boxed);
      label->setRotation(rotation);
      axis->setLabel(label);

      if (version > 10) {
            *t>>x;
            axis->setTicsPos((int)x);
            kdDebug()<<"TIC POSITION = "<<x<<endl;
            *t>>x>>y;
            axis->setScaling(x);
            axis->setShift(y);
            t->readLine();
            QString tmpprefix=t->readLine();
            axis->setTicsLabelPrefix(tmpprefix);
            kdDebug()<<"Prefix = "<<tmpprefix<<endl;
            QString tmpsuffix=t->readLine();
            axis->setTicsLabelSuffix(tmpsuffix);
            kdDebug()<<"Suffix = "<<tmpsuffix<<endl;
            if(version > 14) {
                  *t>>x;
                  axis->setTicsLabelRotation(x);
                  if(version > 16) {
                        *t>>x;
                        axis->setTicsLabelGap((int)x);
                  }
                  t->readLine();
            }
      }

      // tics
      if (version > 3) {
            if (version<11)
                  t->readLine();
            family=t->readLine();
            *t>>pointsize>>weight>>italic;
            axis->setTicsFont( QFont(family,pointsize,weight,italic));
      }

      kdDebug()<<"axis (Tics) "<<family<<pointsize<<endl;

      *t>>major>>minor;
      axis->setMajorTics(major);
      axis->setMinorTics(minor);
      *t>> majore>>minore;
      axis->enableMajorTics(majore);
      axis->enableMinorTics(minore);
      if (version > 3) {
            *t>>color;
            axis->setTicsColor(QColor(color));
            *t>>color;
            axis->setTicsLabelColor(QColor(color));
            *t>>color;
            axis->setBorderColor(QColor(color));
      }
      if (version > 4) {
            int tmp;
            *t>>tmp;
            axis->setTicsLabelFormat((TFormat)tmp);
            *t>>tmp;
            axis->setTicsLabelPrecision(tmp);
      }
      if(version >11) {
            QString tmp;
            t->readLine();
            tmp = t->readLine();
            axis->setDateTimeFormat(tmp);
      }

      kdDebug()<<"OK Axis : "<<l<<endl;
}

//! build the tic label string according to atlf
QString Plot::TicLabel(int axisnr, int atlf, int prec, QString dtf, double value) {
      QString label;
      
      switch(atlf) {
      case AUTO:
            label = QString::number(value,'g',prec);
            break;
      case NORMAL:
            label = QString::number(value,'f',prec);
            break;
      case SCIENTIFIC:
            label = QString::number(value,'e',prec);
            break;
      case POWER10:
            label = "10<span style=\"vertical-align:super\">"+ QString::number(log10(value),'g',prec)+"</span>";
            break;
      case POWER2:
            label = "2<span style=\"vertical-align:super\">"+ QString::number(log2(value),'g',prec)+"</span>";
            break;
      case POWERE:
            label = "e<span style=\"vertical-align:super\">"+ QString::number(log(value),'g',prec)+"</span>";
            break;
      case FSQRT:
            label = "sqrt("+ QString::number(value*value,'g',prec) + ")";
            break;
      case TIME: {
            QTime time;
            time=time.addMSecs((int) (value*1000));
                  
            QString format;
            if(fabs(value)<1)
                  format="z";
            else if(fabs(value)<10) {
                  format="s.zzz";
                  if (prec==0)
                        format="s";
                  else if (prec==1) {
                        // round to 100 ms
                        int ms=time.msec();
                        time=time.addMSecs(-ms);
                        ms = 100*(int)rint(ms/100);
                        time=time.addMSecs(ms);
                  }
                  else if (prec==2) {
                        // round to 10 ms
                        int ms=time.msec();
                        time=time.addMSecs(-ms);
                        ms = 10*(int)rint(ms/10);
                        time=time.addMSecs(ms);
                  }
            }
            else if (fabs(value)<3600) {
                  format = "m:ss";
                  if (prec==0) {
                        int s=time.second();
                        // round to full minute
                        time=time.addSecs(-s);
                        if(s>=30)
                              time=time.addSecs(60);
                        format="m";
                  }
                  else if (prec==1) {
                        // round to 10 seconds
                        int s=time.second();
                        time=time.addSecs(-s);
                        s = 10*(int)rint(s/(int)10);
                        time=time.addSecs(s);
                  }
            }
            else {
                  // TODO : round minutes
                  format="h:mm:ss";
            }
                  
            // overwrite auto format
            if (dtf != i18n("auto"))
                  format = dtf;
                  label=time.toString(format);
            kdDebug()<<"VALUE in Time Format : "<<label<<endl;
            }
            break;
      case DATE: {
            QDate date(1970,1,1);
            date=date.addDays((int) value);
            QString format("dd.MM.yyyy");
            if (dtf != i18n("auto"))
                  format = dtf;
                  label=date.toString(format);
                  kdDebug()<<"VALUE in Date Format ( "<<format;
                  kdDebug()<<") : "<<label<<endl;
            }
            break;
      case DATETIME: {
            QDate date(1970,1,1);
            QDateTime datetime(date);
//          kdDebug()<<"value = "<<(int) value<<endl;
            datetime=datetime.addSecs((int)value);
            QString format("dd.MM.yyyy h:mm:ss");
            if (dtf != i18n("auto"))
                  format = dtf;
            label = datetime.toString(format);
//          kdDebug()<<"VALUE in DateTime Format ( "<<format<<") : "<<label<<endl;
            }
            break;
      case DEGREE:
            label = QString::number(180/M_PI*value,'f',prec)+'';
            break;
      }

      return label;
}

Generated by  Doxygen 1.6.0   Back to index