qwt_series_data.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
  2. * Qwt Widget Library
  3. * Copyright (C) 1997 Josef Wilgen
  4. * Copyright (C) 2002 Uwe Rathmann
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the Qwt License, Version 1.0
  8. *****************************************************************************/
  9. #include "qwt_series_data.h"
  10. #include "qwt_math.h"
  11. static inline QRectF qwtBoundingRect( const QPointF &sample )
  12. {
  13. return QRectF( sample.x(), sample.y(), 0.0, 0.0 );
  14. }
  15. static inline QRectF qwtBoundingRect( const QwtPoint3D &sample )
  16. {
  17. return QRectF( sample.x(), sample.y(), 0.0, 0.0 );
  18. }
  19. static inline QRectF qwtBoundingRect( const QwtPointPolar &sample )
  20. {
  21. return QRectF( sample.azimuth(), sample.radius(), 0.0, 0.0 );
  22. }
  23. static inline QRectF qwtBoundingRect( const QwtIntervalSample &sample )
  24. {
  25. return QRectF( sample.interval.minValue(), sample.value,
  26. sample.interval.maxValue() - sample.interval.minValue(), 0.0 );
  27. }
  28. static inline QRectF qwtBoundingRect( const QwtSetSample &sample )
  29. {
  30. double minX = sample.set[0];
  31. double maxX = sample.set[0];
  32. for ( int i = 1; i < ( int )sample.set.size(); i++ )
  33. {
  34. if ( sample.set[i] < minX )
  35. minX = sample.set[i];
  36. if ( sample.set[i] > maxX )
  37. maxX = sample.set[i];
  38. }
  39. double minY = sample.value;
  40. double maxY = sample.value;
  41. return QRectF( minX, minY, maxX - minX, maxY - minY );
  42. }
  43. /*!
  44. \brief Calculate the bounding rect of a series
  45. Slow implementation, that iterates over the series.
  46. \param series Series
  47. \return Bounding rectangle
  48. */
  49. template <class T>
  50. QRectF qwtBoundingRectT( const QwtSeriesData<T>& series )
  51. {
  52. QRectF boundingRect( 1.0, 1.0, -2.0, -2.0 ); // invalid;
  53. const size_t sz = series.size();
  54. if ( sz <= 0 )
  55. return boundingRect;
  56. size_t i;
  57. for ( i = 0; i < sz; i++ )
  58. {
  59. const QRectF rect = qwtBoundingRect( series.sample( i ) );
  60. if ( rect.width() >= 0.0 && rect.height() >= 0.0 )
  61. {
  62. boundingRect = rect;
  63. i++;
  64. break;
  65. }
  66. }
  67. for ( ; i < sz; i++ )
  68. {
  69. const QRectF rect = qwtBoundingRect( series.sample( i ) );
  70. if ( rect.width() >= 0.0 && rect.height() >= 0.0 )
  71. {
  72. boundingRect.setLeft( qMin( boundingRect.left(), rect.left() ) );
  73. boundingRect.setRight( qMax( boundingRect.right(), rect.right() ) );
  74. boundingRect.setTop( qMin( boundingRect.top(), rect.top() ) );
  75. boundingRect.setBottom( qMax( boundingRect.bottom(), rect.bottom() ) );
  76. }
  77. }
  78. return boundingRect;
  79. }
  80. /*!
  81. \brief Calculate the bounding rect of a series
  82. Slow implementation, that iterates over the series.
  83. \param series Series
  84. \return Bounding rectangle
  85. */
  86. QRectF qwtBoundingRect( const QwtSeriesData<QPointF> &series )
  87. {
  88. return qwtBoundingRectT<QPointF>( series );
  89. }
  90. /*!
  91. \brief Calculate the bounding rect of a series
  92. Slow implementation, that iterates over the series.
  93. \param series Series
  94. \return Bounding rectangle
  95. */
  96. QRectF qwtBoundingRect( const QwtSeriesData<QwtPoint3D> &series )
  97. {
  98. return qwtBoundingRectT<QwtPoint3D>( series );
  99. }
  100. /*!
  101. \brief Calculate the bounding rect of a series
  102. The horizontal coordinates represent the azimuth, the
  103. vertical coordinates the radius.
  104. Slow implementation, that iterates over the series.
  105. \param series Series
  106. \return Bounding rectangle
  107. */
  108. QRectF qwtBoundingRect( const QwtSeriesData<QwtPointPolar> &series )
  109. {
  110. return qwtBoundingRectT<QwtPointPolar>( series );
  111. }
  112. /*!
  113. \brief Calculate the bounding rect of a series
  114. Slow implementation, that iterates over the series.
  115. \param series Series
  116. \return Bounding rectangle
  117. */
  118. QRectF qwtBoundingRect( const QwtSeriesData<QwtIntervalSample>& series )
  119. {
  120. return qwtBoundingRectT<QwtIntervalSample>( series );
  121. }
  122. /*!
  123. \brief Calculate the bounding rect of a series
  124. Slow implementation, that iterates over the series.
  125. \param series Series
  126. \return Bounding rectangle
  127. */
  128. QRectF qwtBoundingRect( const QwtSeriesData<QwtSetSample>& series )
  129. {
  130. return qwtBoundingRectT<QwtSetSample>( series );
  131. }
  132. /*!
  133. Constructor
  134. \param samples Samples
  135. */
  136. QwtPointSeriesData::QwtPointSeriesData(
  137. const QVector<QPointF> &samples ):
  138. QwtArraySeriesData<QPointF>( samples )
  139. {
  140. }
  141. /*!
  142. \brief Calculate the bounding rect
  143. The bounding rectangle is calculated once by iterating over all
  144. points and is stored for all following requests.
  145. \return Bounding rectangle
  146. */
  147. QRectF QwtPointSeriesData::boundingRect() const
  148. {
  149. if ( d_boundingRect.width() < 0.0 )
  150. d_boundingRect = qwtBoundingRect( *this );
  151. return d_boundingRect;
  152. }
  153. /*!
  154. Constructor
  155. \param samples Samples
  156. */
  157. QwtPoint3DSeriesData::QwtPoint3DSeriesData(
  158. const QVector<QwtPoint3D> &samples ):
  159. QwtArraySeriesData<QwtPoint3D>( samples )
  160. {
  161. }
  162. /*!
  163. \brief Calculate the bounding rect
  164. The bounding rectangle is calculated once by iterating over all
  165. points and is stored for all following requests.
  166. \return Bounding rectangle
  167. */
  168. QRectF QwtPoint3DSeriesData::boundingRect() const
  169. {
  170. if ( d_boundingRect.width() < 0.0 )
  171. d_boundingRect = qwtBoundingRect( *this );
  172. return d_boundingRect;
  173. }
  174. /*!
  175. Constructor
  176. \param samples Samples
  177. */
  178. QwtIntervalSeriesData::QwtIntervalSeriesData(
  179. const QVector<QwtIntervalSample> &samples ):
  180. QwtArraySeriesData<QwtIntervalSample>( samples )
  181. {
  182. }
  183. /*!
  184. \brief Calculate the bounding rect
  185. The bounding rectangle is calculated once by iterating over all
  186. points and is stored for all following requests.
  187. \return Bounding rectangle
  188. */
  189. QRectF QwtIntervalSeriesData::boundingRect() const
  190. {
  191. if ( d_boundingRect.width() < 0.0 )
  192. d_boundingRect = qwtBoundingRect( *this );
  193. return d_boundingRect;
  194. }
  195. /*!
  196. Constructor
  197. \param samples Samples
  198. */
  199. QwtSetSeriesData::QwtSetSeriesData(
  200. const QVector<QwtSetSample> &samples ):
  201. QwtArraySeriesData<QwtSetSample>( samples )
  202. {
  203. }
  204. /*!
  205. \brief Calculate the bounding rect
  206. The bounding rectangle is calculated once by iterating over all
  207. points and is stored for all following requests.
  208. \return Bounding rectangle
  209. */
  210. QRectF QwtSetSeriesData::boundingRect() const
  211. {
  212. if ( d_boundingRect.width() < 0.0 )
  213. d_boundingRect = qwtBoundingRect( *this );
  214. return d_boundingRect;
  215. }
  216. /*!
  217. Constructor
  218. \param x Array of x values
  219. \param y Array of y values
  220. \sa QwtPlotCurve::setData(), QwtPlotCurve::setSamples()
  221. */
  222. QwtPointArrayData::QwtPointArrayData(
  223. const QVector<double> &x, const QVector<double> &y ):
  224. d_x( x ),
  225. d_y( y )
  226. {
  227. }
  228. /*!
  229. Constructor
  230. \param x Array of x values
  231. \param y Array of y values
  232. \param size Size of the x and y arrays
  233. \sa QwtPlotCurve::setData(), QwtPlotCurve::setSamples()
  234. */
  235. QwtPointArrayData::QwtPointArrayData( const double *x,
  236. const double *y, size_t size )
  237. {
  238. d_x.resize( size );
  239. qMemCopy( d_x.data(), x, size * sizeof( double ) );
  240. d_y.resize( size );
  241. qMemCopy( d_y.data(), y, size * sizeof( double ) );
  242. }
  243. /*!
  244. \brief Calculate the bounding rect
  245. The bounding rectangle is calculated once by iterating over all
  246. points and is stored for all following requests.
  247. \return Bounding rectangle
  248. */
  249. QRectF QwtPointArrayData::boundingRect() const
  250. {
  251. if ( d_boundingRect.width() < 0 )
  252. d_boundingRect = qwtBoundingRect( *this );
  253. return d_boundingRect;
  254. }
  255. //! \return Size of the data set
  256. size_t QwtPointArrayData::size() const
  257. {
  258. return qMin( d_x.size(), d_y.size() );
  259. }
  260. /*!
  261. Return the sample at position i
  262. \param i Index
  263. \return Sample at position i
  264. */
  265. QPointF QwtPointArrayData::sample( size_t i ) const
  266. {
  267. return QPointF( d_x[int( i )], d_y[int( i )] );
  268. }
  269. //! \return Array of the x-values
  270. const QVector<double> &QwtPointArrayData::xData() const
  271. {
  272. return d_x;
  273. }
  274. //! \return Array of the y-values
  275. const QVector<double> &QwtPointArrayData::yData() const
  276. {
  277. return d_y;
  278. }
  279. /*!
  280. Constructor
  281. \param x Array of x values
  282. \param y Array of y values
  283. \param size Size of the x and y arrays
  284. \warning The programmer must assure that the memory blocks referenced
  285. by the pointers remain valid during the lifetime of the
  286. QwtPlotCPointer object.
  287. \sa QwtPlotCurve::setData(), QwtPlotCurve::setRawSamples()
  288. */
  289. QwtCPointerData::QwtCPointerData(
  290. const double *x, const double *y, size_t size ):
  291. d_x( x ),
  292. d_y( y ),
  293. d_size( size )
  294. {
  295. }
  296. /*!
  297. \brief Calculate the bounding rect
  298. The bounding rectangle is calculated once by iterating over all
  299. points and is stored for all following requests.
  300. \return Bounding rectangle
  301. */
  302. QRectF QwtCPointerData::boundingRect() const
  303. {
  304. if ( d_boundingRect.width() < 0 )
  305. d_boundingRect = qwtBoundingRect( *this );
  306. return d_boundingRect;
  307. }
  308. //! \return Size of the data set
  309. size_t QwtCPointerData::size() const
  310. {
  311. return d_size;
  312. }
  313. /*!
  314. Return the sample at position i
  315. \param i Index
  316. \return Sample at position i
  317. */
  318. QPointF QwtCPointerData::sample( size_t i ) const
  319. {
  320. return QPointF( d_x[int( i )], d_y[int( i )] );
  321. }
  322. //! \return Array of the x-values
  323. const double *QwtCPointerData::xData() const
  324. {
  325. return d_x;
  326. }
  327. //! \return Array of the y-values
  328. const double *QwtCPointerData::yData() const
  329. {
  330. return d_y;
  331. }
  332. /*!
  333. Constructor
  334. \param size Number of points
  335. \param interval Bounding interval for the points
  336. \sa setInterval(), setSize()
  337. */
  338. QwtSyntheticPointData::QwtSyntheticPointData(
  339. size_t size, const QwtInterval &interval ):
  340. d_size( size ),
  341. d_interval( interval )
  342. {
  343. }
  344. /*!
  345. Change the number of points
  346. \param size Number of points
  347. \sa size(), setInterval()
  348. */
  349. void QwtSyntheticPointData::setSize( size_t size )
  350. {
  351. d_size = size;
  352. }
  353. /*!
  354. \return Number of points
  355. \sa setSize(), interval()
  356. */
  357. size_t QwtSyntheticPointData::size() const
  358. {
  359. return d_size;
  360. }
  361. /*!
  362. Set the bounding interval
  363. \param interval Interval
  364. \sa interval(), setSize()
  365. */
  366. void QwtSyntheticPointData::setInterval( const QwtInterval &interval )
  367. {
  368. d_interval = interval.normalized();
  369. }
  370. /*!
  371. \return Bounding interval
  372. \sa setInterval(), size()
  373. */
  374. QwtInterval QwtSyntheticPointData::interval() const
  375. {
  376. return d_interval;
  377. }
  378. /*!
  379. Set a the "rect of interest"
  380. QwtPlotSeriesItem defines the current area of the plot canvas
  381. as "rect of interest" ( QwtPlotSeriesItem::updateScaleDiv() ).
  382. If interval().isValid() == false the x values are calculated
  383. in the interval rect.left() -> rect.right().
  384. \sa rectOfInterest()
  385. */
  386. void QwtSyntheticPointData::setRectOfInterest( const QRectF &rect )
  387. {
  388. d_rectOfInterest = rect;
  389. d_intervalOfInterest = QwtInterval(
  390. rect.left(), rect.right() ).normalized();
  391. }
  392. /*!
  393. \return "rect of interest"
  394. \sa setRectOfInterest()
  395. */
  396. QRectF QwtSyntheticPointData::rectOfInterest() const
  397. {
  398. return d_rectOfInterest;
  399. }
  400. /*!
  401. \brief Calculate the bounding rect
  402. This implementation iterates over all points, what could often
  403. be implemented much faster using the characteristics of the series.
  404. When there are many points it is recommended to overload and
  405. reimplement this method using the characteristics of the series
  406. ( if possible ).
  407. \return Bounding rectangle
  408. */
  409. QRectF QwtSyntheticPointData::boundingRect() const
  410. {
  411. if ( d_size == 0 ||
  412. !( d_interval.isValid() || d_intervalOfInterest.isValid() ) )
  413. {
  414. return QRectF(1.0, 1.0, -2.0, -2.0); // something invalid
  415. }
  416. return qwtBoundingRect( *this );
  417. }
  418. /*!
  419. Calculate the point from an index
  420. \param index Index
  421. \return QPointF(x(index), y(x(index)));
  422. \warning For invalid indices ( index < 0 || index >= size() )
  423. (0, 0) is returned.
  424. */
  425. QPointF QwtSyntheticPointData::sample( size_t index ) const
  426. {
  427. if ( index >= d_size )
  428. return QPointF( 0, 0 );
  429. const double xValue = x( index );
  430. const double yValue = y( xValue );
  431. return QPointF( xValue, yValue );
  432. }
  433. /*!
  434. Calculate a x-value from an index
  435. x values are calculated by deviding an interval into
  436. equidistant steps. If !interval().isValid() the
  437. interval is calculated from the "rect of interest".
  438. \sa interval(), rectOfInterest(), y()
  439. */
  440. double QwtSyntheticPointData::x( uint index ) const
  441. {
  442. const QwtInterval &interval = d_interval.isValid() ?
  443. d_interval : d_intervalOfInterest;
  444. if ( !interval.isValid() || d_size == 0 || index >= d_size )
  445. return 0.0;
  446. const double dx = interval.width() / d_size;
  447. return interval.minValue() + index * dx;
  448. }