Logo Search packages:      
Sourcecode: labplot version File versions

Plot2DSurface.cc

//LabPlot Plot2DSurface.cc

#include <kdebug.h>
#include "Plot2DSurface.h"

#ifndef INFINITY
#define INFINITY 0x7fffffff
#endif

inline double MAX(double x,double y) {if (x>y) return x; else return y;}
inline double MIN(double x,double y) {if (x<y) return x; else return y;}

// density and contour 2D Plot class
Plot2DSurface::Plot2DSurface(Worksheet *p)
      : Plot2D(p)
{
      densityenabled=TRUE;
      contourenabled=TRUE;
      contour_color = QColor(Qt::black);
      colored_contour = FALSE;
      mesh = FALSE;
      relative = TRUE;
      brush = 1;
      number = 20;
      threshold = -INFINITY;
      palette = 0;

      // room for legend
      int xmax = (int)(worksheet->width()*(size.X()*p2.X()+position.X()));
      setXMax(xmax-(int)(120*size.X()),worksheet->width());
}

QStringList Plot2DSurface::Info() {
      QStringList s;
      s<<"SURFACE";
      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;
}

int Plot2DSurface::graph_segment(QPainter *p,double x1,double y1, double z1, double x2, double y2, double z2,
            double x3, double y3, double z3, double level) {
      double factor;
      double x,y,xa,ya,xb,yb,tmp;

      if(z1>=z2) {
            tmp=x1; x1=x2; x2=tmp;
            tmp=y1; y1=y2; y2=tmp;
            tmp=z1; z1=z2; z2=tmp;
      }
      if(z2>z3) {
            if(z3<z1) {
                  tmp=x1; x1=x3; x3=tmp;
                  tmp=y1; y1=y3; y3=tmp;
                  tmp=z1; z1=z3; z3=tmp;
            }
            tmp=x2; x2=x3; x3=tmp;
            tmp=y2; y2=y3; y3=tmp;
            tmp=z2; z2=z3; z3=tmp;
      }

      if(level<z1 || level > z3) {  // important
            return 0;
      }
      // not needed
      /*if(level == z1 && z1 == z2 && z2 != z3) {
            p.drawLine((int)(x1*FACTOR),(int)(y1*FACTOR),(int)(x2*FACTOR),(int)(y2*FACTOR));
      }
      if(level == z3 && z3 == z2 && z2 != z1) {
            p.drawLine((int)(x3*FACTOR),(int)(y3*FACTOR),(int)(x2*FACTOR),(int)(y2*FACTOR));
      }*/
      if (level == z2 ) {
            if( z3 == z1)
                  return 0;
            factor = (level-z1)/(z3-z1);
            x=x1+(x3-x1)*factor;
            y=y1+(y3-y1)*factor;
            p->drawLine((int)(x),(int)(y),(int)(x2),(int)(y2));
      }
      else if (level<z2) {
            factor = (level-z1)/(z2-z1);
            xa=x1+(x2-x1)*factor;
            ya=y1+(y2-y1)*factor;
            factor = (level-z1)/(z3-z1);
            xb=x1+(x3-x1)*factor;
            yb=y1+(y3-y1)*factor;
            p->drawLine((int)(xa),(int)(ya),(int)(xb),(int)(yb));
      } else {
            factor = (level-z1)/(z3-z1);
            xa=x1+(x3-x1)*factor;
            ya=y1+(y3-y1)*factor;
            factor = (level-z2)/(z3-z2);
            xb=x2+(x3-x2)*factor;
            yb=y2+(y3-y2)*factor;
            p->drawLine((int)(xa),(int)(ya),(int)(xb),(int)(yb));
      }
      return 0;
}

void Plot2DSurface::drawCurves(QPainter *p, int w, int h) {
      kdDebug()<<"Plot2DSurface::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()));
      kdDebug()<<"xmin/xmax ymin/ymax : "<<xmin<<'/'<<xmax<<' '<<ymin<<'/'<<ymax<<endl;

      for (unsigned int i=0; i < graphlist->getNumber() ; i++) {
            if(graphlist->getGraph(i)->isShown() == FALSE)
                  continue;

            if ( graphlist->getStruct(i) == GRAPHIMAGE ) {
                  QPixmap pm(graphlist->getGraphIMAGE(i)->Pixmap());
                  
                  p->save();  // scale painter so that pixmap fits into drawing area
                  p->translate(xmin,ymin);
                  p->scale((xmax-xmin)/(double)pm.width(),(ymax-ymin)/(double)pm.height());
                  p->drawPixmap(0,0,pm);
                  p->restore();
                  continue;
            }
            
            GraphM *g = graphlist->getGraphM(i);
            int NX = g->NX(), NY = g->NY();
            double *a = g->Data();

            kdDebug()<<"GRAPHM Type = "<<g->Type()<<endl;
            kdDebug()<<"xmin/xmax "<<xmin<<' '<<xmax<<endl;
            kdDebug()<<"ymin/ymax "<<ymin<<' '<<ymax<<endl;
            kdDebug()<<"xact1/xact2 "<<actrange[0].rMin()<<' '<<actrange[0].rMax()<<endl;
            kdDebug()<<"yact1/yact2 "<<actrange[1].rMin()<<' '<<actrange[1].rMax()<<endl;

            LRange r[3];
            r[0]= g->Range(0);
            r[1]= g->Range(1);
            r[2]= g->Range(2);

            double minx = actrange[0].rMin();
            double maxx = actrange[0].rMax();
            double miny = actrange[1].rMin();
            double maxy = actrange[1].rMax();

            int xold=xmin, yold=ymin;
            double zmin=r[2].rMin(),zmax=r[2].rMax();

            kdDebug()<<"minx/miny = "<<minx<<"/"<<miny<<endl;

            // density plot
            if(densityenabled) {
                  int y=0;
                  for (int i=0;i<=NY;i++) {
                        switch(axis[1].Scale()) {
                        case LINEAR:
                              y = ymin + (int)((i+miny) * (ymax-ymin)/(maxy-miny));
                              break;
                        case LOG10:
                              y = ymax - (int)(log10((NY-i)/miny) * (ymax-ymin)/log10(maxy/miny));
                              break;
                        case LOG2:
                              y = ymax - (int)((log2((NY-i)/miny)) * (ymax-ymin)/(log2(maxy/miny)));
                              break;
                        case LN:
                              y = ymax - (int)((log((NY-i)/miny)) * (ymax-ymin)/(log(maxy/miny)));
                              break;
                        case SQRT:
                              y = ymax - (int)((sqrt(miny)+sqrt((double)i)) * (ymax-ymin)/(sqrt(maxy)-sqrt(miny)));
                              break;
                        }

                        int x=0;
                        for (int j=0;j<=NX;j++) {
                              switch (axis[0].Scale()) {
                              case LINEAR:
                                    x = xmin + (int)((j-minx) * (xmax-xmin)/(maxx-minx));
                                    break;
                              case LOG10:
                                    x = xmin + (int)(log10(j/minx)*(xmax-xmin)/log10(maxx/minx));
                                    break;
                              case LOG2:
                                    x = xmin + (int)(log2(j/minx)*(xmax-xmin)/log2(maxx/minx));
                                    break;
                              case LN:
                                    x = xmin + (int)(log(j/minx)*(xmax-xmin)/log(maxx/minx));
                                    break;
                              case SQRT:
                                    x = xmin + (int)(sqrt(j-minx)*(xmax-xmin)/sqrt(maxx-minx));
                                    break;
                              }

                              //kdDebug()<<" DENSITY : x = "<<x<<" y = "<<y<<" (i="<<i<<",j="<<j<<") "<<endl;

                              if(i>0 && j>0) {
                                    // value = 0 .. 255
                                    // ??? : i=0,j=0 : a[-1-NX] ???
                                    int value;
                                    if (relative)
                                          value = (int) (255.0*(a[j-1+NX*(i-1)]-zmin)/(zmax-zmin));
                                    else
                                          value = (int) (127.0*a[j-1+NX*(i-1)]/MAX(fabs(zmax),fabs(zmin))+127.0);

                                    //kdDebug()<<"max = "<<zmax<<"/ min = "<<zmin<<endl;
//                                  kdDebug()<<"a = "<<a[j-1+NX*(i-1)]<<endl;
//                                  kdDebug()<<" color value ("<<i<<"/"<<j<<") = "<<value<<endl;

                                    QBrush qbrush(Color(value,palette),(Qt::BrushStyle)brush);
                                    p->setBrush(qbrush);
                                    if(mesh)
                                          p->setPen( Qt::black );
                                    else
                                          p->setPen( Qt::NoPen );

                                    int tmpy=y-yold,tmpx=x-xold;
                                    //if (i==1)
                                    //    tmpy+=2;
                                    //if (j==NX)
                                    //    tmpx--;

                                    // fill border rects to border
                                    if (xold<=xmin-1 && xold+tmpx>=xmin-1)
                                          xold=xmin-1;
                                    else if (xold+tmpx>=xmax+1 && xold<=xmax+1)
                                          tmpx=xmax+1-xold;
                                    if (yold<=ymin-1 && yold+tmpy>=ymin-1)
                                          yold=ymin-1;
                                    else if (yold+tmpy>=ymax+1 && yold<=ymax+1)
                                          tmpy=ymax+1-yold;

                                    if(xold >= xmin-1  && tmpx+xold <= xmax+1 &&
                                          yold >= ymin-1 &&  tmpy+yold <= ymax+1) {
                                          //kdDebug()<<" Draw Rect from ("<<xold+1<<","<<yold<<" / size ("<<tmpx<<","<<tmpy<<")"<<endl;
                                          if (a[j-1+NX*(i-1)]> threshold)
                                                p->drawRect(xold+1,yold,tmpx,tmpy);
                                    }
                              }
                              xold=(int)x;
                        }
                        yold=(int)y;
                  }
            }

//          kdDebug()<<"DENSITY OK"<<endl;

            // contour plot
            if (contourenabled) {
                  double *x,*y;
                  x = new double[NX];
                  y = new double[NY];

                  switch (axis[0].Scale()) {
                  case LINEAR:
                        for(int i=0;i<NX;i++)
                              x[i] = xmin + (i*NX/(double)(NX-1)-minx) * (xmax-xmin)/(maxx-minx);
                        break;
                  case LOG10:
                        for(int i=0;i<NX;i++)
                              x[i] = xmin + log10((i+1)/minx)*(xmax-xmin-1)/log10(maxx/minx);
                        break;
                  case LOG2:
                        for(int i=0;i<NX;i++)
                              x[i] = xmin + log2((i+1)/minx)*(xmax-xmin-1)/log2(maxx/minx);
                        break;
                  case LN:
                        for(int i=0;i<NX;i++)
                              x[i] = xmin + log((i+1)/minx)*(xmax-xmin-1)/log(maxx/minx);
                        break;
                  case SQRT:
                        for(int i=0;i<NX;i++)
                              x[i] = xmin + sqrt(i+1-minx)*(xmax-xmin-1)/sqrt(maxx-minx);
                        break;
                  }

                  switch(axis[1].Scale()) {
                  case LINEAR:
                        for(int j=0;j<NY;j++)
                              y[j] = ymin + (j*NY/(double)(NY-1)+miny) * (ymax-ymin)/(maxy-miny);
                        break;
                  case LOG10:
                        for(int j=0;j<NY;j++)
                              y[j] = ymax - (log10((NY-j)/miny)) * (ymax-ymin)/(log10(maxy/miny));
                        break;
                  case LOG2:
                        for(int j=0;j<NY;j++)
                              y[j] = ymax - (log2((NY-j)/miny)) * (ymax-ymin)/(log2(maxy/miny));
                        break;
                  case LN:
                        for(int j=0;j<NY;j++)
                              y[j] = ymax - (log((NY-j)*miny)) * (ymax-ymin)/(log(maxy/miny));
                        break;
                  case SQRT:
                        for(int j=0;j<NY;j++)
                              y[j] = ymin + (sqrt(j-1+miny)) * (ymax-ymin)/(sqrt(maxy-miny));
                        break;
                  }

                  double diff = (zmax-zmin)/number;

                  //kdDebug()<<"diff = "<<diff<<endl;
                  //kdDebug()<<"zmin/zmax = "<<zmin<<' '<<zmax<<endl;

                  for (int i=0;i<NY-1;i++) {
                        double yavg = (y[i]+y[i+1])/2.0;
                        for (int j=0;j<NX-1;j++) {
                              double xavg = (x[j]+x[j+1])/2.0;
                              //kdDebug()<<" SURFACE : x = "<<x[j]<<" y = "<<y[i]<<" (i="<<i<<",j="<<j<<") "<<endl;

                              double zij = a[i*NX+j];
                              double zipj = a[i*NX+j+1];
                              double zijp = a[(i+1)*NX+j];
                              double zipjp = a[(i+1)*NX+j+1];

                              //kdDebug()<<zij<<' '<<zipj<<endl;
                              //kdDebug()<<zijp<<' '<<zipjp<<endl<<endl;

                              double zavg=(zij+zipj+zijp+zipjp)/4.0;

                              p->setPen(contour_color);

                              for (double level=zmin;level<zmax;level+=diff) {
                                    if (colored_contour) {
                                          // value = 0 .. 255
                                          int value;
                                          if (relative)
                                                value = (int)((level-zmin)/(zmax-zmin)*255.0);
                                          else
                                                value = (int)(127.0*(level)/MAX(fabs(zmax),fabs(zmin))+127.0);
                                          p->setPen(Color(value,palette));
                                    }

                                    // TODO : fill border rects to border
/*                                  if (xold<=xmin-1 && xold+tmpx>=xmin-1)
                                          xold=xmin-1;
                                    else if (xold+tmpx>=xmax+1 && xold<=xmax+1)
                                          tmpx=xmax+1-xold;
                                    if (yold<=ymin-1 && yold+tmpy>=ymin-1)
                                          yold=ymin-1;
                                    else if (yold+tmpy>=ymax+1 && yold<=ymax+1)
                                          tmpy=ymax+1-yold;
*/
                                    if (x[j]>=xmin && x[j]<=xmax && x[j+1]>= xmin && x[j+1] <= xmax
                                          && y[i]>=ymin && y[i]<=ymax && y[i+1]>=ymin && y[i+1]<=ymax) {
                                          if (zavg> threshold) {
                                                graph_segment(p,x[j],y[i],zij,x[j],y[i+1],zijp,xavg,yavg,zavg,level);
                                                graph_segment(p,x[j],y[i],zij,x[j+1],y[i],zipj,xavg,yavg,zavg,level);
                                                graph_segment(p,x[j+1],y[i],zipj,x[j+1],y[i+1],zipjp,xavg,yavg,zavg,level);
                                                graph_segment(p,x[j],y[i+1],zijp,x[j+1],y[i+1],zipjp,xavg,yavg,zavg,level);
                                          }
                                    }
                              }
                        }
                  }
            }
      }
}

QColor Plot2DSurface::Color(int value, int palette) {
      QColor c;

      // value = 0 .. 255
      switch (palette) {
      case 0:
            if (value > 127)
                  c = QColor(2*(value-128),0,0);
            else
                  c = QColor(0,0,2*(127-value));
            break;
      case 1:
            if (value > 127)
                  c = QColor(0,2*(value-128),0);
            else
                  c = QColor(0,0,2*(127-value));
            break;
      case 2:
            if (value > 127)
                  c = QColor(0,0,2*(value-128));
            else
                  c = QColor(2*(127-value),0,0);
            break;
      case 3:
            if (value > 127)
                  c = QColor(0,0,2*(value-128));
            else
                  c = QColor(0,2*(127-value),0);
            break;
      case 4:
            if (value > 127)
                  c = QColor(0,2*(value-128),0);
            else
                  c = QColor(2*(127-value),0,0);
            break;
      case 5:
            c = QColor(value,0,0);
            break;
      case 6:
            c = QColor(0,value,0);
            break;
      case 7:
            c = QColor(0,0,value);
            break;
      case 8:
            c = QColor(value,value,value);
            break;
      case 9:
            c = QColor(value,value,0);
            break;
      case 10:
            c = QColor(value,0,value);
            break;
      case 11:
            c = QColor(0,value,value);
            break;
      case 12:
            c = QColor(255-value,255,255,QColor::Hsv);
            break;
      case 13:
            c = QColor(255-value,255,200,QColor::Hsv);
            break;
      case 14:
            c = QColor(255-value,100,255,QColor::Hsv);
            break;
      case 15:
            c = QColor(255-value,100,200,QColor::Hsv);
            break;
      case 16:
            c = QColor(value,255,255,QColor::Hsv);
            break;
      case 17:
                  c = QColor(value,255,200,QColor::Hsv);
            break;
      case 18:
                  c = QColor(value,100,255,QColor::Hsv);
            break;
      case 19:
                  c = QColor(value,100,200,QColor::Hsv);
            break;
      case 20:
            c = QColor(255-value,255-value,255-value);
            break;
      }

      return c;
}

Generated by  Doxygen 1.6.0   Back to index