Back to index

salome-gui  6.5.0
Plot2d.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 
00020 // File   : Plot2d.cxx
00021 // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
00022 //
00023 #include "Plot2d.h"
00024 
00025 #include <QPainter>
00026 
00027 #include <qwt_plot.h>
00028 #include <qwt_plot_curve.h>
00029 
00030 const int MSIZE  = 9;
00031 const int MAX_ATTEMPTS        = 10;     // max attempts
00032 
00033 // color tolerance (used to compare color values)
00034 const long COLOR_DISTANCE = 100;
00035 
00036 
00037 
00041 Plot2d_Point::Plot2d_Point()
00042   : x( 0. ), y( 0. ), deviationPtr(0)
00043 {
00044 }
00045 
00049 Plot2d_Point::Plot2d_Point( double theX, double theY, const QString& theText )
00050   : x( theX ), y( theY ), text( theText ), deviationPtr(0)
00051 {
00052 }
00053 
00057 Plot2d_Point::~Plot2d_Point() {
00058   clearDeviation();
00059 }
00060 
00064 void Plot2d_Point::clearDeviation() {
00065   if(deviationPtr)
00066     delete deviationPtr;
00067   deviationPtr = 0;
00068 }
00069 
00073 bool Plot2d_Point::hasDeviation() const {
00074   return !(deviationPtr == 0);
00075 }
00076 
00080 void Plot2d_Point::setDeviation(double min, double max) {
00081  clearDeviation();
00082  deviationPtr = new double[2];
00083  deviationPtr[0] = min;deviationPtr[1] = max;
00084 }
00085 
00090 bool Plot2d_Point::deviation(double& min, double& max) const {
00091   if(hasDeviation()) {
00092     min = deviationPtr[0];
00093     max = deviationPtr[1];
00094   }
00095   return false;
00096 }
00097 
00101 bool Plot2d_Point::minDeviation(double& min) const {
00102   if(hasDeviation()) {
00103     min = deviationPtr[0];
00104     return true;
00105   } else {
00106     min = 0;
00107   }
00108   return false;
00109 }
00110 
00114 bool Plot2d_Point::maxDeviation(double& max) const {
00115   if(hasDeviation()) {
00116     max = deviationPtr[1];
00117     return true;
00118   } else {
00119     max = 0;
00120   }
00121   return false;
00122 }
00123 
00124 
00125 
00131 QwtSymbol::Style Plot2d::plot2qwtMarker( Plot2d::MarkerType m )
00132 {
00133   QwtSymbol::Style ms = QwtSymbol::NoSymbol;  
00134   switch ( m ) {
00135   case Plot2d::Circle:
00136     ms = QwtSymbol::Ellipse;   break;
00137   case Plot2d::Rectangle:
00138     ms = QwtSymbol::Rect;      break;
00139   case Plot2d::Diamond:
00140     ms = QwtSymbol::Diamond;   break;
00141   case Plot2d::DTriangle:
00142     ms = QwtSymbol::DTriangle; break;
00143   case Plot2d::UTriangle:
00144     ms = QwtSymbol::UTriangle; break;
00145   case Plot2d::LTriangle:
00146     ms = QwtSymbol::LTriangle; break;
00147   case Plot2d::RTriangle:
00148     ms = QwtSymbol::RTriangle; break;
00149   case Plot2d::Cross:
00150     ms = QwtSymbol::Cross;     break;
00151   case Plot2d::XCross:
00152     ms = QwtSymbol::XCross;    break;
00153   case Plot2d::None:
00154   default:
00155     ms = QwtSymbol::NoSymbol;  break;
00156   }
00157   return ms;
00158 }
00159 
00165 Plot2d::MarkerType Plot2d::qwt2plotMarker( QwtSymbol::Style m )
00166 {
00167   Plot2d::MarkerType ms = Plot2d::None;  
00168   switch ( m ) {
00169   case QwtSymbol::Ellipse:
00170     ms = Plot2d::Circle;    break;
00171   case QwtSymbol::Rect:
00172     ms = Plot2d::Rectangle; break;
00173   case QwtSymbol::Diamond:
00174     ms = Plot2d::Diamond;   break;
00175   case QwtSymbol::DTriangle:
00176     ms = Plot2d::DTriangle; break;
00177   case QwtSymbol::UTriangle:
00178     ms = Plot2d::UTriangle; break;
00179   case QwtSymbol::RTriangle:
00180     ms = Plot2d::RTriangle; break;
00181   case QwtSymbol::LTriangle:
00182     ms = Plot2d::LTriangle; break;
00183   case QwtSymbol::Cross:
00184     ms = Plot2d::Cross;     break;
00185   case QwtSymbol::XCross:
00186     ms = Plot2d::XCross;    break;
00187   case QwtSymbol::NoSymbol:
00188   default:
00189     ms = Plot2d::None;      break;
00190   }
00191   return ms;
00192 }
00193 
00199 Qt::PenStyle Plot2d::plot2qwtLine( Plot2d::LineType p )
00200 {
00201   Qt::PenStyle ps = Qt::NoPen;
00202   switch ( p ) {
00203   case Plot2d::Solid:
00204     ps = Qt::SolidLine;      break;
00205   case Plot2d::Dash:
00206     ps = Qt::DashLine;       break;
00207   case Plot2d::Dot:
00208     ps = Qt::DotLine;        break;
00209   case Plot2d::DashDot:
00210     ps = Qt::DashDotLine;    break;
00211   case Plot2d::DashDotDot:
00212     ps = Qt::DashDotDotLine; break;
00213   case Plot2d::NoPen:
00214   default:
00215     ps = Qt::NoPen;          break;
00216   }
00217   return ps;
00218 }
00219 
00225 Plot2d::LineType Plot2d::qwt2plotLine( Qt::PenStyle p )
00226 {
00227   Plot2d::LineType ps = Plot2d::NoPen;
00228   switch ( p ) {
00229   case Qt::SolidLine:
00230     ps = Plot2d::Solid;      break;
00231   case Qt::DashLine:
00232     ps = Plot2d::Dash;       break;
00233   case Qt::DotLine:
00234     ps = Plot2d::Dot;        break;
00235   case Qt::DashDotLine:
00236     ps = Plot2d::DashDot;    break;
00237   case Qt::DashDotDotLine:
00238     ps = Plot2d::DashDotDot; break;
00239   case Qt::NoPen:
00240   default:
00241     ps = Plot2d::NoPen;      break;
00242   }
00243   return ps;
00244 }
00245 
00255 void Plot2d::drawLine( QPainter* painter, const QPoint& p1, const QPoint& p2, 
00256                        Qt::PenStyle type, const QColor& color, int width )
00257 {
00258   painter->save();
00259   QPen pen( type );
00260   pen.setColor( color );
00261   pen.setWidth( width );
00262   painter->setPen( pen );
00263   painter->drawLine( p1, p2 );
00264   painter->restore();
00265 }
00266 
00276 void Plot2d::drawLine( QPainter* painter, const QPoint& p1, const QPoint& p2, 
00277                        Plot2d::LineType type, const QColor& color, int width )
00278 {
00279   drawLine( painter, p1, p2, plot2qwtLine( type ), color, width );
00280 }
00281 
00293 void Plot2d::drawLine( QPainter* painter, int x1, int y1, int x2, int y2,
00294                        Qt::PenStyle type, const QColor& color, int width )
00295 {
00296   drawLine( painter, QPoint( x1, y1 ), QPoint( x2, y2 ), type, color, width );
00297 }
00298 
00310 void Plot2d::drawLine( QPainter* painter, int x1, int y1, int x2, int y2,
00311                        Plot2d::LineType type, const QColor& color, int width )
00312 {
00313   drawLine( painter, QPoint( x1, y1 ), QPoint( x2, y2 ), 
00314             plot2qwtLine( type), color, width );
00315 }
00316 
00325 void Plot2d::drawMarker( QPainter* painter, const QPoint& p, const QRect& r,
00326                          QwtSymbol::Style type, const QColor& color )
00327 {
00328   painter->save();
00329   painter->setPen( color );
00330   painter->setBrush( color );
00331   
00332   QRect ar = r;
00333   ar.moveCenter( p );
00334   const int w2 = ar.width()  / 2;
00335   const int h2 = ar.height() / 2;
00336 
00337   switch( type ) {
00338   case QwtSymbol::Ellipse:
00339     painter->drawEllipse( ar );
00340     break;
00341   case QwtSymbol::Rect:
00342     painter->drawRect( ar );
00343     painter->fillRect( ar, QBrush( color ) );
00344     break;
00345   case QwtSymbol::Diamond:
00346     {
00347       QPolygon polygon;
00348       polygon << QPoint( ar.x() + w2, ar.y() );
00349       polygon << QPoint( ar.right(), ar.y() + h2 );
00350       polygon << QPoint( ar.x() + w2, ar.bottom() );
00351       polygon << QPoint( ar.x(), ar.y() + h2 );
00352       painter->drawPolygon( polygon );
00353       break;
00354     }
00355   case QwtSymbol::Cross:
00356     painter->drawLine( ar.left() + w2, ar.top(), ar.left() + w2, ar.bottom() );
00357     painter->drawLine( ar.left(), ar.top() + h2, ar.right(), ar.top() + h2 );
00358     break;
00359   case QwtSymbol::XCross:
00360     painter->drawLine( ar.left(), ar.top(), ar.right(), ar.bottom() );
00361     painter->drawLine( ar.left(), ar.bottom(), ar.right(), ar.top() );
00362     break;
00363   case QwtSymbol::UTriangle:
00364     {
00365       QPolygon polygon;
00366       polygon << QPoint( ar.left() + w2, ar.top() );
00367       polygon << QPoint( ar.right(), ar.bottom() );
00368       polygon << QPoint( ar.left(), ar.bottom() );
00369       painter->drawPolygon( polygon );
00370       break;
00371     }
00372   case QwtSymbol::DTriangle:
00373     {
00374       QPolygon polygon;
00375       polygon << QPoint( ar.left() + w2, ar.bottom() );
00376       polygon << QPoint( ar.right(), ar.top() );
00377       polygon << QPoint( ar.left(), ar.top() );
00378       painter->drawPolygon( polygon );
00379       break;
00380     }
00381   case QwtSymbol::RTriangle:
00382     {
00383       QPolygon polygon;
00384       polygon << QPoint( ar.left(), ar.top() );
00385       polygon << QPoint( ar.right(), ar.top() + h2 );
00386       polygon << QPoint( ar.left(), ar.bottom() );
00387       painter->drawPolygon( polygon );
00388       break;
00389     }
00390   case QwtSymbol::LTriangle:
00391     {
00392       QPolygon polygon;
00393       polygon << QPoint( ar.left(), ar.top() + h2 );
00394       polygon << QPoint( ar.right(), ar.top() );
00395       polygon << QPoint( ar.right(), ar.bottom() );
00396       painter->drawPolygon( polygon );
00397       break;
00398     }
00399   default:
00400     break;
00401   }
00402   painter->restore();
00403 }
00404 
00413 void Plot2d::drawMarker( QPainter* painter, const QPoint& p, const QRect& r,
00414                          Plot2d::MarkerType type, const QColor& color )
00415 {
00416   drawMarker( painter, p, r, plot2qwtMarker( type ), color ); 
00417 }
00418 
00429 void Plot2d::drawMarker( QPainter* painter, int x, int y, int w, int h,
00430                          QwtSymbol::Style type, const QColor& color )
00431 {
00432   drawMarker( painter, QPoint( x, y ), QRect( 0, 0, w, h ), type, color ); 
00433 }
00434 
00445 void Plot2d::drawMarker( QPainter* painter, int x, int y, int w, int h,
00446                          Plot2d::MarkerType type, const QColor& color )
00447 {
00448   drawMarker( painter, QPoint( x, y ), QRect( 0, 0, w, h ), plot2qwtMarker( type ), color ); 
00449 }
00450 
00451 
00459 QPixmap Plot2d::markerIcon(const QSize &size, const QColor& color, Plot2d::MarkerType type )
00460 {
00461 
00462   QPixmap px( size );
00463   px.fill( QColor( 255, 255, 255, 0 ) );
00464   QPainter p( &px );
00465   Plot2d::drawMarker( &p, size.width()/2, size.height()/2, MSIZE, MSIZE, type, color );
00466   return px;
00467 }
00468 
00469 
00477 QPixmap Plot2d::lineIcon( const QSize& size,  const QColor& color, Plot2d::LineType type )
00478 {
00479 
00480   QPixmap px( size );
00481   px.fill( QColor( 255, 255, 255, 0 ) );
00482   QPainter p( &px );
00483   drawLine( &p, 5, size.height()/2, size.width()-5, size.height()/2, type,
00484            color, 1 );
00485   return px;
00486 }
00487 
00491 void Plot2d::getNextMarker( const int rtti, const QwtPlot* thePlot, QwtSymbol::Style& typeMarker,
00492                          QColor& color, Qt::PenStyle& typeLine ) 
00493 {
00494   bool bOk = false;
00495   int cnt = 0;
00496   while ( !bOk ) {
00497     int aRed    = (int)( 256.0 * rand() / RAND_MAX );  // generate random color
00498     int aGreen  = (int)( 256.0 * rand() / RAND_MAX );  // ...
00499     int aBlue   = (int)( 256.0 * rand() / RAND_MAX );  // ...
00500     int aMarker = (int)( 9.0 * rand() / RAND_MAX ) + 1;// 9 markers types( not including empty )
00501     int aLine   = (int)( 5.0 * rand() / RAND_MAX ) + 1;// 5 line types ( not including empty )
00502     
00503     typeMarker = ( QwtSymbol::Style )aMarker;
00504     color      = QColor( aRed, aGreen, aBlue );
00505     typeLine   = ( Qt::PenStyle )aLine;
00506     
00507     bOk = ( ++cnt == MAX_ATTEMPTS ) || !existMarker( rtti, thePlot, typeMarker, color, typeLine );
00508   }
00509 }
00510 
00514 bool Plot2d::existMarker( const int rtti, const QwtPlot* thePlot, const QwtSymbol::Style typeMarker,
00515                        const QColor& color, const Qt::PenStyle typeLine ) 
00516 {
00517   bool ok = false;
00518   
00519   QColor bgColor = thePlot->palette().color( QPalette::Background );
00520   if ( closeColors( color, bgColor ) ) {
00521     ok = true;
00522   }
00523   else {
00524     QwtPlotItemList anItems = thePlot->itemList();
00525     QwtPlotItemIterator anIt = anItems.begin(), aLast = anItems.end();
00526     QwtPlotItem* anItem;
00527     for ( ; anIt != aLast && !ok; anIt++ ) {
00528       anItem = *anIt;
00529       if ( anItem && anItem->rtti() == rtti ) {
00530        QwtPlotCurve* crv = dynamic_cast<QwtPlotCurve*>( anItem );
00531        if ( crv ) {
00532          QwtSymbol::Style aStyle = crv->symbol().style();
00533          QColor           aColor = crv->pen().color();
00534          Qt::PenStyle     aLine  = crv->pen().style();
00535          ok = closeColors( aColor, color ) && aStyle == typeMarker && aLine == typeLine;
00536        }
00537       }
00538     }
00539   }
00540   return ok;
00541 }
00542 
00548 bool Plot2d::closeColors( const QColor& color1,
00549                        const QColor& color2,
00550                        int distance )
00551 {
00552   long tol = 
00553     qAbs( color2.red()   - color1.red()   ) + 
00554     qAbs( color2.green() - color1.green() ) +
00555     qAbs( color2.blue()  - color1.blue()  ) -
00556     ( distance < 0 ? COLOR_DISTANCE : distance );
00557 
00558   return tol <= 0;
00559 }