| 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)#endifconst double QwtScaleMap::LogMin = 1.0e-150;const double QwtScaleMap::LogMax = 1.0e150;//! Constructor for a linear transformationQwtScaleTransformation::QwtScaleTransformation( Type type ):    d_type( type ){}//! DestructorQwtScaleTransformation::~QwtScaleTransformation(){}//! Create a clone of the transformationQwtScaleTransformation *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 constructorQwtScaleMap::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 operatorQwtScaleMap &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 transformationconst 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_STREAMQDebug 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
 |