00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "qwt_raster_data.h"
00011
00012 class QwtRasterData::Contour3DPoint
00013 {
00014 public:
00015 inline void setPos(double x, double y)
00016 {
00017 d_x = x;
00018 d_y = y;
00019 }
00020
00021 inline QwtDoublePoint pos() const
00022 {
00023 return QwtDoublePoint(d_x, d_y);
00024 }
00025
00026 inline void setX(double x) { d_x = x; }
00027 inline void setY(double y) { d_y = y; }
00028 inline void setZ(double z) { d_z = z; }
00029
00030 inline double x() const { return d_x; }
00031 inline double y() const { return d_y; }
00032 inline double z() const { return d_z; }
00033
00034 private:
00035 double d_x;
00036 double d_y;
00037 double d_z;
00038 };
00039
00040 class QwtRasterData::ContourPlane
00041 {
00042 public:
00043 inline ContourPlane(double z):
00044 d_z(z)
00045 {
00046 }
00047
00048 inline bool intersect(const Contour3DPoint vertex[3],
00049 QwtDoublePoint line[2], bool ignoreOnPlane) const;
00050
00051 inline double z() const { return d_z; }
00052
00053 private:
00054 inline int compare(double z) const;
00055 inline QwtDoublePoint intersection(
00056 const Contour3DPoint& p1, const Contour3DPoint &p2) const;
00057
00058 double d_z;
00059 };
00060
00061 inline bool QwtRasterData::ContourPlane::intersect(
00062 const Contour3DPoint vertex[3], QwtDoublePoint line[2],
00063 bool ignoreOnPlane) const
00064 {
00065 bool found = true;
00066
00067
00068 const int eq1 = compare(vertex[0].z());
00069 const int eq2 = compare(vertex[1].z());
00070 const int eq3 = compare(vertex[2].z());
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 static const int tab[3][3][3] =
00086 {
00087
00088 { { 0, 0, 8 }, { 0, 2, 5 }, { 7, 6, 9 } },
00089 { { 0, 3, 4 }, { 1, 10, 1 }, { 4, 3, 0 } },
00090 { { 9, 6, 7 }, { 5, 2, 0 }, { 8, 0, 0 } }
00091 };
00092
00093 const int edgeType = tab[eq1+1][eq2+1][eq3+1];
00094 switch (edgeType)
00095 {
00096 case 1:
00097
00098 line[0] = vertex[0].pos();
00099 line[1] = vertex[1].pos();
00100 break;
00101 case 2:
00102
00103 line[0] = vertex[1].pos();
00104 line[1] = vertex[2].pos();
00105 break;
00106 case 3:
00107
00108 line[0] = vertex[2].pos();
00109 line[1] = vertex[0].pos();
00110 break;
00111 case 4:
00112
00113 line[0] = vertex[0].pos();
00114 line[1] = intersection(vertex[1], vertex[2]);
00115 break;
00116 case 5:
00117
00118 line[0] = vertex[1].pos();
00119 line[1] = intersection(vertex[2], vertex[0]);
00120 break;
00121 case 6:
00122
00123 line[0] = vertex[1].pos();
00124 line[1] = intersection(vertex[0], vertex[1]);
00125 break;
00126 case 7:
00127
00128 line[0] = intersection(vertex[0], vertex[1]);
00129 line[1] = intersection(vertex[1], vertex[2]);
00130 break;
00131 case 8:
00132
00133 line[0] = intersection(vertex[1], vertex[2]);
00134 line[1] = intersection(vertex[2], vertex[0]);
00135 break;
00136 case 9:
00137
00138 line[0] = intersection(vertex[2], vertex[0]);
00139 line[1] = intersection(vertex[0], vertex[1]);
00140 break;
00141 case 10:
00142
00143
00144
00145
00146 if ( ignoreOnPlane )
00147 found = false;
00148 else
00149 {
00150 line[0] = vertex[2].pos();
00151 line[1] = vertex[0].pos();
00152 }
00153 break;
00154 default:
00155 found = false;
00156 }
00157
00158 return found;
00159 }
00160
00161 inline int QwtRasterData::ContourPlane::compare(double z) const
00162 {
00163 if (z > d_z)
00164 return 1;
00165
00166 if (z < d_z)
00167 return -1;
00168
00169 return 0;
00170 }
00171
00172 inline QwtDoublePoint QwtRasterData::ContourPlane::intersection(
00173 const Contour3DPoint& p1, const Contour3DPoint &p2) const
00174 {
00175 const double h1 = p1.z() - d_z;
00176 const double h2 = p2.z() - d_z;
00177
00178 const double x = (h2 * p1.x() - h1 * p2.x()) / (h2 - h1);
00179 const double y = (h2 * p1.y() - h1 * p2.y()) / (h2 - h1);
00180
00181 return QwtDoublePoint(x, y);
00182 }
00183
00185 QwtRasterData::QwtRasterData()
00186 {
00187 }
00188
00195 QwtRasterData::QwtRasterData(const QwtDoubleRect &boundingRect):
00196 d_boundingRect(boundingRect)
00197 {
00198 }
00199
00201 QwtRasterData::~QwtRasterData()
00202 {
00203 }
00204
00211 void QwtRasterData::setBoundingRect(const QwtDoubleRect &boundingRect)
00212 {
00213 d_boundingRect = boundingRect;
00214 }
00215
00220 QwtDoubleRect QwtRasterData::boundingRect() const
00221 {
00222 return d_boundingRect;
00223 }
00224
00240 void QwtRasterData::initRaster(const QwtDoubleRect &, const QSize&)
00241 {
00242 }
00243
00254 void QwtRasterData::discardRaster()
00255 {
00256 }
00257
00276 QSize QwtRasterData::rasterHint(const QwtDoubleRect &) const
00277 {
00278 return QSize();
00279 }
00280
00287 #if QT_VERSION >= 0x040000
00288 QwtRasterData::ContourLines QwtRasterData::contourLines(
00289 const QwtDoubleRect &rect, const QSize &raster,
00290 const QList<double> &levels, int flags) const
00291 #else
00292 QwtRasterData::ContourLines QwtRasterData::contourLines(
00293 const QwtDoubleRect &rect, const QSize &raster,
00294 const QValueList<double> &levels, int flags) const
00295 #endif
00296 {
00297 ContourLines contourLines;
00298
00299 if ( levels.size() == 0 || !rect.isValid() || !raster.isValid() )
00300 return contourLines;
00301
00302 const double dx = rect.width() / raster.width();
00303 const double dy = rect.height() / raster.height();
00304
00305 const bool ignoreOnPlane =
00306 flags & QwtRasterData::IgnoreAllVerticesOnLevel;
00307
00308 const QwtDoubleInterval range = this->range();
00309 bool ignoreOutOfRange = false;
00310 if ( range.isValid() )
00311 ignoreOutOfRange = flags & IgnoreOutOfRange;
00312
00313 ((QwtRasterData*)this)->initRaster(rect, raster);
00314
00315 for ( int y = 0; y < raster.height() - 1; y++ )
00316 {
00317 enum Position
00318 {
00319 Center,
00320
00321 TopLeft,
00322 TopRight,
00323 BottomRight,
00324 BottomLeft,
00325
00326 NumPositions
00327 };
00328
00329 Contour3DPoint xy[NumPositions];
00330
00331 for ( int x = 0; x < raster.width() - 1; x++ )
00332 {
00333 const QwtDoublePoint pos(rect.x() + x * dx, rect.y() + y * dy);
00334
00335 if ( x == 0 )
00336 {
00337 xy[TopRight].setPos(pos.x(), pos.y());
00338 xy[TopRight].setZ(
00339 value( xy[TopRight].x(), xy[TopRight].y())
00340 );
00341
00342 xy[BottomRight].setPos(pos.x(), pos.y() + dy);
00343 xy[BottomRight].setZ(
00344 value(xy[BottomRight].x(), xy[BottomRight].y())
00345 );
00346 }
00347
00348 xy[TopLeft] = xy[TopRight];
00349 xy[BottomLeft] = xy[BottomRight];
00350
00351 xy[TopRight].setPos(pos.x() + dx, pos.y());
00352 xy[BottomRight].setPos(pos.x() + dx, pos.y() + dy);
00353
00354 xy[TopRight].setZ(
00355 value(xy[TopRight].x(), xy[TopRight].y())
00356 );
00357 xy[BottomRight].setZ(
00358 value(xy[BottomRight].x(), xy[BottomRight].y())
00359 );
00360
00361 double zMin = xy[TopLeft].z();
00362 double zMax = zMin;
00363 double zSum = zMin;
00364
00365 for ( int i = TopRight; i <= BottomLeft; i++ )
00366 {
00367 const double z = xy[i].z();
00368
00369 zSum += z;
00370 if ( z < zMin )
00371 zMin = z;
00372 if ( z > zMax )
00373 zMax = z;
00374 }
00375
00376 if ( ignoreOutOfRange )
00377 {
00378 if ( !range.contains(zMin) || !range.contains(zMax) )
00379 continue;
00380 }
00381
00382 if ( zMax < levels[0] ||
00383 zMin > levels[levels.size() - 1] )
00384 {
00385 continue;
00386 }
00387
00388 xy[Center].setPos(pos.x() + 0.5 * dx, pos.y() + 0.5 * dy);
00389 xy[Center].setZ(0.25 * zSum);
00390 const int numLevels = (int)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 #if QT_VERSION >= 0x040000
00397 QPolygonF &lines = contourLines[level];
00398 #else
00399 QwtArray<QwtDoublePoint> &lines = contourLines[level];
00400 #endif
00401 const ContourPlane plane(level);
00402
00403 QwtDoublePoint line[2];
00404 Contour3DPoint vertex[3];
00405
00406 for (int m = TopLeft; m < NumPositions; m++)
00407 {
00408 vertex[0] = xy[m];
00409 vertex[1] = xy[0];
00410 vertex[2] = xy[m != BottomLeft ? m + 1 : TopLeft];
00411
00412 const bool intersects =
00413 plane.intersect(vertex, line, ignoreOnPlane);
00414 if ( intersects )
00415 {
00416 #if QT_VERSION >= 0x040000
00417 lines += line[0];
00418 lines += line[1];
00419 #else
00420 const int index = lines.size();
00421 lines.resize(lines.size() + 2, QGArray::SpeedOptim);
00422
00423 lines[index] = line[0];
00424 lines[index+1] = line[1];
00425 #endif
00426 }
00427 }
00428 }
00429 }
00430 }
00431
00432 ((QwtRasterData*)this)->discardRaster();
00433
00434 return contourLines;
00435 }