plotmaplabel.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                        plotmaplabel.cpp  -  description
00003                              -------------------
00004     begin                : Tue Mar 29 2005
00005     copyright            : (C) 2005-2006 by Ben Swerts
00006     email                : bswerts@users.sourceforge.net
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00019 
00025 
00026 
00027 
00029 
00030 // Qt header files
00031 #include <qpainter.h>
00032 #include <qpixmap.h>
00033 
00034 // Xbrabo header files
00035 #include "plotmaplabel.h"
00036 
00040 
00042 PlotMapLabel::PlotMapLabel(QWidget* parent, const char* name, WFlags fl) : QLabel(parent, name, fl),
00043   densityPixmap(NULL),
00044   drawDrag(false)
00046 {
00047 }
00048 
00050 PlotMapLabel::~PlotMapLabel()
00052 {
00053   if(densityPixmap)
00054     delete densityPixmap;
00055 }
00056 
00058 void PlotMapLabel::setDrawStyle(const unsigned int style, const bool cubic)
00064 {
00065   if(style > 3)
00066     return;
00067 
00068   drawStyle = style;
00069   cubicInterpolation = cubic;
00070 }
00071 
00073 void PlotMapLabel::setDensityPixmap(const QPixmap& pixmap)
00075 {
00076   if(!densityPixmap)
00077     densityPixmap = new QPixmap(pixmap);
00078   else
00079     *densityPixmap = pixmap;
00080 }
00081 
00083 void PlotMapLabel::setCrosses(const vector<Point3D<double> >& centers)
00085 {
00086   if(centers.empty())
00087     return;
00088 
00089   crosses.clear();
00090   crosses.reserve(centers.size());
00091   crosses.assign(centers.begin(), centers.end());
00092 }
00093 
00095 void PlotMapLabel::setGrid(const Point3D<unsigned int>& pointDimension, const Point3D<double>& pointDelta)
00099 {
00100   numPoints = pointDimension;
00101   delta = pointDelta;
00102 }
00103 
00105 void PlotMapLabel::setIsoCurves(const vector< vector<Point3D<double> >* >& curves, const vector<QColor>& lineColors)
00107 {
00108   isoCurves.clear();
00109   isoCurves.reserve(curves.size());
00110   isoCurves.assign(curves.begin(), curves.end());
00111 
00112   //isoCurveColors.clear();
00113   //isoCurveColors.reserve(colors.size());
00114   //isoCurveColors.assign(colors.begin(), colors.end());
00115 
00116   isoLineColors.clear();
00117   isoLineColors.reserve(lineColors.size());
00118   isoLineColors.assign(lineColors.begin(), lineColors.end());
00119 }
00120 
00122 void PlotMapLabel::setPolygons(const vector< vector<Point3D<double> > >& polygons, const vector<QColor>& colors)
00124 {
00125   isoPolygons.clear();
00126   isoPolygons.reserve(polygons.size());
00127   isoPolygons.assign(polygons.begin(), polygons.end());
00128 
00129   /*qDebug("the contents of isoPolygons in PlotMapLabel:");
00130   for(unsigned int polygon = 0; polygon < isoPolygons.size(); polygon++)
00131   {
00132     qDebug(" for polygon %d with %d points",polygon, isoPolygons[polygon].size());
00133     for(unsigned int i = 0; i < isoPolygons[polygon].size(); i++)
00134       qDebug("  point %d = (%f, %f)",i,isoPolygons[polygon][i].x(),isoPolygons[polygon][i].y()); 
00135   }*/
00136 
00137   isoPolygonColors.clear();
00138   isoPolygonColors.reserve(colors.size());
00139   isoPolygonColors.assign(colors.begin(), colors.end());
00140 }
00141 
00143 void PlotMapLabel::setColors(const QColor& zero, const QColor& atom)
00145 {
00146   zeroColor = zero;
00147   crossColor = atom;
00148 }
00149 
00151 void PlotMapLabel::startDrag(const QPoint& pos)
00153 {
00155   if(pos.x() < 0 || pos.y() < 0 || pos.x() > width() || pos.y() > height())
00156     return;
00157 
00158   startPosition = pos;
00159   endPosition = pos;
00160   drawDrag = true;
00161 }
00162 
00164 void PlotMapLabel::moveDrag(const QPoint& pos)
00166 {
00167   if(!drawDrag)
00168     return;
00169 
00170   endPosition = pos;
00171   update();
00172 }
00173 
00175 void PlotMapLabel::endDrag()
00177 {
00178   drawDrag = false;
00179   update();
00180 }
00181 
00185 
00187 void PlotMapLabel::drawContents(QPainter* )
00191 {  
00193   const QRect drawRect = contentsRect();
00195   //const double scaleX = static_cast<double>(drawRect.width()) / numPoints.x();
00196   //const double scaleY = static_cast<double>(drawRect.height()) / numPoints.y();
00198   const double aspectRatio = static_cast<double>(numPoints.x()) / numPoints.y();
00199   double scaleX, scaleY;
00200   if(aspectRatio > static_cast<double>(drawRect.width()) / drawRect.height())
00201   {
00202     // the drawing will be done in the top part of the frame
00203     scaleX = static_cast<double>(drawRect.width()) / numPoints.x(); // scale to the width of the frame
00204     scaleY = static_cast<double>(drawRect.width()) / aspectRatio / numPoints.y(); // scale according to the aspect ratio
00205   }
00206   else
00207   {
00208     // the drawing will be done in the left part of the frame
00209     scaleX = static_cast<double>(drawRect.height()) * aspectRatio / numPoints.x(); // scale to the aspect ratio
00210     scaleY = static_cast<double>(drawRect.height()) / numPoints.y(); // scale according to the heigth of the frame
00211   }
00212   const unsigned int maxPoints = static_cast<unsigned int>(scaleX + scaleY); // the number of points to interpolate between to fixed points
00213 
00215   QPixmap pm(drawRect.width(), drawRect.height());
00216   QPainter paint;
00217   paint.begin(&pm);
00218 
00220   // always fill the widget with the zeroColor
00221   paint.fillRect(drawRect, QBrush(zeroColor));
00222   if(drawStyle == 0 && densityPixmap)
00223   {
00224     QRect pixmapRect(drawRect);
00225     // define the rectangle to draw the pixmap in
00226     if(aspectRatio > static_cast<double>(drawRect.width()) / drawRect.height())
00227       pixmapRect.setHeight(static_cast<int>(drawRect.width() / aspectRatio));
00228     else
00229       pixmapRect.setWidth(static_cast<int>(drawRect.height() * aspectRatio));
00230     paint.drawPixmap(pixmapRect, *densityPixmap); // autoscaling
00231   }
00232   
00234   if(false)
00235   {
00236     paint.setPen(QColor(0, 255, 0));
00237     for(unsigned int y = 0; y < numPoints.y(); y++)
00238     {
00239       for(unsigned int x = 0; x < numPoints.x(); x++)
00240         paint.drawPoint(static_cast<int>((x+0.5)*scaleX), static_cast<int>((y+0.5)*scaleY));
00241     }
00242   }
00243 
00244   if(drawStyle > 1)
00245   {
00247     for(unsigned int polygon = 0; polygon < isoPolygons.size(); polygon++)
00248     {
00249       paint.setBrush(isoPolygonColors[polygon]);
00250       paint.setPen(Qt::NoPen);
00251       paint.drawPolygon(pointCurve(isoPolygons[polygon], cubicInterpolation, scaleX, scaleY, maxPoints));
00252       /*
00253       QPointArray pa(isoPolygons[polygon].size() - 1);
00254       for(unsigned int i = 0; i < isoPolygons[polygon].size() - 1; i++)
00255       {
00256         if(!cubicInterpolation)
00257         {
00258           int x = static_cast<int>((isoPolygons[polygon][i].x()+0.5) * scaleX);
00259           int y = static_cast<int>((isoPolygons[polygon][i].y()+0.5) * scaleY);
00260           pa.setPoint(i, QPoint(x, y));
00261         }
00262         else
00263         {
00264 
00265         }
00266       }
00267       paint.drawPolygon(pa);
00268       */
00269     }
00270   }
00271 
00272   if(drawStyle == 1 || drawStyle == 3)
00273   {
00275     if(scaleX <= 1.0 && scaleY <= 1.0)
00276     {
00277       // no interpolation needed if the scale is smaller than 1
00278       for(unsigned int curve = 0; curve < isoCurves.size(); curve++)
00279       {
00280         paint.setPen(QPen(isoLineColors[curve]));
00281         for(unsigned int i = 0; i < isoCurves[curve]->size() - 1; i++) // never draw the last point as it is either identical to 
00282         {                                                               // the first or the previous point
00283           int x = static_cast<int>((isoCurves[curve]->operator[](i).x()+0.5) * scaleX);
00284           int y = static_cast<int>((isoCurves[curve]->operator[](i).y()+0.5) * scaleY);
00285           paint.drawPoint(x, y);
00286         }
00287       }
00288     }
00289     else
00290     {
00291       for(unsigned int curve = 0; curve < isoCurves.size(); curve++)
00292       {
00293         paint.setPen(QPen(isoLineColors[curve]));
00294         paint.drawPolyline(pointCurve(*isoCurves[curve], cubicInterpolation, scaleX, scaleY, maxPoints));
00295       }
00296     }
00297     /*
00298     else if(!cubicInterpolation)
00299     {
00300       // use linear interpolation
00301       for(unsigned int curve = 0; curve < isoCurves.size(); curve++)
00302       {
00303         paint.setPen(QPen(isoLineColors[curve], 1));
00304         if(isoCurves[curve]->size() > 1)
00305         {
00306           int oldx = static_cast<int>((isoCurves[curve]->operator[](0).x()+0.5) * scaleX);
00307           int oldy = static_cast<int>((isoCurves[curve]->operator[](0).y()+0.5) * scaleY);
00308           for(unsigned int i = 1; i < isoCurves[curve]->size(); i++)
00309           {
00310             int newx = static_cast<int>((isoCurves[curve]->operator[](i).x()+0.5) * scaleX);
00311             int newy = static_cast<int>((isoCurves[curve]->operator[](i).y()+0.5) * scaleY);
00312             paint.drawLine(oldx, oldy, newx, newy);
00313             oldx = newx;
00314             oldy = newy;
00315           }
00316         }
00317       }
00318     }
00319     else
00320     {
00321       // use cubic interpolation
00322       for(unsigned int curve = 0; curve < isoCurves.size(); curve++)
00323       {
00324         if(isoCurves[curve]->size() > 3)
00325         {
00326           paint.setPen(isoLineColors[curve]);
00327           for(unsigned int i = 1; i < isoCurves[curve]->size() - 2; i++)
00328           {
00329             //qDebug("drawing spline between (%f, %f) and (%f, %f)",isoCurves[curve]->operator[](i).x(),isoCurves[curve]->operator[](i).y(),
00330             //                                                      isoCurves[curve]->operator[](i+1).x(),isoCurves[curve]->operator[](i+1).y());
00331             Point3D<double> controlPoint1((isoCurves[curve]->operator[](i-1).x()+0.5) * scaleX, (isoCurves[curve]->operator[](i-1).y()+0.5) * scaleY, 0.0);
00332             Point3D<double> startPoint((isoCurves[curve]->operator[](i).x()+0.5) * scaleX, (isoCurves[curve]->operator[](i).y()+0.5) * scaleY, 0.0);
00333             Point3D<double> endPoint((isoCurves[curve]->operator[](i+1).x()+0.5) * scaleX, (isoCurves[curve]->operator[](i+1).y()+0.5) * scaleY, 0.0);
00334             Point3D<double> controlPoint2((isoCurves[curve]->operator[](i+2).x()+0.5) * scaleX, (isoCurves[curve]->operator[](i+2).y()+0.5) * scaleY, 0.0);
00335             paint.drawPoints(cardinalSpline(controlPoint1, startPoint, endPoint, controlPoint2, maxPoints));
00336           }
00337           // if the last point of the curve is identical to the first point, the curve 
00338           // is circular and two extra segments should be drawn
00339           if(isoCurves[curve]->operator[](0).id() == isoCurves[curve]->operator[](isoCurves[curve]->size() - 1).id())
00340           {
00341             const unsigned int lastIndex = isoCurves[curve]->size() - 1;
00342             // between last and first points
00343             //qDebug("drawing spline between (%f, %f) and (%f, %f)",isoCurves[curve]->operator[](lastIndex-1).x(),isoCurves[curve]->operator[](lastIndex-1).y(),
00344             //                                                      isoCurves[curve]->operator[](0).x(),isoCurves[curve]->operator[](0).y());
00345             Point3D<double> controlPoint1((isoCurves[curve]->operator[](lastIndex - 2).x()+0.5) * scaleX, (isoCurves[curve]->operator[](lastIndex - 2).y()+0.5) * scaleY, 0.0);
00346             Point3D<double> startPoint((isoCurves[curve]->operator[](lastIndex - 1).x()+0.5) * scaleX, (isoCurves[curve]->operator[](lastIndex - 1).y()+0.5) * scaleY, 0.0);
00347             Point3D<double> endPoint((isoCurves[curve]->operator[](0).x()+0.5) * scaleX, (isoCurves[curve]->operator[](0).y()+0.5) * scaleY, 0.0);
00348             Point3D<double> controlPoint2((isoCurves[curve]->operator[](1).x()+0.5) * scaleX, (isoCurves[curve]->operator[](1).y()+0.5) * scaleY, 0.0);
00349             paint.drawPoints(cardinalSpline(controlPoint1, startPoint, endPoint, controlPoint2, maxPoints));
00350             // between first and second points
00351             //qDebug("drawing spline between (%f, %f) and (%f, %f)",isoCurves[curve]->operator[](0).x(),isoCurves[curve]->operator[](0).y(),
00352             //                                                      isoCurves[curve]->operator[](1).x(),isoCurves[curve]->operator[](1).y());
00353             controlPoint1 = startPoint;
00354             startPoint = endPoint;
00355             endPoint = controlPoint2;
00356             controlPoint2.setValues((isoCurves[curve]->operator[](2).x()+0.5) * scaleX, (isoCurves[curve]->operator[](2).y()+0.5) * scaleY, 0.0);
00357             paint.drawPoints(cardinalSpline(controlPoint1, startPoint, endPoint, controlPoint2, maxPoints));
00358           }
00359         }
00360       }
00361     }
00362     */
00363   }
00364 
00366   if(!crosses.empty())
00367   {
00368     // scale from the grid size to the current window size
00369     // scale to the complete frame
00370     //double scaleX = 1.0 / delta.x() / numPoints.x() * drawRect.width();
00371     //double scaleY = 1.0 / delta.y() / numPoints.y() * drawRect.height();
00372     // scale keeping the aspect ratio => WARNING: scaleX and scaleY are changed here !!!
00373     scaleX *= 1.0 / delta.x();
00374     scaleY *= 1.0 / delta.y();
00375     paint.setPen(crossColor);
00376     for(unsigned int i = 0; i < crosses.size(); i++)
00377     {
00379       int centerX = static_cast<int>(crosses[i].x()*scaleX);
00380       //int centerY = contentsRect().height() - static_cast<int>(crosses[i].y()*scaleY);
00381       int centerY = static_cast<int>((numPoints.y()*delta.y() - crosses[i].y())*scaleY);
00382        paint.drawLine(centerX - 5, centerY, centerX + 5, centerY);
00383       paint.drawLine(centerX, centerY - 5, centerX, centerY + 5);
00384     }
00385   }
00386 
00388   if(drawDrag)
00389   {
00390     //qDebug("drawing a rect from (%d, %d) to (%d, %d)", startPosition.x(),startPosition.y(),endPosition.x(),endPosition.y()); 
00391     //paint.setRasterOp(Qt::XorROP);
00392     paint.setBrush(Qt::NoBrush);
00393     paint.setPen(QPen(crossColor, 0, Qt::DashLine));
00394     paint.drawRect(QRect(startPosition, endPosition));
00395     //paint.setRasterOp(Qt::CopyROP);
00396   }
00397 
00399   paint.end();
00400 
00402   bitBlt(this, 0, 0, &pm);
00403 }
00404 
00408 
00410 QPointArray PlotMapLabel::pointCurve(const vector<Point3D<double> >& curve, const bool cubicInterpolation, const double scaleX, const double scaleY, const unsigned int numInterpolated)
00413 {
00414   QPointArray result;
00415 
00416   if(cubicInterpolation && curve.size() > 3)
00417   {
00418     // Cubic interpolation needs at least 4 points 
00419     for(unsigned int i = 1; i < curve.size() - 2; i++)
00420     {
00421       Point3D<double> controlPoint1((curve[i-1].x()+0.5) * scaleX, (curve[i-1].y()+0.5) * scaleY, 0.0);
00422       Point3D<double> startPoint(   (curve[i].x()+0.5)   * scaleX, (curve[i].y()+0.5)   * scaleY, 0.0);
00423       Point3D<double> endPoint(     (curve[i+1].x()+0.5) * scaleX, (curve[i+1].y()+0.5) * scaleY, 0.0);
00424       Point3D<double> controlPoint2((curve[i+2].x()+0.5) * scaleX, (curve[i+2].y()+0.5) * scaleY, 0.0);
00425       if(curve[i-1].x() < Point3D<double>::TOLERANCE && curve[i-1].y() < Point3D<double>::TOLERANCE ||
00426          curve[i].x()   < Point3D<double>::TOLERANCE && curve[i].y()   < Point3D<double>::TOLERANCE ||
00427          curve[i+1].x() < Point3D<double>::TOLERANCE && curve[i+1].y() < Point3D<double>::TOLERANCE ||
00428          curve[i+2].x() < Point3D<double>::TOLERANCE && curve[i+2].y() < Point3D<double>::TOLERANCE)
00429         // never interpolate lines that go through (0,0) as they control Areas
00430         result.putPoints(result.size(), 1, static_cast<int>(startPoint.x()), static_cast<int>(startPoint.y()),
00431                                            static_cast<int>(endPoint.x()), static_cast<int>(endPoint.y())); // might result in some double additions 
00432       else
00433         result.putPoints(result.size(), numInterpolated, cardinalSpline(controlPoint1, startPoint, endPoint, controlPoint2, numInterpolated));
00434     }
00435     // if the last point of the curve is identical to the first point, the curve 
00436     // is circular and two extra segments should be drawn
00437     const unsigned int lastIndex = curve.size() - 1;
00438     if(curve[0].id() == curve[lastIndex].id())
00439     {
00440       // between last and first points
00441       Point3D<double> controlPoint1((curve[lastIndex - 2].x()+0.5) * scaleX, (curve[lastIndex - 2].y()+0.5) * scaleY, 0.0);
00442       Point3D<double> startPoint(   (curve[lastIndex - 1].x()+0.5) * scaleX, (curve[lastIndex - 1].y()+0.5) * scaleY, 0.0);
00443       Point3D<double> endPoint(     (curve[0].x()+0.5)             * scaleX, (curve[0].y()+0.5)             * scaleY, 0.0);
00444       Point3D<double> controlPoint2((curve[1].x()+0.5)             * scaleX, (curve[1].y()+0.5)             * scaleY, 0.0);
00445       if(curve[lastIndex - 2].x()   < Point3D<double>::TOLERANCE && curve[lastIndex - 2].y()   < Point3D<double>::TOLERANCE ||
00446          curve[lastIndex - 1].x()   < Point3D<double>::TOLERANCE && curve[lastIndex - 1].y()   < Point3D<double>::TOLERANCE ||
00447          curve[0].x() < Point3D<double>::TOLERANCE && curve[0].y() < Point3D<double>::TOLERANCE ||
00448          curve[1].x() < Point3D<double>::TOLERANCE && curve[1].y() < Point3D<double>::TOLERANCE)
00449         // never interpolate lines that go through (0,0) as they control Areas
00450         result.putPoints(result.size(), 1, static_cast<int>(startPoint.x()), static_cast<int>(startPoint.y()),
00451                                            static_cast<int>(endPoint.x()), static_cast<int>(endPoint.y())); // might result in some double additions 
00452       else
00453         result.putPoints(result.size(), numInterpolated, cardinalSpline(controlPoint1, startPoint, endPoint, controlPoint2, numInterpolated));
00454       // between first and second points
00455       controlPoint1 = startPoint;
00456       startPoint = endPoint;
00457       endPoint = controlPoint2;
00458       controlPoint2.setValues((curve[2].x()+0.5) * scaleX, (curve[2].y()+0.5) * scaleY, 0.0);
00459       if(curve[lastIndex - 1].x()   < Point3D<double>::TOLERANCE && curve[lastIndex - 1].y()   < Point3D<double>::TOLERANCE ||
00460          curve[0].x() < Point3D<double>::TOLERANCE && curve[0].y() < Point3D<double>::TOLERANCE ||
00461          curve[1].x() < Point3D<double>::TOLERANCE && curve[1].y() < Point3D<double>::TOLERANCE ||
00462          curve[2].x() < Point3D<double>::TOLERANCE && curve[2].y() < Point3D<double>::TOLERANCE)
00463         // never interpolate lines that go through (0,0) as they control Areas
00464         result.putPoints(result.size(), 1, static_cast<int>(startPoint.x()), static_cast<int>(startPoint.y()),
00465                                            static_cast<int>(endPoint.x()), static_cast<int>(endPoint.y())); // might result in some double additions 
00466       else
00467         result.putPoints(result.size(), numInterpolated, cardinalSpline(controlPoint1, startPoint, endPoint, controlPoint2, numInterpolated));
00468     }
00469   }
00470   else if(curve.size() > 1)
00471   {
00472     // Linear interpolation
00473     result.resize(curve.size());
00474     for(unsigned int i = 0; i < curve.size(); i++)
00475       result.setPoint(i, static_cast<int>((curve[i].x()+0.5) * scaleX), static_cast<int>((curve[i].y()+0.5) * scaleY));
00476   }
00477   return result;
00478 }
00479 
00481 QPointArray PlotMapLabel::cardinalSpline(const Point3D<double>& controlPoint1, const Point3D<double>& startPoint, const Point3D<double>& endPoint, const Point3D<double>& controlPoint2, const unsigned int numInterpolated)
00485 {
00486   const double t = 0.0; // defines the type of the Catmull-Rom Spline => 0.0 is a Cardinal Spline
00487                         //                                            => 1.0 is a polyline
00488   const double s = (1.0 - t)/2.0; 
00489 
00490   //int oldx = 100000;
00491   //int oldy = 100000;
00492   QPointArray result(numInterpolated);
00493   //unsigned int numPoints = 0;
00494   for(unsigned int i = 0; i < numInterpolated; i++)
00495   {
00496     const double value = static_cast<double>(i)/numInterpolated;
00497     const double value2 = value*value;
00498     const double value3 = value2*value;
00499     const int x = static_cast<int>(   (    -s*controlPoint1.x() + (2.0 - s)*startPoint.x() +     (s - 2.0)*endPoint.x() + s*controlPoint2.x() ) * value3
00500                                     + ( 2.0*s*controlPoint1.x() + (s - 3.0)*startPoint.x() + (3.0 - 2.0*s)*endPoint.x() - s*controlPoint2.x() ) * value2
00501                                     + (    -s*controlPoint1.x()                            +             s*endPoint.x()                       ) * value
00502                                                                 +           startPoint.x()  
00503                                   );
00504     const int y = static_cast<int>(   (    -s*controlPoint1.y() + (2.0 - s)*startPoint.y() +     (s - 2.0)*endPoint.y() + s*controlPoint2.y() ) * value3
00505                                     + ( 2.0*s*controlPoint1.y() + (s - 3.0)*startPoint.y() + (3.0 - 2.0*s)*endPoint.y() - s*controlPoint2.y() ) * value2
00506                                     + (    -s*controlPoint1.y()                            +             s*endPoint.y()                       ) * value
00507                                                                 +           startPoint.y()  
00508                                   );
00509     result.setPoint(i, x, y);
00510     //if(x != oldx && y!= oldy)
00511     //{
00512     //  result.resize(numPoints+1, QGArray::SpeedOptim);
00513     //  result.setPoint(numPoints++,QPoint(x,y));
00514     //  oldx = x;
00515     //  oldy = y;
00516     //}
00517   }
00518   return result;
00519 }
00520 

Generated on Fri May 19 14:31:55 2006 for Brabosphere by  doxygen 1.4.6-NO