Logo Search packages:      
Sourcecode: labplot version File versions

Plot3D.cc

// LabPlot : Plot3D.cc

#include <iostream>
#include <klocale.h>
#include <kdebug.h>
#include "Plot3D.h"

using namespace std;

//! general 3D Plot class
Plot3D::Plot3D(Worksheet *p)
      : Plot(p) 
{
      title = new Label(i18n("Title 3D"),QFont("Adobe Times",22),QColor(Qt::black));
      title->setPosition(0.4,0.04);

      axis[0].setLabel(new Label(i18n("x-Axis")));
      axis[1].setLabel(new Label(i18n("y-Axis")));
      axis[2].setLabel(new Label(i18n("z-Axis")));
      axis[3].setLabel(new Label(i18n("x2-Axis")));
      axis[4].setLabel(new Label(i18n("y2-Axis")));
      axis[5].setLabel(new Label(i18n("z2-Axis")));
      axis[6].setLabel(new Label(i18n("x3-Axis")));
      axis[7].setLabel(new Label(i18n("y3-Axis")));
      axis[8].setLabel(new Label(i18n("z3-Axis")));
      axis[9].setLabel(new Label(i18n("x4-Axis")));
      axis[10].setLabel(new Label(i18n("y4-Axis")));
      axis[11].setLabel(new Label(i18n("z4-Axis")));

      // grid & border
      for (int i=0;i<12;i++) {
            borderenabled[i] = TRUE;
            axis[i].enable(1);
      }
      for (int i=3;i<12;i++)
            axis[i].enable(0);
      for (int i=0;i<24;i++)
            gridenabled[i] = FALSE;
}

QStringList Plot3D::Info() {
      QStringList s;
      s<<"3D";
      s<<QString::number(position.X())+QString(" , ")+QString::number(position.Y());
      s<<QString::number(size.X())+QString(" X ")+QString::number(size.Y());
      if (transparent)
            s<<QString("yes");
      else
            s<<QString("no");
      s<<bgcolor.name();
      s<<gbgcolor.name();

      return s;
}

void Plot3D::setBorder(int item, bool on) {
      const int unit = 5, numunit = 40, numunit2 = 20;
      int w = worksheet->width(), h = worksheet->height();

      int xmin = (int)(w*(size.X()*p1.X()+position.X()));
      int xmax = (int)(w*(size.X()*p2.X()+position.X()));
      int ymin = (int)(h*(size.Y()*p1.Y()+position.Y()));
      int ymax = (int)(h*(size.Y()*p2.Y()+position.Y()));

      if(item == 3) {
            if (on) {
                  if (axis[3].label()->title().length() > 0) ymax -= axis[3].label()->font().pointSize();
                  if (axis[3].MajorTicsEnabled())   ymax -= unit+numunit2;
                  if (axis[3].MinorTicsEnabled())   ymax -= unit;
            }
            else {
                  if (axis[3].label()->title().length() > 0) ymax += axis[3].label()->font().pointSize();
                  if (axis[3].MajorTicsEnabled())   ymax += unit+numunit2;
                  if (axis[3].MinorTicsEnabled())   ymax += unit;

            }
      }
      if(item == 5) {
            if (on) {
                  if (axis[5].label()->title().length() > 0) xmin += axis[5].label()->font().pointSize();
                  if (axis[5].MajorTicsEnabled())   xmin += unit+numunit;
                  if (axis[5].MinorTicsEnabled())   xmin += unit;
            }
            else {
                  if (axis[5].label()->title().length() > 0) xmin -= axis[5].label()->font().pointSize();
                  if (axis[5].MajorTicsEnabled())   xmin -= unit+numunit;
                  if (axis[5].MinorTicsEnabled())   xmin -= unit;
            }
      }
      if(item == 9) {
            if (on) {
                  if (axis[9].label()->title().length() > 0) ymin += axis[9].label()->font().pointSize();
                  if (axis[9].MajorTicsEnabled())   ymin += unit+numunit2;
                  if (axis[9].MinorTicsEnabled())   ymin += unit;
            }
            else {
                  if (axis[9].label()->title().length() > 0) ymin += axis[9].label()->font().pointSize();
                  if (axis[9].MajorTicsEnabled())   ymin += unit+numunit2;
                  if (axis[9].MinorTicsEnabled())   ymin += unit;
            }
      }
      if(item == 11) {
            if (on) {
                  if (axis[11].label()->title().length() > 0) xmax -= axis[11].label()->font().pointSize();
                  if (axis[11].MajorTicsEnabled())   xmax -= unit+numunit;
                  if (axis[11].MinorTicsEnabled())   xmax -= unit;
            }
            else {
                  if (axis[11].label()->title().length() > 0) xmax += axis[11].label()->font().pointSize();
                  if (axis[11].MajorTicsEnabled())   xmax += unit+numunit;
                  if (axis[11].MinorTicsEnabled())   xmax += unit;
            }
      }

      setXMin(xmin,w);
      setXMax(xmax,w);
      setYMin(ymin,h);
      setYMax(ymax,h);
}

void Plot3D::draw(QPainter *p,int w, int h) {
      //int w = worksheet->width(), h = worksheet->height();

      kdDebug()<<"Plot3D::draw() w/h : "<<w<<' '<<h<<endl;
      int xmin = (int)(w*(size.X()*p1.X()+position.X()));
      int xmax = (int)(w*(size.X()*p2.X()+position.X()));
      int ymin = (int)(h*(size.Y()*p1.Y()+position.Y()));
      int ymax = (int)(h*(size.Y()*p2.Y()+position.Y()));

      // 3d perspective
      xmax -= (xmax-xmin)/3;
      ymin += (ymax-ymin)/3;

      kdDebug()<<"XMIN/MXAX/YMIN/YMAX = "<<xmin<<','<<xmax<<','<<ymin<<','<<ymax<<endl;
      kdDebug()<<"p1 = "<<p1.X()<<'/'<<p1.Y()<<" p2 = "<<p2.X()<<'/'<<p2.Y()<<endl;

      if (!transparent) {
            // background color
            p->setBrush(bgcolor);
            p->setPen(Qt::NoPen);
            p->drawRect((int)(w*position.X()),(int)(h*position.Y()),(int)(w*size.X()),(int)(h*size.Y()));

            // graph background color
            p->setBrush(gbgcolor);
            //TEST : p->setBrush(Qt::green);
            p->setPen(Qt::NoPen);
      }

      QPointArray a;
      a.setPoints( 6, xmin,ymax,xmax,ymax,
            xmax+(xmax-xmin)/2,(ymax+ymin)/2,xmax+(xmax-xmin)/2,ymin-(ymax-ymin)/2,
            (xmax+xmin)/2,ymin-(ymax-ymin)/2,xmin,ymin);
      p->drawPolygon(a);

        // TODO : draw baseline here (before every axis ?) -> see Plot2D.cc

      // TODO
      kdDebug()<<"PLOT3D : title->draw() pos:"<<position.X()<<' '<<position.Y()<<endl;
      kdDebug()<<"                  size:"<<size.X()<<' '<<size.Y()<<endl;
      title->draw(p,position,size,w,h,0);

      drawAxes(p,w,h,0);      // all axes & borders
      drawBorder(p,w,h,0);

      drawCurves(p,w,h);

      drawAxes(p,w,h,1);      // only front axes & borders
      drawBorder(p,w,h,1);

      if(legend.enabled())
            legend.draw(p,type,graphlist,position,size,w,h);
}

void Plot3D::drawBorder(QPainter *p,int w, int h,bool hide) {
      int start=0;
      if (hide) start=3;

      int xmin = (int)(w*(size.X()*p1.X()+position.X()));
      int xmax = (int)(w*(size.X()*p2.X()+position.X()));
      int ymin = (int)(h*(size.Y()*p1.Y()+position.Y()));
      int ymax = (int)(h*(size.Y()*p2.Y()+position.Y()));

      // 3d perspective
      xmax -= (xmax-xmin)/3;
      ymin += (ymax-ymin)/3;

      int x1[12]={(xmax+xmin)/2,xmin,(xmax+xmin)/2,xmin,xmax,xmin,
            xmin,xmax,xmax,(xmax+xmin)/2,xmin,(3*xmax-xmin)/2};
      int y1[12]={(ymin+ymax)/2,ymax,(3*ymin-ymax)/2,ymax,ymax,ymin,
            ymin,ymin,ymin,(3*ymin-ymax)/2,ymin,(3*ymin-ymax)/2};
      int x2[12]={(3*xmax-xmin)/2,(xmin+xmax)/2,(xmax+xmin)/2,xmax,(3*xmax-xmin)/2,xmin,
            xmax,(3*xmax-xmin)/2,xmax,(3*xmax-xmin)/2,(xmax+xmin)/2,(3*xmax-xmin)/2};
      int y2[12]={(ymin+ymax)/2,(ymax+ymin)/2,(ymin+ymax)/2,ymax,(ymin+ymax)/2,ymax,
            ymin,(3*ymin-ymax)/2,ymax,(3*ymin-ymax)/2,(3*ymin-ymax)/2,(ymin+ymax)/2};

      for (int i=start;i<12;i++) {
            if (borderenabled[i]) {
                  p->setPen(axis[i].BorderColor());
                  p->drawLine(x1[i],y1[i],x2[i],y2[i]);
            }
      }
}

void Plot3D::drawCurves(QPainter *p, int w, int h) {
      kdDebug()<<"Plot3D::drawCurves()"<<endl;
      int xmin = (int)(w*(size.X()*p1.X()+position.X()));
      int xmax = (int)(w*(size.X()*p2.X()+position.X()));
      int ymin = (int)(h*(size.Y()*p1.Y()+position.Y()));
      int ymax = (int)(h*(size.Y()*p2.Y()+position.Y()));

      // 3d perspective
      xmax -= (xmax-xmin)/3;
      ymin += (ymax-ymin)/3;

      kdDebug()<<"xmin/xmax ymin/ymax : "<<xmin<<'/'<<xmax<<' '<<ymin<<'/'<<ymax<<endl;
      kdDebug()<<"width/height : "<<w<<'/'<<h<<endl;

      for (unsigned int i=0; i < graphlist->getNumber() ; i++) {
            kdDebug()<<"draw Graph "<<i+1<<endl;
            if(graphlist->getGraph(i)->isShown() == FALSE)
                  continue;
            
            double oldx=0, oldy=0;
            double oldlinex=0, oldliney=0;
            int N, NY=0, NX=0;
            Style style;
            Symbol symbol;
            GRAPHType s = graphlist->getStruct(i);
            Graph *graph=graphlist->getGraph(i);
            Point3D *d=0;
            if (s == GRAPH3D) {
                  kdDebug()<<"GRAPH3D "<<endl;
                  Graph3D *g = graphlist->getGraph3D(i);

                  d = g->Data();
                  NX=g->NX();
                  NY=g->NY();
                  style =  g->getStyle();
                  symbol = g->getSymbol();
                  kdDebug()<<" ... OK "<<endl;
            }
            else if (s == GRAPHM) {
                  GraphM *g = graphlist->getGraphM(i);

                  double *data = g->Data();
                  NX=g->NX();
                  NY=g->NY();
                  kdDebug()<<"GRAPHM "<<NX<<'x'<<NY<<endl;
                  // conversion to 3d Point data
                  d = new Point3D[NX*NY];
                  for (int j=0;j<NY;j++) {
                        for (int k=0;k<NX;k++) {
                              d[k+j*NX].setPoint(k+1,j+1,data[k+j*NX]);
                        }
                  }
                  style =  g->getStyle();
                  symbol = g->getSymbol();
            }
            if (NY==0)
                  N=NX;
            else
                  N=NX*NY;

            int type = style.Type();

            double *linex = new double[NX], *liney = new double[NX];    // NX is ok here
            for (int k=NY-1; k>=0;k--) {
                  for(int j=NX-1 ;j>=0;j--) {
                        int index = j+k*NX;
                        // TODO : scales (log10,log2,ln,sqrt)
                        double x = xmin + (d[index].X() - actrange[0].rMin()) *
                              (xmax-xmin)/(actrange[0].rMax() - actrange[0].rMin())
                              + (xmax-xmin)/(2*(actrange[1].rMax() -
                              actrange[1].rMin()))*(d[index].Y()-actrange[1].rMin());
                        double y = ymax - (d[index].Y() - actrange[1].rMin()) *
                              (ymax-ymin)/(actrange[1].rMax() - actrange[1].rMin())
                              + (ymax-ymin)/(2*(actrange[1].rMax() -
                              actrange[1].rMin()))*(d[index].Y()-actrange[1].rMin())
                              - (d[index].Z()-actrange[2].rMin()) * (ymax-ymin)/(actrange[2].rMax()
                                - actrange[2].rMin());

                        int xlen = (xmax-xmin)/(NX-1);
                        int ylen = ymax-ymin;
                        if (NY>1)
                              ylen = (ymax-ymin)/(NY-1);

                        int dropy = (int)(y+(d[index].Z()-actrange[2].rMin()) *
                                    (ymax-ymin)/(actrange[2].rMax() - actrange[2].rMin()));

                        if (x >= xmin-1 && x <= xmax+(xmax-xmin)/2+1
                                    && y >= ymin-(ymax-ymin)/2-1 && y <= ymax+1) {
                              QPen pen( style.Color(), style.Width(),(Qt::PenStyle) style.PenStyle() );
                              p->setPen(pen);

                              if (style.isFilled()) {
                                    QPointArray a;
                                    p->setBrush(style.FillColor());

                                    if (type == 0) {
//                                        if (k>0 && j<NX-1) {
                                          if (k<NY-1 && j<NX-1) {
                                                a.setPoints( 4, (int)oldlinex,(int)oldliney,(int)linex[j],(int)liney[j],
                                                            (int)x,(int)y,(int)oldx,(int)oldy);
                                                p->drawPolygon(a);
                                          }
                                    }
                                    else if (type == 2 || type == 3) {
                                          a.setPoints( 4,(int)(x-3*xlen/4),(int)(y+ylen/4),(int)(x+xlen/4),(int)(y+ylen/4),
                                                      (int)(x+3*xlen/4),(int)(y-ylen/4),(int)(x-xlen/4),(int)(y-ylen/4));
                                          p->drawPolygon(a);
                                          if (type == 3) {
                                                a.setPoints(4,(int)(x-3*xlen/4),(int)(y+ylen/4),(int)(x-3*xlen/4),
                                                      (int)(dropy+ylen/4),(int)(x+xlen/4),(int)(dropy+ylen/4),
                                                      (int)(x+xlen/4),(int)(y+ylen/4));
                                                p->drawPolygon(a);
                                                a.setPoints(4,(int)(x+xlen/4),(int)(y+ylen/4),(int)(x+xlen/4),
                                                      (int)(dropy+ylen/4),(int)(x+3*xlen/4),(int)(dropy-ylen/4),
                                                      (int)(x+3*xlen/4),(int)(y-ylen/4));
                                                p->drawPolygon(a);
                                          }
                                    }
                              }
                              else {
                                    if (type == 0) {
//                                        if (k>0 && j<NX-1) {
                                          if (k<NY-1 && j<NX-1) {
                                                p->drawLine((int)oldlinex,(int)oldliney,(int)linex[j],(int)liney[j]);
                                                p->drawLine((int)linex[j],(int)liney[j],(int)x,(int)y);
                                                p->drawLine((int)x,(int)y,(int)oldx,(int)oldy);
                                                p->drawLine((int)oldx,(int)oldy,(int)oldlinex,(int)oldliney);
                                          }
                                    }
                                    else if (type == 2 || type == 3) {
                                          p->drawLine((int)(x-3*xlen/4),(int)(y+ylen/4),(int)(x+xlen/4),(int)(y+ylen/4));
                                          p->drawLine((int)(x+xlen/4),(int)(y+ylen/4),(int)(x+3*xlen/4),(int)(y-ylen/4));
                                          p->drawLine((int)(x+3*xlen/4),(int)(y-ylen/4),(int)(x-xlen/4),(int)(y-ylen/4));
                                          p->drawLine((int)(x-xlen/4),(int)(y-ylen/4),(int)(x-3*xlen/4),(int)(y+ylen/4));

                                          if (type == 3) { // drop step lines;
                                                p->drawLine((int)(x-3*xlen/4),(int)(y+ylen/4), (int)(x-3*xlen/4),(int)(dropy+ylen/4));
                                                p->drawLine((int)(x+xlen/4),(int)(y+ylen/4), (int)(x+xlen/4),(int)(dropy+ylen/4));
                                                p->drawLine((int)(x+3*xlen/4),(int)(y-ylen/4), (int)(x+3*xlen/4),(int)(dropy-ylen/4));
                                                p->drawLine((int)(x-xlen/4),(int)(y-ylen/4), (int)(x-xlen/4),(int)(dropy-ylen/4));

                                                // base step
                                                p->drawLine((int)(x-3*xlen/4),(int)(dropy+ylen/4), (int)(x+xlen/4),(int)(dropy+ylen/4));
                                                p->drawLine((int)(x+xlen/4),(int)(dropy+ylen/4), (int)(x+3*xlen/4),(int)(dropy-ylen/4));
                                                p->drawLine((int)(x+3*xlen/4),(int)(dropy-ylen/4), (int)(x-xlen/4),(int)(dropy-ylen/4));
                                                p->drawLine((int)(x-xlen/4),(int)(dropy-ylen/4), (int)(x-3*xlen/4),(int)(dropy+ylen/4));
                                          }
                                    }
                              }

                              if (type == 4)
                                    p->drawLine((int)x,(int)y,(int)x,(int)dropy);

                              symbol.draw(p,(int)x,(int)y);
                              graph->getAnnotateValues().draw(p,(int)x,(int)y,d[index].X(),d[index].Y(),d[index].Z());
                        }
                        oldx = x;oldy = y;
                        oldlinex=linex[j];
                        oldliney=liney[j];
                        linex[j]=x;
                        liney[j]=y;
                  }
            }
      }
}

//! draw the axes. hide=1 : only front axes (others hidden by curves)
void Plot3D::drawAxes(QPainter *p, int w, int h, bool hide) {
      const int unit = 5, gap = 10, numunit = 40, numunit2 = 20;

      kdDebug()<<"Plot3D::drawAxes()"<<endl;
      int xmin = (int)(w*(size.X()*p1.X()+position.X()));
      int xmax = (int)(w*(size.X()*p2.X()+position.X()));
      int ymin = (int)(h*(size.Y()*p1.Y()+position.Y()));
      int ymax = (int)(h*(size.Y()*p2.Y()+position.Y()));

      // 3d perspective
      xmax -= (xmax-xmin)/3;
      ymin += (ymax-ymin)/3;

      kdDebug()<<"xmin/xmax ymin/ymax : "<<xmin<<'/'<<xmax<<' '<<ymin<<'/'<<ymax<<endl;
      kdDebug()<<"width/height : "<<w<<'/'<<h<<endl;

      int start=0;
      if (hide == 1) start=1;

      // axes label
      // x,x2,x3,x4
      double xx[4] = {xmax,xmin+(xmax-xmin)/2,xmin+(xmax-xmin)/2,xmax};
      double yx[4] = {(ymax+ymin)/2+(2*unit+numunit2)*axis[0].MajorTicsEnabled(),
            ymax+(2*unit+numunit2)*axis[3].MajorTicsEnabled(),ymin-(2*unit+numunit2)*axis[6].MajorTicsEnabled()-3*gap,
            ymin-(ymax-ymin)/2-(2*unit+numunit2)*axis[9].MajorTicsEnabled()-3*gap};
      for (int i=start;i<4;i++) {
            Label *label = axis[3*i].label();
            if (label->X()==0)      // default
                  label->setPosition((xx[i]+gap)/(double)w,yx[i]/(double)h);
            if (axis[3*i].enabled())
                  label->draw(p,position,size,w,h,0);
      }

      // z,z2,z3,z4
      double xz[4] = {xmax-2*(xmax-xmin)/3-2*gap+axis[2].label()->font().pointSize()-gap,
                  gap+axis[5].label()->font().pointSize()-gap, xmax+(2*unit+numunit)*axis[8].MajorTicsEnabled(),
                  xmax+(xmax-xmin)/2+(2*unit+numunit)*axis[11].MajorTicsEnabled()};
      double yz[4] = {ymin,ymin+(ymax-ymin)/2,ymin+(ymax-ymin)/2,ymin};
      for (int i=start;i<4;i++) {
            Label *label = axis[3*i+2].label();
            p->save();
            if (label->X()==0)      // default
                  label->setPosition(xz[i]/(double)w,(yz[i]-gap)/(double)h);
            if (axis[3*i+2].enabled())
                  label->draw(p,position,size,w,h,270);
            p->restore();
      }

      // y,y,2,y3,y4
      double dx = (xmax-xmin)/2, dy = (ymax-ymin)/2;
      double phi = 180.0/M_PI*atan(dy/dx);
      double xy[4] = {xmin+(xmax+xmin)/4-(2*unit+numunit)*axis[1].MajorTicsEnabled(),
            xmax+(xmax+xmin)/4+(2*unit+numunit)*axis[4].MajorTicsEnabled()-4*gap,
            xmax+(xmax+xmin)/4+(2*unit+numunit)*axis[7].MajorTicsEnabled()-4*gap,
            xmin+(xmax+xmin)/4-(2*unit+numunit)*axis[10].MajorTicsEnabled()
            };
      double yy[4] = {ymax-(ymax-ymin)/4-4*gap,ymax-(ymax-ymin)/4+2*gap,
            ymin-(ymax-ymin)/4+2*gap,ymin-(ymax-ymin)/4-4*gap };
      for (int i=start;i<4;i++) {
            Label *label = axis[3*i+1].label();
            p->save();
            if (label->X()==0)      // default
                  label->setPosition((xy[i]-2*gap)/(double)w,yy[i]/(double)h);
            if (axis[3*i+1].enabled())
                  label->draw(p,position,size,w,h,360-phi);
            p->restore();
      }

      // Tics and Grid
      // TODO : scales (log10,log2,ln,sqrt)
      // x,x2,x3,x4
      for (int k=start;k<4;k++) {
            int xi[4]={(xmin+xmax)/2,xmin,xmin,(xmin+xmax)/2};
            int yi1[4], yi2[4], ykna[4], yknb[4];
            switch (axis[3*k].TicsPos()) {      // major/minor tics 
            case 0:
                  yi1[0]=ymax-(ymax-ymin)/2+10; yi1[1]=ymax; yi1[2]=ymin-10; yi1[3]=ymin-(ymax-ymin)/2-10;
                  yi2[0]=ymax-(ymax-ymin)/2; yi2[1]=ymax+10; yi2[2]=ymin; yi2[3]=ymin-(ymax-ymin)/2;
                  ykna[0]=ymax-(ymax-ymin)/2+5; ykna[1]=ymax; ykna[2]=ymin-5; ykna[3]=ymin-(ymax-ymin)/2-5;
                  yknb[0]=ymax-(ymax-ymin)/2; yknb[1]=ymax+5; yknb[2]=ymin; yknb[3]=ymin-(ymax-ymin)/2;
                  break;
            case 1:
                  yi1[0]=ymax-(ymax-ymin)/2-10; yi1[1]=ymax-10; yi1[2]=ymin; yi1[3]=ymin-(ymax-ymin)/2;
                  yi2[0]=ymax-(ymax-ymin)/2; yi2[1]=ymax; yi2[2]=ymin+10; yi2[3]=ymin-(ymax-ymin)/2+10;
                  ykna[0]=ymax-(ymax-ymin)/2-5; ykna[1]=ymax-5; ykna[2]=ymin; ykna[3]=ymin-(ymax-ymin)/2;
                  yknb[0]=ymax-(ymax-ymin)/2; yknb[1]=ymax; yknb[2]=ymin+5; yknb[3]=ymin-(ymax-ymin)/2+5;
                  break;
            case 2:
                  yi1[0]=ymax-(ymax-ymin)/2+10; yi1[1]=ymax-10; yi1[2]=ymin-10; yi1[3]=ymin-(ymax-ymin)/2-10;
                  yi2[0]=ymax-(ymax-ymin)/2-10; yi2[1]=ymax+10; yi2[2]=ymin+10; yi2[3]=ymin-(ymax-ymin)/2+10;
                  ykna[0]=ymax-(ymax-ymin)/2+5; ykna[1]=ymax-5; ykna[2]=ymin-5; ykna[3]=ymin-(ymax-ymin)/2-5;
                  yknb[0]=ymax-(ymax-ymin)/2-5; yknb[1]=ymax-5; yknb[2]=ymin+5; yknb[3]=ymin-(ymax-ymin)/2+5;
                  break;
            case 3:
                  break;
            }
            int yia[4]={ymin-(ymax-ymin)/2,ymax-(ymax-ymin)/2,ymin,ymin-(ymax-ymin)/2};
            int yib[4]={ymax-(ymax-ymin)/2,ymax,ymax,ymin};
            int yina[4]={ymin-(ymax-ymin)/2,ymax-(ymax-ymin)/2,ymin,ymin-(ymax-ymin)/2};
            int yinb[4]={ymax-(ymax-ymin)/2,ymax,ymax,ymin};
            if (axis[3*k].MajorTicsEnabled() && axis[3*k].enabled()) {
                  double min = actrange[0].rMin(), max = actrange[0].rMax();
                  TScale scale = axis[k].Scale();
                  int t=-1;
                  switch (scale) {
                  case LINEAR: t = axis[3*k].MajorTics(); break;
                  case LOG10: t = (int) log10(max/min)+2; break;
                  case LOG2: t = (int) log2(max/min)+2; break;
                  case LN: t = (int) log(max/min)+2; break;
                  case SQRT: t = (int) (pow(max,2)-pow(min,2))+1; break;
                  }
                  if(t==0) t=-1;

                  for (int i=0;i <= t;i++) {
                        int x1=0, x2=0;
                        switch(scale) {
                        case LINEAR:
                              x1 = xi[k]+i*(xmax-xmin)/t;
                              x2 = xi[k]+(i+1)*(xmax-xmin)/t;
                              break;
                        case LOG10: {
                              double gap = 1.0-log10(pow(10,ceil(log10(min)))/min); // fragment of decade to shift left
                              double decade = (xmax-xmin)/(log10(max/min));         // width of decade
                              x1 = xi[k]+(int)((i-gap)*decade);
                              x2 = (int) (x1+decade+ceil(fabs(log10(max))));
                              } break;
                        case LOG2: {
                              double gap = 1.0-log2(pow(2,ceil(log2(min)))/min);    // fragment of decade to shift left
                              double decade = (xmax-xmin)/(log2(max/min));          // width of decade
                              x1 = xi[k]+(int)((i-gap)*decade);
                              x2 = (int) (x1+decade+ceil(fabs(log2(max))));
                              } break;
                        case LN: {
                              double gap = 1.0-log(pow(M_E,ceil(log(min)))/min);    // fragment of decade to shift left
                              double decade = (xmax-xmin)/(log(max/min));           // width of decade
                              x1 = xi[k]+(int)((i-gap)*decade);
                              x2 = (int) (x1+decade+ceil(fabs(log(max))));
                              } break;
                        case SQRT: {
                              x1 = xi[k]+(int)((sqrt(min*min+i)-min)/(max-min)*(xmax-xmin));
                              x2 = xi[k]+(int)((sqrt(min*min+i+1)-min)/(max-min)*(xmax-xmin));
                              } break;
                        }

                        int xia[4]={x1,x1+(xmax-xmin)/2,x1,x1};
                        int xib[4]={x1,x1,x1,x1-(xmax-xmin)/2};

                        // major tics
                        if(axis[3*k].TicsPos()!=3) {
                              p->setPen(axis[3*k].TicsColor());
                              p->drawLine(x1,yi1[k],x1,yi2[k]);
                        }

                        if (gridenabled[6*k]) {
                              p->setPen(Qt::DashLine);
                              p->setPen(axis[3*k].GridColor());
                              p->drawLine(xia[k],yia[k],xib[k],yib[k]);
                              p->setPen(Qt::SolidLine);
                        }
                        if (graphlist->getNumber() > 0) {
                              QColor c = axis[3*k].TicsLabelColor();
                              QFont f = axis[3*k].TicsFont();
                              int atlf = axis[3*k].TicsLabelFormat();

                              double dx = max-min;
                              double value=0;
                              switch(scale) {
                                    case LINEAR: value = min + i*dx/t; break;
                                    case LOG10: value = pow(10,ceil(log10(min)))*pow(10.0,i-1); break;
                                    case LOG2: value = pow(2,ceil(log2(min)))*pow(2.0,i-1); break;
                                    case LN: value = pow(M_E,ceil(log(min)))*pow(M_E,i-1); break;
                                    case SQRT: value = min + i*dx/t; break;
                              }

                              // scale and shift value
                              value = value*axis[3*k].Scaling()+axis[3*k].Shift();

                              QString label = TicLabel(3*k,atlf,axis[3*k].TicsLabelPrecision(), 
                                    axis[3*k].DateTimeFormat(),value);
                                    
                              // apply prefix & suffix
                              label.prepend(axis[3*k].TicsLabelPrefix());
                              label.append(axis[3*k].TicsLabelSuffix());

                              // draw tic label
                              QFontMetrics fm(f);
                              p->save();
                              int tlg = axis[3*k].TicsLabelGap();
                              int yilb[4]={ymax-(ymax-ymin)/2+fm.ascent()+tlg,ymax+fm.ascent()+tlg,
                                    ymin-tlg,ymin-(ymax-ymin)/2-tlg};
                              p->translate(x1,yilb[k]);
                              p->rotate(axis[3*k].TicsLabelRotation());
                              if (atlf == AUTO || atlf == NORMAL || atlf == SCIENTIFIC) {
                                    p->setPen(c);
                                    f.setPointSize((int)(f.pointSize()*size.X()));  // resize tic label
                                    p->setFont(f);

                                    p->drawText(-fm.width(label)/2,fm.ascent()/2,label);
                              }
                              else {      // rich text label
                                    QSimpleRichText *richtext = new QSimpleRichText(label,f);
                                    QColorGroup cg;
                                    cg.setColor(QColorGroup::Text,c);
                                    richtext->draw(p,-richtext->width()/4, -fm.ascent()/2,QRect(),cg);
                              }
                              p->restore();
                        }
                        if (axis[3*k].MinorTicsEnabled() && i != t ) {
                              for (int j=1;j <= axis[3*k].MinorTics()+1;j++) {
                                    int x = x1+j*(x2-x1)/(axis[3*k].MinorTics()+1);
                                    int xina[4]={x,x+(xmax-xmin)/2,x,x};
                                    int xinb[4]={x,x,x,x-(xmax-xmin)/2};
                                    if(axis[3*k].TicsPos()!=3) {
                                          p->setPen(axis[3*k].TicsColor());
                                          p->drawLine(x,ykna[k],x,yknb[k]);
                                    }
                                    if (gridenabled[6*k+1]) {
                                          p->setPen(Qt::DotLine);
                                          p->setPen(axis[3*k].GridColor());
                                          p->drawLine(xina[k],yina[k],xinb[k],yinb[k]);
                                          p->setPen(Qt::SolidLine);
                                    }
                              }
                        }
                  }
            }
      }

      // z,z2,z3,z4
      for (int k=start;k<4;k++) {
            int yi[4]={ymin-(ymax-ymin)/2,ymin,ymin,ymin-(ymax-ymin)/2};
            int xi1[4], xi2[4], xkna[4], xknb[4];
            switch (axis[3*k+2].TicsPos()) {
            case 0:
                  //major tics
                  xi1[0]=(xmax+xmin)/2; xi1[1]=xmin-10; xi1[2]=xmax; xi1[3]=xmax+(xmax-xmin)/2;
                  xi2[0]=(xmax+xmin)/2-10; xi2[1]=xmin; xi2[2]=xmax+10; xi2[3]=xmax+(xmax-xmin)/2+10;
                  //minor tics
                  xkna[0]=(xmax+xmin)/2; xkna[1]=xmin-5; xkna[2]=xmax; xkna[3]=xmax+(xmax-xmin)/2;
                  xknb[0]=(xmax+xmin)/2-5; xknb[1]=xmin; xknb[2]=xmax+5; xknb[3]=xmax+(xmax-xmin)/2+5;
                  break;
            case 1:
                  //major tics
                  xi1[0]=(xmax+xmin)/2; xi1[1]=xmin+10; xi1[2]=xmax; xi1[3]=xmax+(xmax-xmin)/2;
                  xi2[0]=(xmax+xmin)/2+10; xi2[1]=xmin; xi2[2]=xmax-10; xi2[3]=xmax+(xmax-xmin)/2-10;
                  //minor tics
                  xkna[0]=(xmax+xmin)/2; xkna[1]=xmin+5; xkna[2]=xmax; xkna[3]=xmax+(xmax-xmin)/2;
                  xknb[0]=(xmax+xmin)/2+5; xknb[1]=xmin; xknb[2]=xmax-5; xknb[3]=xmax+(xmax-xmin)/2-5;
                  break;
            case 2:
                  //major tics
                  xi1[0]=(xmax+xmin)/2+10; xi1[1]=xmin-10; xi1[2]=xmax-10; xi1[3]=xmax+(xmax-xmin)/2-10;
                  xi2[0]=(xmax+xmin)/2-10; xi2[1]=xmin+10; xi2[2]=xmax+10; xi2[3]=xmax+(xmax-xmin)/2+10;
                  //minor tics
                  xkna[0]=(xmax+xmin)/2+5; xkna[1]=xmin-5; xkna[2]=xmax-5; xkna[3]=xmax+(xmax-xmin)/2-5;
                  xknb[0]=(xmax+xmin)/2-5; xknb[1]=xmin+5; xknb[2]=xmax+5; xknb[3]=xmax+(xmax-xmin)/2+5;
                  break;
            }
            int xia[4]={xmin,xmin,xmax+(xmax-xmin)/2,(xmax+xmin)/2};
            int xib[4]={(xmax+xmin)/2,xmax,xmax,xmax+(xmax-xmin)/2};
            int xina[4]={xmin,xmin,xmax,(xmax+xmin)/2};
            int xinb[4]={(xmax+xmin)/2,xmax,xmax+(xmax-xmin)/2,xmax+(xmax-xmin)/2};
            
            if (axis[3*k+2].MajorTicsEnabled() && axis[3*k+2].enabled()) {
                  double min = actrange[2].rMin(), max = actrange[2].rMax();
                  TScale scale = axis[k].Scale();
                  int t=-1;
                  switch (scale) {
                  case LINEAR: t = axis[3*k+2].MajorTics(); break;
                  case LOG10: t = (int) log10(max/min)+2; break;
                  case LOG2: t = (int) log2(max/min)+2; break;
                  case LN: t = (int) log(max/min)+2; break;
                  case SQRT: t = (int) (pow(max,2)-pow(min,2))+1; break;
                  }
                  if(t==0) t=-1;
                  
                  for (int i=0;i <= t;i++) {
                        // TODO : use scale (see x)
                        int y1 = yi[k]+i*(ymax-ymin)/t;
                        int y2 = yi[k]+(i+1)*(ymax-ymin)/t;
                        int yia[4] = {ymin+i*(ymax-ymin)/t,y1,y1+(ymin-ymax)/2,y1};
                  
                        if (axis[3*k+2].TicsPos()!=3) {
                              p->setPen(axis[3*k+2].TicsColor());
                              p->drawLine(xi1[k],y1,xi2[k],y1);
                        }
                        
                        if (gridenabled[6*k+4]) {
                              p->setPen(Qt::DashLine);
                              p->setPen(axis[3*k+2].GridColor());
                              p->drawLine(xia[k],yia[k],xib[k],y1);
                              p->setPen(Qt::SolidLine);
                        }
                        if (graphlist->getNumber() > 0) {
                              QColor c = axis[3*k+2].TicsLabelColor();
                              QFont f = axis[3*k+2].TicsFont();
                              double dz = max-min;
                              int atlf = axis[3*k+2].TicsLabelFormat();
      
                              double value=0;
                              switch(scale) {
                                    case LINEAR: value = min + (t-i)*dz/t; break;
                                    case LOG10: value = pow(10,ceil(log10(min)))*pow(10.0,i-1); break;
                                    case LOG2: value = pow(2,ceil(log2(min)))*pow(2.0,i-1); break;
                                    case LN: value = pow(M_E,ceil(log(min)))*pow(M_E,i-1); break;
                                    case SQRT: value = min + (t-i)*dz/t; break;
                              }
                              // scale and shift value
                              value = value*axis[3*k+2].Scaling()+axis[3*k+2].Shift();
      
                              QString label = TicLabel(3*k+2,atlf,axis[3*k+2].TicsLabelPrecision(),
                                          axis[3*k+2].DateTimeFormat(),value);

                              // apply prefix & suffix
                              label.prepend(axis[3*k+2].TicsLabelPrefix());
                              label.append(axis[3*k+2].TicsLabelSuffix());

                              // draw tic label
                              QFontMetrics fm(f);
                              p->save();
                              int tlg = axis[3*k+2].TicsLabelGap();
                              if (atlf == AUTO || atlf == NORMAL || atlf == SCIENTIFIC) {
                                    int xk[4]={(xmax+xmin)/2-fm.width(label)/2-tlg,xmin-fm.width(label)/2-tlg,
                                          xmax+tlg,xmax+(xmax-xmin)/2+tlg};
                                    p->translate(xk[k],y1);
                                    p->rotate(axis[3*k+2].TicsLabelRotation());
                                    p->setPen(c);
                                    f.setPointSize((int)(f.pointSize()*size.X()));  // resize tic label
                                    p->setFont(f);

                                    p->drawText(-fm.width(label)/2,fm.ascent()/2,label);
                              }
                              else {      // rich text label
                                    QSimpleRichText *richtext = new QSimpleRichText(label,f);
                                    int xk[4]={(xmax+xmin)/2-richtext->width()/2-tlg,xmin-richtext->width()-tlg,
                                          xmax+tlg,xmax+(xmax-xmin)/2+tlg};
                                    p->translate(xk[k],y1);
                                    p->rotate(axis[3*k+2].TicsLabelRotation());
                                    QColorGroup cg;
                                    cg.setColor(QColorGroup::Text,c);
                                    richtext->draw(p,-richtext->width()/2, -fm.ascent()/2,QRect(),cg);
                              }
                              p->restore();
                        }
                        if (axis[3*k+2].MinorTicsEnabled() && i != t ) {
                              for (int j=1;j <= axis[3*k+2].MinorTics()+1;j++) {
                                    int y = y1+j*(y2-y1)/(axis[3*k+2].MinorTics()+1);
                                    int yina[4]={y+(ymax-ymin)/2,y,y,y};
                                    int yinb[4]={y,y,y+(ymin-ymax)/2,y};
                                    if(axis[3*k+2].TicsPos()!=3) {
                                          p->setPen(axis[3*k+2].TicsColor());
                                          p->drawLine(xkna[k],y,xknb[k],y);
                                    }
                                    if (gridenabled[6*k+5]) {
                                          p->setPen(Qt::DotLine);
                                          p->setPen(axis[3*k+2].GridColor());
                                          p->drawLine(xina[k],yina[k],xinb[k],yinb[k]);
                                          p->setPen(Qt::SolidLine);
                                    }
                              }
                        }
                  }
            }
      }

      // y,y2,y3,y4
      for (int k=start;k<4;k++) {
            int xi[4]={xmin,xmax,xmax,xmin};
            int yi[4]={ymax,ymax,ymin,ymin};
            if (axis[3*k+1].MajorTicsEnabled() && axis[3*k+1].enabled()) {          // y
                  double min = actrange[1].rMin(), max = actrange[1].rMax();
                  TScale scale = axis[k].Scale();
                  int t=-1;
                  switch (scale) {
                  case LINEAR: t = axis[3*k+1].MajorTics(); break;
                  case LOG10: t = (int) log10(max/min)+2; break;
                  case LOG2: t = (int) log2(max/min)+2; break;
                  case LN: t = (int) log(max/min)+2; break;
                  case SQRT: t = (int) (pow(max,2)-pow(min,2))+1; break;
                  }
                  if (t==0) t=-1;
                  
                  for (int i=0;i <= t;i++) {
                        // TODO : use scale (see x)
                        int y1 = yi[k]-i*(ymax-ymin)/(2*t);
                        int y2 = yi[k]-(i+1)*(ymax-ymin)/(2*t);
                        int x1 = xi[k]+i*(xmax-xmin)/(2*t);
                        int x2 = xi[k]+(i+1)*(xmax-xmin)/(2*t);

                        int xi1[4],xi2[4];
                        switch(axis[3*k+1].TicsPos()) {
                        case 0:
                              xi1[0]=xi1[1]=xi1[2]=xi1[3]=x1;
                              xi2[0]=xi2[3]=x1-10;xi2[1]=xi2[2]=x1+10;
                              break;
                        case 1:
                              xi1[0]=xi1[1]=xi1[2]=xi1[3]=x1;
                              xi2[0]=xi2[3]=x1+10; xi2[1]=xi2[2]=x1-10;
                              break;
                        case 2:
                              xi1[0]=xi1[1]=xi1[2]=xi1[3]=x1-10;
                              xi2[0]=xi2[1]=xi2[2]=xi2[3]=x1+10;
                              break;
                        }
                        int xia[4]={x1,x1,x1-(xmax-xmin),x1};
                        int xib[4]={x1+xmax-xmin,x1,x1,x1};
                        int yib[4]={y1,y1-ymax+ymin,y1,y1+ymax-ymin};
                        
                        if (axis[3*k+1].TicsPos()!=3) {
                              p->setPen(axis[3*k+1].TicsColor());
                              p->drawLine(xi1[k],y1,xi2[k],y1);
                        }
                        
                        if (gridenabled[6*k+2]) {
                              p->setPen(Qt::DashLine);
                              p->setPen(axis[3*k+1].GridColor());
                              p->drawLine(xia[k],y1,xib[k],yib[k]);
                              p->setPen(Qt::SolidLine);
                        }
                        if (graphlist->getNumber() > 0) {
                              QColor c = axis[3*k+1].TicsLabelColor();
                              QFont f = axis[3*k+1].TicsFont();
                              double dy = max-min;
                              int yy[4]={ymax,ymax,ymin,ymin};
                              // TODO : use scale (see x)
                              // TODO : fix rounding bug
                              double value = min+2*dy*(yy[k]-y1)/(ymax-ymin);
                              int atlf = axis[3*k+1].TicsLabelFormat();

                              // scale and shift value
                              value = value*axis[3*k+1].Scaling()+axis[3*k+1].Shift();

                              QString label = TicLabel(3*k+1,atlf,axis[3*k+1].TicsLabelPrecision(),
                                          axis[3*k+1].DateTimeFormat(),value);

                              // apply prefix & suffix
                              label.prepend(axis[3*k+1].TicsLabelPrefix());
                              label.append(axis[3*k+1].TicsLabelSuffix());

                              // draw tic label
                              QFontMetrics fm(f);
                              p->save();
                              int tlg = axis[3*k+1].TicsLabelGap();
                              if (atlf == AUTO || atlf == NORMAL || atlf == SCIENTIFIC) {
                                    int xilb[4]={x1-fm.width(label)/2-tlg,x1+tlg,x1+tlg,x1-fm.width(label)/2-tlg};
                                    p->translate(xilb[k],y1);
                                    p->rotate(axis[3*k+1].TicsLabelRotation());
                                    p->setPen(c);
                                    f.setPointSize((int)(f.pointSize()*size.X()));  // resize tic label
                                    p->setFont(f);

                                    p->drawText(-fm.width(label)/2,fm.ascent()/2-1,label);
                              }
                              else {      // rich text label
                                    QSimpleRichText *richtext = new QSimpleRichText(label,f);
                                    int xilb[4]={x1-richtext->width()/2-tlg,x1+tlg,x1+tlg,x1-richtext->width()/2-tlg};
                                    p->translate(xilb[k],y1);
                                    p->rotate(axis[3*k+1].TicsLabelRotation());
                                    QColorGroup cg;
                                    cg.setColor(QColorGroup::Text,c);
                                    richtext->draw(p,-richtext->width()/2, -fm.ascent()/2,QRect(),cg);
                              }
                              p->restore();
                        }
                        if (axis[3*k+1].MinorTicsEnabled() && i != t ) {
                              for (int j=1;j <= axis[3*k+1].MinorTics()+1;j++) {
                                    int y = y1+j*(y2-y1)/(axis[3*k+1].MinorTics()+1);
                                    int x = x1+j*(x2-x1)/(axis[3*k+1].MinorTics()+1);
                                    p->setPen(axis[3*k+1].TicsColor());
                                    int xina[4]={x,x,x-(xmax-xmin),x};
                                    int xinb[4]={x+xmax-xmin,x,x,x};
                                    int yinb[4]={y,y-ymax+ymin,y,y+ymax-ymin};
                              
                                    int xkna[4],xknb[4];
                                    switch(axis[3*k+1].TicsPos()) {
                                    case 0:
                                          xkna[0]=xkna[1]=xkna[2]=xkna[3]=x;
                                          xknb[0]=xknb[3]=x-5;xknb[1]=xknb[2]=x+5;
                                          break;
                                    case 1:
                                          xkna[0]=xkna[1]=xkna[2]=xkna[3]=x;
                                          xknb[0]=xknb[3]=x+5;xknb[1]=xknb[2]=x-5;
                                          break;
                                    case 2:
                                          xkna[0]=xkna[1]=xkna[2]=xkna[3]=x-5;
                                          xknb[0]=xknb[1]=xknb[2]=xknb[3]=x+5;
                                          break;
                                    }
                              
                                    if (axis[3*k+1].TicsPos()!=3) {
                                          p->drawLine(xkna[k],y,xknb[k],y);
                                    }
                                    if (gridenabled[6*k+3]) {
                                          p->setPen(Qt::DotLine);
                                          p->setPen(axis[3*k+1].GridColor());
                                          p->drawLine(xina[k],y,xinb[k],yinb[k]);
                                          p->setPen(Qt::SolidLine);
                                    }
                              }
                        }
                  }
            }
      }
}

void Plot3D::saveAxes(QTextStream *t) {
      for (int i = 0; i < 12; i++) {
            saveAxis(t,&axis[i],gridenabled[2*i],borderenabled[i],gridenabled[2*i+1]);
      }
}

void Plot3D::openAxes(QTextStream *t, int version) {
      for(int i = 0;i<12;i++) {
            openAxis(t,version, &axis[i],&gridenabled[2*i],&borderenabled[i],&gridenabled[2*i+1]);
      }
}

Generated by  Doxygen 1.6.0   Back to index