00001
00002
00003
00004
00005
00006
00007
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
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
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 static const int tab[3][3][3] =
00060 {
00061
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
00072 line[0] = vertex[0].toPoint();
00073 line[1] = vertex[1].toPoint();
00074 break;
00075 case 2:
00076
00077 line[0] = vertex[1].toPoint();
00078 line[1] = vertex[2].toPoint();
00079 break;
00080 case 3:
00081
00082 line[0] = vertex[2].toPoint();
00083 line[1] = vertex[0].toPoint();
00084 break;
00085 case 4:
00086
00087 line[0] = vertex[0].toPoint();
00088 line[1] = intersection( vertex[1], vertex[2] );
00089 break;
00090 case 5:
00091
00092 line[0] = vertex[1].toPoint();
00093 line[1] = intersection( vertex[2], vertex[0] );
00094 break;
00095 case 6:
00096
00097 line[0] = vertex[2].toPoint();
00098 line[1] = intersection( vertex[0], vertex[1] );
00099 break;
00100 case 7:
00101
00102 line[0] = intersection( vertex[0], vertex[1] );
00103 line[1] = intersection( vertex[1], vertex[2] );
00104 break;
00105 case 8:
00106
00107 line[0] = intersection( vertex[1], vertex[2] );
00108 line[1] = intersection( vertex[2], vertex[0] );
00109 break;
00110 case 9:
00111
00112 line[0] = intersection( vertex[2], vertex[0] );
00113 line[1] = intersection( vertex[0], vertex[1] );
00114 break;
00115 case 10:
00116
00117
00118
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
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 }