qwt_raster_data.cpp
Go to the documentation of this file.
00001 /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
00002  * Qwt Widget Library
00003  * Copyright (C) 1997   Josef Wilgen
00004  * Copyright (C) 2002   Uwe Rathmann
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the Qwt License, Version 1.0
00008  *****************************************************************************/
00009 
00010 #include "qwt_raster_data.h"
00011 #include "qwt_point_3d.h"
00012 #include <qnumeric.h>
00013 
00014 class QwtRasterData::ContourPlane
00015 {
00016 public:
00017     explicit inline ContourPlane( double z ):
00018         d_z( z )
00019     {
00020     }
00021 
00022     inline bool intersect( const QwtPoint3D vertex[3],
00023         QPointF line[2], bool ignoreOnPlane ) const;
00024 
00025     inline double z() const { return d_z; }
00026 
00027 private:
00028     inline int compare( double z ) const;
00029     inline QPointF intersection(
00030         const QwtPoint3D& p1, const QwtPoint3D &p2 ) const;
00031 
00032     double d_z;
00033 };
00034 
00035 inline bool QwtRasterData::ContourPlane::intersect(
00036     const QwtPoint3D vertex[3], QPointF line[2],
00037     bool ignoreOnPlane ) const
00038 {
00039     bool found = true;
00040 
00041     // Are the vertices below (-1), on (0) or above (1) the plan ?
00042     const int eq1 = compare( vertex[0].z() );
00043     const int eq2 = compare( vertex[1].z() );
00044     const int eq3 = compare( vertex[2].z() );
00045 
00046     /*
00047         (a) All the vertices lie below the contour level.
00048         (b) Two vertices lie below and one on the contour level.
00049         (c) Two vertices lie below and one above the contour level.
00050         (d) One vertex lies below and two on the contour level.
00051         (e) One vertex lies below, one on and one above the contour level.
00052         (f) One vertex lies below and two above the contour level.
00053         (g) Three vertices lie on the contour level.
00054         (h) Two vertices lie on and one above the contour level.
00055         (i) One vertex lies on and two above the contour level.
00056         (j) All the vertices lie above the contour level.
00057      */
00058 
00059     static const int tab[3][3][3] =
00060     {
00061         // jump table to avoid nested case statements
00062         { { 0, 0, 8 }, { 0, 2, 5 }, { 7, 6, 9 } },
00063         { { 0, 3, 4 }, { 1, 10, 1 }, { 4, 3, 0 } },
00064         { { 9, 6, 7 }, { 5, 2, 0 }, { 8, 0, 0 } }
00065     };
00066 
00067     const int edgeType = tab[eq1+1][eq2+1][eq3+1];
00068     switch ( edgeType )
00069     {
00070         case 1:
00071             // d(0,0,-1), h(0,0,1)
00072             line[0] = vertex[0].toPoint();
00073             line[1] = vertex[1].toPoint();
00074             break;
00075         case 2:
00076             // d(-1,0,0), h(1,0,0)
00077             line[0] = vertex[1].toPoint();
00078             line[1] = vertex[2].toPoint();
00079             break;
00080         case 3:
00081             // d(0,-1,0), h(0,1,0)
00082             line[0] = vertex[2].toPoint();
00083             line[1] = vertex[0].toPoint();
00084             break;
00085         case 4:
00086             // e(0,-1,1), e(0,1,-1)
00087             line[0] = vertex[0].toPoint();
00088             line[1] = intersection( vertex[1], vertex[2] );
00089             break;
00090         case 5:
00091             // e(-1,0,1), e(1,0,-1)
00092             line[0] = vertex[1].toPoint();
00093             line[1] = intersection( vertex[2], vertex[0] );
00094             break;
00095         case 6:
00096             // e(-1,1,0), e(1,0,-1)
00097             line[0] = vertex[2].toPoint();
00098             line[1] = intersection( vertex[0], vertex[1] );
00099             break;
00100         case 7:
00101             // c(-1,1,-1), f(1,1,-1)
00102             line[0] = intersection( vertex[0], vertex[1] );
00103             line[1] = intersection( vertex[1], vertex[2] );
00104             break;
00105         case 8:
00106             // c(-1,-1,1), f(1,1,-1)
00107             line[0] = intersection( vertex[1], vertex[2] );
00108             line[1] = intersection( vertex[2], vertex[0] );
00109             break;
00110         case 9:
00111             // f(-1,1,1), c(1,-1,-1)
00112             line[0] = intersection( vertex[2], vertex[0] );
00113             line[1] = intersection( vertex[0], vertex[1] );
00114             break;
00115         case 10:
00116             // g(0,0,0)
00117             // The CONREC algorithm has no satisfying solution for
00118             // what to do, when all vertices are on the plane.
00119 
00120             if ( ignoreOnPlane )
00121                 found = false;
00122             else
00123             {
00124                 line[0] = vertex[2].toPoint();
00125                 line[1] = vertex[0].toPoint();
00126             }
00127             break;
00128         default:
00129             found = false;
00130     }
00131 
00132     return found;
00133 }
00134 
00135 inline int QwtRasterData::ContourPlane::compare( double z ) const
00136 {
00137     if ( z > d_z )
00138         return 1;
00139 
00140     if ( z < d_z )
00141         return -1;
00142 
00143     return 0;
00144 }
00145 
00146 inline QPointF QwtRasterData::ContourPlane::intersection(
00147     const QwtPoint3D& p1, const QwtPoint3D &p2 ) const
00148 {
00149     const double h1 = p1.z() - d_z;
00150     const double h2 = p2.z() - d_z;
00151 
00152     const double x = ( h2 * p1.x() - h1 * p2.x() ) / ( h2 - h1 );
00153     const double y = ( h2 * p1.y() - h1 * p2.y() ) / ( h2 - h1 );
00154 
00155     return QPointF( x, y );
00156 }
00157 
00158 class QwtRasterData::PrivateData
00159 {
00160 public:
00161     QwtRasterData::Attributes attributes;
00162 };  
00163 
00165 QwtRasterData::QwtRasterData()
00166 {
00167     d_data = new PrivateData();
00168 }
00169 
00171 QwtRasterData::~QwtRasterData()
00172 {
00173     delete d_data;
00174 }
00175 
00183 void QwtRasterData::setAttribute( Attribute attribute, bool on )
00184 {
00185     if ( on )
00186         d_data->attributes |= attribute;
00187     else
00188         d_data->attributes &= ~attribute;
00189 }
00190 
00195 bool QwtRasterData::testAttribute( Attribute attribute ) const
00196 {
00197     return d_data->attributes & attribute;
00198 }
00199 
00215 void QwtRasterData::initRaster( const QRectF &area, const QSize &raster )
00216 {
00217     Q_UNUSED( area );
00218     Q_UNUSED( raster );
00219 }
00220 
00231 void QwtRasterData::discardRaster()
00232 {
00233 }
00234 
00261 QRectF QwtRasterData::pixelHint( const QRectF &area ) const
00262 {
00263     Q_UNUSED( area );
00264     return QRectF(); 
00265 }
00266 
00280 QwtRasterData::ContourLines QwtRasterData::contourLines(
00281     const QRectF &rect, const QSize &raster,
00282     const QList<double> &levels, ConrecFlags flags ) const
00283 {
00284     ContourLines contourLines;
00285 
00286     if ( levels.size() == 0 || !rect.isValid() || !raster.isValid() )
00287         return contourLines;
00288 
00289     const double dx = rect.width() / raster.width();
00290     const double dy = rect.height() / raster.height();
00291 
00292     const bool ignoreOnPlane =
00293         flags & QwtRasterData::IgnoreAllVerticesOnLevel;
00294 
00295     const QwtInterval range = interval( Qt::ZAxis );
00296     bool ignoreOutOfRange = false;
00297     if ( range.isValid() )
00298         ignoreOutOfRange = flags & IgnoreOutOfRange;
00299 
00300     QwtRasterData *that = const_cast<QwtRasterData *>( this );
00301     that->initRaster( rect, raster );
00302 
00303     for ( int y = 0; y < raster.height() - 1; y++ )
00304     {
00305         enum Position
00306         {
00307             Center,
00308 
00309             TopLeft,
00310             TopRight,
00311             BottomRight,
00312             BottomLeft,
00313 
00314             NumPositions
00315         };
00316 
00317         QwtPoint3D xy[NumPositions];
00318 
00319         for ( int x = 0; x < raster.width() - 1; x++ )
00320         {
00321             const QPointF pos( rect.x() + x * dx, rect.y() + y * dy );
00322 
00323             if ( x == 0 )
00324             {
00325                 xy[TopRight].setX( pos.x() );
00326                 xy[TopRight].setY( pos.y() );
00327                 xy[TopRight].setZ(
00328                     value( xy[TopRight].x(), xy[TopRight].y() )
00329                 );
00330 
00331                 xy[BottomRight].setX( pos.x() );
00332                 xy[BottomRight].setY( pos.y() + dy );
00333                 xy[BottomRight].setZ(
00334                     value( xy[BottomRight].x(), xy[BottomRight].y() )
00335                 );
00336             }
00337 
00338             xy[TopLeft] = xy[TopRight];
00339             xy[BottomLeft] = xy[BottomRight];
00340 
00341             xy[TopRight].setX( pos.x() + dx );
00342             xy[TopRight].setY( pos.y() );
00343             xy[BottomRight].setX( pos.x() + dx );
00344             xy[BottomRight].setY( pos.y() + dy );
00345 
00346             xy[TopRight].setZ(
00347                 value( xy[TopRight].x(), xy[TopRight].y() )
00348             );
00349             xy[BottomRight].setZ(
00350                 value( xy[BottomRight].x(), xy[BottomRight].y() )
00351             );
00352 
00353             double zMin = xy[TopLeft].z();
00354             double zMax = zMin;
00355             double zSum = zMin;
00356 
00357             for ( int i = TopRight; i <= BottomLeft; i++ )
00358             {
00359                 const double z = xy[i].z();
00360 
00361                 zSum += z;
00362                 if ( z < zMin )
00363                     zMin = z;
00364                 if ( z > zMax )
00365                     zMax = z;
00366             }
00367 
00368             if ( qIsNaN( zSum ) )
00369             {
00370                 // one of the points is NaN
00371                 continue;
00372             }
00373 
00374             if ( ignoreOutOfRange )
00375             {
00376                 if ( !range.contains( zMin ) || !range.contains( zMax ) )
00377                     continue;
00378             }
00379 
00380             if ( zMax < levels[0] ||
00381                 zMin > levels[levels.size() - 1] )
00382             {
00383                 continue;
00384             }
00385 
00386             xy[Center].setX( pos.x() + 0.5 * dx );
00387             xy[Center].setY( pos.y() + 0.5 * dy );
00388             xy[Center].setZ( 0.25 * zSum );
00389 
00390             const int numLevels = levels.size();
00391             for ( int l = 0; l < numLevels; l++ )
00392             {
00393                 const double level = levels[l];
00394                 if ( level < zMin || level > zMax )
00395                     continue;
00396                 QPolygonF &lines = contourLines[level];
00397                 const ContourPlane plane( level );
00398 
00399                 QPointF line[2];
00400                 QwtPoint3D vertex[3];
00401 
00402                 for ( int m = TopLeft; m < NumPositions; m++ )
00403                 {
00404                     vertex[0] = xy[m];
00405                     vertex[1] = xy[0];
00406                     vertex[2] = xy[m != BottomLeft ? m + 1 : TopLeft];
00407 
00408                     const bool intersects =
00409                         plane.intersect( vertex, line, ignoreOnPlane );
00410                     if ( intersects )
00411                     {
00412                         lines += line[0];
00413                         lines += line[1];
00414                     }
00415                 }
00416             }
00417         }
00418     }
00419 
00420     that->discardRaster();
00421 
00422     return contourLines;
00423 }


plotjuggler
Author(s): Davide Faconti
autogenerated on Fri Sep 1 2017 02:41:56