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
00184 QwtRasterData::QwtRasterData()
00185 {
00186 }
00187
00188 QwtRasterData::QwtRasterData(const QwtDoubleRect &boundingRect):
00189 d_boundingRect(boundingRect)
00190 {
00191 }
00192
00193 QwtRasterData::~QwtRasterData()
00194 {
00195 }
00196
00197 void QwtRasterData::setBoundingRect(const QwtDoubleRect &boundingRect)
00198 {
00199 d_boundingRect = boundingRect;
00200 }
00201
00202 QwtDoubleRect QwtRasterData::boundingRect() const
00203 {
00204 return d_boundingRect;
00205 }
00206
00222 void QwtRasterData::initRaster(const QwtDoubleRect &, const QSize&)
00223 {
00224 }
00225
00236 void QwtRasterData::discardRaster()
00237 {
00238 }
00239
00258 QSize QwtRasterData::rasterHint(const QwtDoubleRect &) const
00259 {
00260 return QSize();
00261 }
00262
00269 #if QT_VERSION >= 0x040000
00270 QwtRasterData::ContourLines QwtRasterData::contourLines(
00271 const QwtDoubleRect &rect, const QSize &raster,
00272 const QList<double> &levels, int flags) const
00273 #else
00274 QwtRasterData::ContourLines QwtRasterData::contourLines(
00275 const QwtDoubleRect &rect, const QSize &raster,
00276 const QValueList<double> &levels, int flags) const
00277 #endif
00278 {
00279 ContourLines contourLines;
00280
00281 if ( levels.size() == 0 || !rect.isValid() || !raster.isValid() )
00282 return contourLines;
00283
00284 const double dx = rect.width() / raster.width();
00285 const double dy = rect.height() / raster.height();
00286
00287 const bool ignoreOnPlane =
00288 flags & QwtRasterData::IgnoreAllVerticesOnLevel;
00289
00290 const QwtDoubleInterval range = this->range();
00291 bool ignoreOutOfRange = false;
00292 if ( range.isValid() )
00293 ignoreOutOfRange = flags & IgnoreOutOfRange;
00294
00295 ((QwtRasterData*)this)->initRaster(rect, raster);
00296
00297 for ( int y = 0; y < raster.height() - 1; y++ )
00298 {
00299 enum Position
00300 {
00301 Center,
00302
00303 TopLeft,
00304 TopRight,
00305 BottomRight,
00306 BottomLeft,
00307
00308 NumPositions
00309 };
00310
00311 Contour3DPoint xy[NumPositions];
00312
00313 for ( int x = 0; x < raster.width() - 1; x++ )
00314 {
00315 const QwtDoublePoint pos(rect.x() + x * dx, rect.y() + y * dy);
00316
00317 if ( x == 0 )
00318 {
00319 xy[TopRight].setPos(pos.x(), pos.y());
00320 xy[TopRight].setZ(
00321 value( xy[TopRight].x(), xy[TopRight].y())
00322 );
00323
00324 xy[BottomRight].setPos(pos.x(), pos.y() + dy);
00325 xy[BottomRight].setZ(
00326 value(xy[BottomRight].x(), xy[BottomRight].y())
00327 );
00328 }
00329
00330 xy[TopLeft] = xy[TopRight];
00331 xy[BottomLeft] = xy[BottomRight];
00332
00333 xy[TopRight].setPos(pos.x() + dx, pos.y());
00334 xy[BottomRight].setPos(pos.x() + dx, pos.y() + dy);
00335
00336 xy[TopRight].setZ(
00337 value(xy[TopRight].x(), xy[TopRight].y())
00338 );
00339 xy[BottomRight].setZ(
00340 value(xy[BottomRight].x(), xy[BottomRight].y())
00341 );
00342
00343 double zMin = xy[TopLeft].z();
00344 double zMax = zMin;
00345 double zSum = zMin;
00346
00347 for ( int i = TopRight; i <= BottomLeft; i++ )
00348 {
00349 const double z = xy[i].z();
00350
00351 zSum += z;
00352 if ( z < zMin )
00353 zMin = z;
00354 if ( z > zMax )
00355 zMax = z;
00356 }
00357
00358 if ( ignoreOutOfRange )
00359 {
00360 if ( !range.contains(zMin) || !range.contains(zMax) )
00361 continue;
00362 }
00363
00364 if ( zMax < levels[0] ||
00365 zMin > levels[levels.size() - 1] )
00366 {
00367 continue;
00368 }
00369
00370 xy[Center].setPos(pos.x() + 0.5 * dx, pos.y() + 0.5 * dy);
00371 xy[Center].setZ(0.25 * zSum);
00372 const int numLevels = (int)levels.size();
00373 for (int l = 0; l < numLevels; l++)
00374 {
00375 const double level = levels[l];
00376 if ( level < zMin || level > zMax )
00377 continue;
00378 #if QT_VERSION >= 0x040000
00379 QPolygonF &lines = contourLines[level];
00380 #else
00381 QwtArray<QwtDoublePoint> &lines = contourLines[level];
00382 #endif
00383 const ContourPlane plane(level);
00384
00385 QwtDoublePoint line[2];
00386 Contour3DPoint vertex[3];
00387
00388 for (int m = TopLeft; m < NumPositions; m++)
00389 {
00390 vertex[0] = xy[m];
00391 vertex[1] = xy[0];
00392 vertex[2] = xy[m != BottomLeft ? m + 1 : TopLeft];
00393
00394 const bool intersects =
00395 plane.intersect(vertex, line, ignoreOnPlane);
00396 if ( intersects )
00397 {
00398 #if QT_VERSION >= 0x040000
00399 lines += line[0];
00400 lines += line[1];
00401 #else
00402 const int index = lines.size();
00403 lines.resize(lines.size() + 2, QGArray::SpeedOptim);
00404
00405 lines[index] = line[0];
00406 lines[index+1] = line[1];
00407 #endif
00408 }
00409 }
00410 }
00411 }
00412 }
00413
00414 ((QwtRasterData*)this)->discardRaster();
00415
00416 return contourLines;
00417 }