qwt_scale_map.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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_scale_map.h"
  10. #include <qrect.h>
  11. #include <qalgorithms.h>
  12. #include <qmath.h>
  13. #include <qdebug.h>
  14. #if QT_VERSION < 0x040601
  15. #define qExp(x) ::exp(x)
  16. #endif
  17. QT_STATIC_CONST_IMPL double QwtScaleMap::LogMin = 1.0e-150;
  18. QT_STATIC_CONST_IMPL double QwtScaleMap::LogMax = 1.0e150;
  19. //! Constructor for a linear transformation
  20. QwtScaleTransformation::QwtScaleTransformation( Type type ):
  21. d_type( type )
  22. {
  23. }
  24. //! Destructor
  25. QwtScaleTransformation::~QwtScaleTransformation()
  26. {
  27. }
  28. //! Create a clone of the transformation
  29. QwtScaleTransformation *QwtScaleTransformation::copy() const
  30. {
  31. return new QwtScaleTransformation( d_type );
  32. }
  33. /*!
  34. \brief Transform a value between 2 linear intervals
  35. \param s value related to the interval [s1, s2]
  36. \param s1 first border of scale interval
  37. \param s2 second border of scale interval
  38. \param p1 first border of target interval
  39. \param p2 second border of target interval
  40. \return
  41. <dl>
  42. <dt>linear mapping:<dd>p1 + (p2 - p1) / (s2 - s1) * (s - s1)</dd>
  43. </dl>
  44. <dl>
  45. <dt>log10 mapping: <dd>p1 + (p2 - p1) / log(s2 / s1) * log(s / s1)</dd>
  46. </dl>
  47. */
  48. double QwtScaleTransformation::xForm(
  49. double s, double s1, double s2, double p1, double p2 ) const
  50. {
  51. if ( d_type == Log10 )
  52. return p1 + ( p2 - p1 ) / log( s2 / s1 ) * log( s / s1 );
  53. else
  54. return p1 + ( p2 - p1 ) / ( s2 - s1 ) * ( s - s1 );
  55. }
  56. /*!
  57. \brief Transform a value from a linear to a logarithmic interval
  58. \param p value related to the linear interval [p1, p2]
  59. \param p1 first border of linear interval
  60. \param p2 second border of linear interval
  61. \param s1 first border of logarithmic interval
  62. \param s2 second border of logarithmic interval
  63. \return
  64. <dl>
  65. <dt>exp((p - p1) / (p2 - p1) * log(s2 / s1)) * s1;
  66. </dl>
  67. */
  68. double QwtScaleTransformation::invXForm( double p, double p1, double p2,
  69. double s1, double s2 ) const
  70. {
  71. if ( d_type == Log10 )
  72. return qExp( ( p - p1 ) / ( p2 - p1 ) * log( s2 / s1 ) ) * s1;
  73. else
  74. return s1 + ( s2 - s1 ) / ( p2 - p1 ) * ( p - p1 );
  75. }
  76. /*!
  77. \brief Constructor
  78. The scale and paint device intervals are both set to [0,1].
  79. */
  80. QwtScaleMap::QwtScaleMap():
  81. d_s1( 0.0 ),
  82. d_s2( 1.0 ),
  83. d_p1( 0.0 ),
  84. d_p2( 1.0 ),
  85. d_cnv( 1.0 )
  86. {
  87. d_transformation = new QwtScaleTransformation(
  88. QwtScaleTransformation::Linear );
  89. }
  90. //! Copy constructor
  91. QwtScaleMap::QwtScaleMap( const QwtScaleMap& other ):
  92. d_s1( other.d_s1 ),
  93. d_s2( other.d_s2 ),
  94. d_p1( other.d_p1 ),
  95. d_p2( other.d_p2 ),
  96. d_cnv( other.d_cnv )
  97. {
  98. d_transformation = other.d_transformation->copy();
  99. }
  100. /*!
  101. Destructor
  102. */
  103. QwtScaleMap::~QwtScaleMap()
  104. {
  105. delete d_transformation;
  106. }
  107. //! Assignment operator
  108. QwtScaleMap &QwtScaleMap::operator=( const QwtScaleMap & other )
  109. {
  110. d_s1 = other.d_s1;
  111. d_s2 = other.d_s2;
  112. d_p1 = other.d_p1;
  113. d_p2 = other.d_p2;
  114. d_cnv = other.d_cnv;
  115. delete d_transformation;
  116. d_transformation = other.d_transformation->copy();
  117. return *this;
  118. }
  119. /*!
  120. Initialize the map with a transformation
  121. */
  122. void QwtScaleMap::setTransformation(
  123. QwtScaleTransformation *transformation )
  124. {
  125. if ( transformation == NULL )
  126. return;
  127. if ( transformation != d_transformation )
  128. {
  129. delete d_transformation;
  130. d_transformation = transformation;
  131. }
  132. setScaleInterval( d_s1, d_s2 );
  133. }
  134. //! Get the transformation
  135. const QwtScaleTransformation *QwtScaleMap::transformation() const
  136. {
  137. return d_transformation;
  138. }
  139. /*!
  140. \brief Specify the borders of the scale interval
  141. \param s1 first border
  142. \param s2 second border
  143. \warning logarithmic scales might be aligned to [LogMin, LogMax]
  144. */
  145. void QwtScaleMap::setScaleInterval( double s1, double s2 )
  146. {
  147. if ( d_transformation->type() == QwtScaleTransformation::Log10 )
  148. {
  149. if ( s1 < LogMin )
  150. s1 = LogMin;
  151. else if ( s1 > LogMax )
  152. s1 = LogMax;
  153. if ( s2 < LogMin )
  154. s2 = LogMin;
  155. else if ( s2 > LogMax )
  156. s2 = LogMax;
  157. }
  158. d_s1 = s1;
  159. d_s2 = s2;
  160. if ( d_transformation->type() != QwtScaleTransformation::Other )
  161. newFactor();
  162. }
  163. /*!
  164. \brief Specify the borders of the paint device interval
  165. \param p1 first border
  166. \param p2 second border
  167. */
  168. void QwtScaleMap::setPaintInterval( double p1, double p2 )
  169. {
  170. d_p1 = p1;
  171. d_p2 = p2;
  172. if ( d_transformation->type() != QwtScaleTransformation::Other )
  173. newFactor();
  174. }
  175. /*!
  176. \brief Re-calculate the conversion factor.
  177. */
  178. void QwtScaleMap::newFactor()
  179. {
  180. d_cnv = 0.0;
  181. switch ( d_transformation->type() )
  182. {
  183. case QwtScaleTransformation::Linear:
  184. if ( d_s2 != d_s1 )
  185. d_cnv = ( d_p2 - d_p1 ) / ( d_s2 - d_s1 );
  186. break;
  187. case QwtScaleTransformation::Log10:
  188. if ( d_s1 != 0 )
  189. d_cnv = ( d_p2 - d_p1 ) / log( d_s2 / d_s1 );
  190. break;
  191. default:;
  192. }
  193. }
  194. /*!
  195. Transform a rectangle
  196. \param xMap X map
  197. \param yMap Y map
  198. \param rect Rectangle in scale coordinates
  199. \return Rectangle in paint coordinates
  200. \sa invTransform()
  201. */
  202. QRectF QwtScaleMap::transform( const QwtScaleMap &xMap,
  203. const QwtScaleMap &yMap, const QRectF &rect )
  204. {
  205. double x1 = xMap.transform( rect.left() );
  206. double x2 = xMap.transform( rect.right() );
  207. double y1 = yMap.transform( rect.top() );
  208. double y2 = yMap.transform( rect.bottom() );
  209. if ( x2 < x1 )
  210. qSwap( x1, x2 );
  211. if ( y2 < y1 )
  212. qSwap( y1, y2 );
  213. if ( qwtFuzzyCompare( x1, 0.0, x2 - x1 ) == 0 )
  214. x1 = 0.0;
  215. if ( qwtFuzzyCompare( x2, 0.0, x2 - x1 ) == 0 )
  216. x2 = 0.0;
  217. if ( qwtFuzzyCompare( y1, 0.0, y2 - y1 ) == 0 )
  218. y1 = 0.0;
  219. if ( qwtFuzzyCompare( y2, 0.0, y2 - y1 ) == 0 )
  220. y2 = 0.0;
  221. return QRectF( x1, y1, x2 - x1 + 1, y2 - y1 + 1 );
  222. }
  223. /*!
  224. Transform a rectangle from paint to scale coordinates
  225. \param xMap X map
  226. \param yMap Y map
  227. \param rect Rectangle in paint coordinates
  228. \return Rectangle in scale coordinates
  229. \sa transform()
  230. */
  231. QRectF QwtScaleMap::invTransform( const QwtScaleMap &xMap,
  232. const QwtScaleMap &yMap, const QRectF &rect )
  233. {
  234. const double x1 = xMap.invTransform( rect.left() );
  235. const double x2 = xMap.invTransform( rect.right() - 1 );
  236. const double y1 = yMap.invTransform( rect.top() );
  237. const double y2 = yMap.invTransform( rect.bottom() - 1 );
  238. const QRectF r( x1, y1, x2 - x1, y2 - y1 );
  239. return r.normalized();
  240. }
  241. #ifndef QT_NO_DEBUG_STREAM
  242. QDebug operator<<( QDebug debug, const QwtScaleMap &map )
  243. {
  244. debug.nospace() << "QwtScaleMap("
  245. << static_cast<int>( map.transformation()->type() )
  246. << ", s:" << map.s1() << "->" << map.s2()
  247. << ", p:" << map.p1() << "->" << map.p2()
  248. << ")";
  249. return debug.space();
  250. }
  251. #endif