123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- /* -*- mode: C++ ; c-file-style: "stroustrup" -*- *****************************
- * Qwt Widget Library
- * Copyright (C) 1997 Josef Wilgen
- * Copyright (C) 2002 Uwe Rathmann
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the Qwt License, Version 1.0
- *****************************************************************************/
- #include "qwt_scale_map.h"
- #include <qrect.h>
- #include <qalgorithms.h>
- #include <qmath.h>
- #include <qdebug.h>
- #if QT_VERSION < 0x040601
- #define qExp(x) ::exp(x)
- #endif
- QT_STATIC_CONST_IMPL double QwtScaleMap::LogMin = 1.0e-150;
- QT_STATIC_CONST_IMPL double QwtScaleMap::LogMax = 1.0e150;
- //! Constructor for a linear transformation
- QwtScaleTransformation::QwtScaleTransformation( Type type ):
- d_type( type )
- {
- }
- //! Destructor
- QwtScaleTransformation::~QwtScaleTransformation()
- {
- }
- //! Create a clone of the transformation
- QwtScaleTransformation *QwtScaleTransformation::copy() const
- {
- return new QwtScaleTransformation( d_type );
- }
- /*!
- \brief Transform a value between 2 linear intervals
- \param s value related to the interval [s1, s2]
- \param s1 first border of scale interval
- \param s2 second border of scale interval
- \param p1 first border of target interval
- \param p2 second border of target interval
- \return
- <dl>
- <dt>linear mapping:<dd>p1 + (p2 - p1) / (s2 - s1) * (s - s1)</dd>
- </dl>
- <dl>
- <dt>log10 mapping: <dd>p1 + (p2 - p1) / log(s2 / s1) * log(s / s1)</dd>
- </dl>
- */
- double QwtScaleTransformation::xForm(
- double s, double s1, double s2, double p1, double p2 ) const
- {
- if ( d_type == Log10 )
- return p1 + ( p2 - p1 ) / log( s2 / s1 ) * log( s / s1 );
- else
- return p1 + ( p2 - p1 ) / ( s2 - s1 ) * ( s - s1 );
- }
- /*!
- \brief Transform a value from a linear to a logarithmic interval
- \param p value related to the linear interval [p1, p2]
- \param p1 first border of linear interval
- \param p2 second border of linear interval
- \param s1 first border of logarithmic interval
- \param s2 second border of logarithmic interval
- \return
- <dl>
- <dt>exp((p - p1) / (p2 - p1) * log(s2 / s1)) * s1;
- </dl>
- */
- double QwtScaleTransformation::invXForm( double p, double p1, double p2,
- double s1, double s2 ) const
- {
- if ( d_type == Log10 )
- return qExp( ( p - p1 ) / ( p2 - p1 ) * log( s2 / s1 ) ) * s1;
- else
- return s1 + ( s2 - s1 ) / ( p2 - p1 ) * ( p - p1 );
- }
- /*!
- \brief Constructor
- The scale and paint device intervals are both set to [0,1].
- */
- QwtScaleMap::QwtScaleMap():
- d_s1( 0.0 ),
- d_s2( 1.0 ),
- d_p1( 0.0 ),
- d_p2( 1.0 ),
- d_cnv( 1.0 )
- {
- d_transformation = new QwtScaleTransformation(
- QwtScaleTransformation::Linear );
- }
- //! Copy constructor
- QwtScaleMap::QwtScaleMap( const QwtScaleMap& other ):
- d_s1( other.d_s1 ),
- d_s2( other.d_s2 ),
- d_p1( other.d_p1 ),
- d_p2( other.d_p2 ),
- d_cnv( other.d_cnv )
- {
- d_transformation = other.d_transformation->copy();
- }
- /*!
- Destructor
- */
- QwtScaleMap::~QwtScaleMap()
- {
- delete d_transformation;
- }
- //! Assignment operator
- QwtScaleMap &QwtScaleMap::operator=( const QwtScaleMap & other )
- {
- d_s1 = other.d_s1;
- d_s2 = other.d_s2;
- d_p1 = other.d_p1;
- d_p2 = other.d_p2;
- d_cnv = other.d_cnv;
- delete d_transformation;
- d_transformation = other.d_transformation->copy();
- return *this;
- }
- /*!
- Initialize the map with a transformation
- */
- void QwtScaleMap::setTransformation(
- QwtScaleTransformation *transformation )
- {
- if ( transformation == NULL )
- return;
- if ( transformation != d_transformation )
- {
- delete d_transformation;
- d_transformation = transformation;
- }
- setScaleInterval( d_s1, d_s2 );
- }
- //! Get the transformation
- const QwtScaleTransformation *QwtScaleMap::transformation() const
- {
- return d_transformation;
- }
- /*!
- \brief Specify the borders of the scale interval
- \param s1 first border
- \param s2 second border
- \warning logarithmic scales might be aligned to [LogMin, LogMax]
- */
- void QwtScaleMap::setScaleInterval( double s1, double s2 )
- {
- if ( d_transformation->type() == QwtScaleTransformation::Log10 )
- {
- if ( s1 < LogMin )
- s1 = LogMin;
- else if ( s1 > LogMax )
- s1 = LogMax;
- if ( s2 < LogMin )
- s2 = LogMin;
- else if ( s2 > LogMax )
- s2 = LogMax;
- }
- d_s1 = s1;
- d_s2 = s2;
- if ( d_transformation->type() != QwtScaleTransformation::Other )
- newFactor();
- }
- /*!
- \brief Specify the borders of the paint device interval
- \param p1 first border
- \param p2 second border
- */
- void QwtScaleMap::setPaintInterval( double p1, double p2 )
- {
- d_p1 = p1;
- d_p2 = p2;
- if ( d_transformation->type() != QwtScaleTransformation::Other )
- newFactor();
- }
- /*!
- \brief Re-calculate the conversion factor.
- */
- void QwtScaleMap::newFactor()
- {
- d_cnv = 0.0;
- switch ( d_transformation->type() )
- {
- case QwtScaleTransformation::Linear:
- if ( d_s2 != d_s1 )
- d_cnv = ( d_p2 - d_p1 ) / ( d_s2 - d_s1 );
- break;
- case QwtScaleTransformation::Log10:
- if ( d_s1 != 0 )
- d_cnv = ( d_p2 - d_p1 ) / log( d_s2 / d_s1 );
- break;
- default:;
- }
- }
- /*!
- Transform a rectangle
- \param xMap X map
- \param yMap Y map
- \param rect Rectangle in scale coordinates
- \return Rectangle in paint coordinates
- \sa invTransform()
- */
- QRectF QwtScaleMap::transform( const QwtScaleMap &xMap,
- const QwtScaleMap &yMap, const QRectF &rect )
- {
- double x1 = xMap.transform( rect.left() );
- double x2 = xMap.transform( rect.right() );
- double y1 = yMap.transform( rect.top() );
- double y2 = yMap.transform( rect.bottom() );
- if ( x2 < x1 )
- qSwap( x1, x2 );
- if ( y2 < y1 )
- qSwap( y1, y2 );
- if ( qwtFuzzyCompare( x1, 0.0, x2 - x1 ) == 0 )
- x1 = 0.0;
- if ( qwtFuzzyCompare( x2, 0.0, x2 - x1 ) == 0 )
- x2 = 0.0;
- if ( qwtFuzzyCompare( y1, 0.0, y2 - y1 ) == 0 )
- y1 = 0.0;
- if ( qwtFuzzyCompare( y2, 0.0, y2 - y1 ) == 0 )
- y2 = 0.0;
- return QRectF( x1, y1, x2 - x1 + 1, y2 - y1 + 1 );
- }
- /*!
- Transform a rectangle from paint to scale coordinates
- \param xMap X map
- \param yMap Y map
- \param rect Rectangle in paint coordinates
- \return Rectangle in scale coordinates
- \sa transform()
- */
- QRectF QwtScaleMap::invTransform( const QwtScaleMap &xMap,
- const QwtScaleMap &yMap, const QRectF &rect )
- {
- const double x1 = xMap.invTransform( rect.left() );
- const double x2 = xMap.invTransform( rect.right() - 1 );
- const double y1 = yMap.invTransform( rect.top() );
- const double y2 = yMap.invTransform( rect.bottom() - 1 );
- const QRectF r( x1, y1, x2 - x1, y2 - y1 );
- return r.normalized();
- }
- #ifndef QT_NO_DEBUG_STREAM
- QDebug operator<<( QDebug debug, const QwtScaleMap &map )
- {
- debug.nospace() << "QwtScaleMap("
- << static_cast<int>( map.transformation()->type() )
- << ", s:" << map.s1() << "->" << map.s2()
- << ", p:" << map.p1() << "->" << map.p2()
- << ")";
- return debug.space();
- }
- #endif
|