183 lines
6.4 KiB
C++
183 lines
6.4 KiB
C++
/****************************************************************************
|
|
** Copyright (C) 2001-2011 Klaralvdalens Datakonsult AB. All rights reserved.
|
|
**
|
|
** This file is part of the KD Chart library.
|
|
**
|
|
** Licensees holding valid commercial KD Chart licenses may use this file in
|
|
** accordance with the KD Chart Commercial License Agreement provided with
|
|
** the Software.
|
|
**
|
|
**
|
|
** This file may be distributed and/or modified under the terms of the
|
|
** GNU General Public License version 2 and version 3 as published by the
|
|
** Free Software Foundation and appearing in the file LICENSE.GPL.txt included.
|
|
**
|
|
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
**
|
|
** Contact info@kdab.com if any conditions of this licensing are not
|
|
** clear to you.
|
|
**
|
|
**********************************************************************/
|
|
|
|
#ifndef CARTESIANCOORDINATETRANSFORMATION_H
|
|
#define CARTESIANCOORDINATETRANSFORMATION_H
|
|
|
|
#include <QList>
|
|
#include <QRectF>
|
|
#include <QPointF>
|
|
|
|
#include "KDChartZoomParameters.h"
|
|
|
|
#include <cmath>
|
|
#include <limits>
|
|
|
|
namespace KDChart {
|
|
|
|
// FIXME: if this struct is used more often, we need to make it a class
|
|
// with proper accessor methods:
|
|
|
|
/**
|
|
* \internal
|
|
*/
|
|
struct CoordinateTransformation {
|
|
QRectF diagramRect;
|
|
// represents the distance of the diagram coordinate origin to the
|
|
// origin of the coordinate plane space:
|
|
QPointF originTranslation;
|
|
// make a vector base for R2:
|
|
double unitVectorX;
|
|
double unitVectorY;
|
|
// implement isometric scaling:
|
|
double isoScaleX;
|
|
double isoScaleY;
|
|
|
|
CartesianCoordinatePlane::AxesCalcMode axesCalcModeY;
|
|
CartesianCoordinatePlane::AxesCalcMode axesCalcModeX;
|
|
|
|
ZoomParameters zoom;
|
|
|
|
typedef QPair< qreal, qreal > qrealPair;
|
|
|
|
inline qreal makeLogarithmic( qrealPair reference, qreal value ) const
|
|
{
|
|
qreal result = value;
|
|
|
|
qreal relation;
|
|
if( reference.second == -1.0 )
|
|
relation = 1.0;
|
|
else if( reference.second == 1.0 )
|
|
relation = 1.0;
|
|
else if( reference.second > 0.0 )
|
|
relation = reference.second / log10( reference.second );
|
|
else if( result < 0.0 )
|
|
relation = reference.second / log10( -reference.second );
|
|
else
|
|
relation = 10.0;
|
|
|
|
if( value == 0.0 )
|
|
result = 0.0;//std::numeric_limits< qreal >::quiet_NaN();
|
|
else if( value > 0.0 )
|
|
result = log10( result ) * relation;
|
|
else if( value < 0.0 )
|
|
result = -log10( -result ) * relation;
|
|
|
|
if( value == 0.0 )
|
|
return result;
|
|
|
|
result -= log10( qAbs( reference.first ) ) * relation;
|
|
result *= ( reference.second - reference.first ) / relation / (log10(qAbs(reference.second))-log10(qAbs(reference.first)));
|
|
result += reference.first;
|
|
|
|
if( reference.first < 0.0 )
|
|
{
|
|
result += reference.first;
|
|
result -= reference.second;
|
|
result = reference.first - result + reference.second;
|
|
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
inline QPointF translate( const QPointF& diagramPoint ) const
|
|
{
|
|
// ### de-inline me
|
|
QPointF result = originTranslation;
|
|
QPointF tempPoint = diagramPoint;
|
|
|
|
const QRectF& diagRect = diagramRect;
|
|
|
|
if( axesCalcModeY == CartesianCoordinatePlane::Logarithmic )
|
|
{
|
|
tempPoint.setY( makeLogarithmic( qrealPair( diagRect.bottom(), diagRect.y() ), tempPoint.y() ) );
|
|
}
|
|
if( axesCalcModeX == CartesianCoordinatePlane::Logarithmic )
|
|
{
|
|
tempPoint.setX( makeLogarithmic( qrealPair( diagRect.x(), diagRect.right() ), tempPoint.x() ) );
|
|
}
|
|
|
|
tempPoint.rx() += diagRect.width() / (2.0 * zoom.xFactor);
|
|
tempPoint.ry() += diagRect.height() / (2.0 * zoom.yFactor);
|
|
|
|
tempPoint.rx() -= diagRect.width() * zoom.xCenter;
|
|
tempPoint.ry() -= diagRect.height() * zoom.yCenter;
|
|
|
|
// translate: xNew = (xOld - diaX) * zoomX + diaX
|
|
tempPoint.setX( ( tempPoint.x() - diagRect.x() ) * zoom.xFactor + diagRect.x() );
|
|
tempPoint.setY( ( tempPoint.y() - diagRect.y() ) * zoom.yFactor + diagRect.y() );
|
|
|
|
result.rx() += isoScaleX * unitVectorX * tempPoint.x();
|
|
result.ry() += isoScaleY * unitVectorY * tempPoint.y();
|
|
|
|
return result;
|
|
}
|
|
|
|
// convert screen points to value space points
|
|
inline const QPointF translateBack( const QPointF& screenPoint ) const
|
|
{
|
|
qreal x, y;
|
|
|
|
x = screenPoint.x() - originTranslation.x();
|
|
y = screenPoint.y() - originTranslation.y();
|
|
|
|
x /= isoScaleX * unitVectorX;
|
|
y /= isoScaleY * unitVectorY;
|
|
|
|
// translate back: xOld = DiaX + (xNew - DiaX) / zoomX
|
|
x = diagramRect.x() + (x - diagramRect.x()) / zoom.xFactor;
|
|
y = diagramRect.y() + (y - diagramRect.y()) / zoom.yFactor;
|
|
|
|
x += diagramRect.width() * zoom.xCenter;
|
|
y += diagramRect.height() * zoom.yCenter;
|
|
|
|
x -= diagramRect.width() / (2.0 * zoom.xFactor);
|
|
y -= diagramRect.height() / (2.0 * zoom.yFactor);
|
|
|
|
/*
|
|
if ( axesCalcModeY == CartesianCoordinatePlane::Logarithmic ){
|
|
tempPoint.setY( makeLogarithmic( diagramRect.y(), tempPoint.y() ) );
|
|
//qDebug() << "Y: " << tempPoint.y();
|
|
}
|
|
if ( axesCalcModeX == CartesianCoordinatePlane::Logarithmic ){
|
|
//qDebug() << "X diagramRect.x(): " << diagramRect.x();
|
|
//qDebug() << "X tempPoint old: " << tempPoint;
|
|
tempPoint.setX( makeLogarithmic( diagramRect.width(), tempPoint.x() ) );
|
|
//qDebug() << "X tempPoint new: " << tempPoint;
|
|
}
|
|
// qDebug() << "CoordinateTransformation::translate() using diagramRect: "
|
|
// << diagramRect.x() << diagramRect.y() << diagramRect.width() << diagramRect.height();
|
|
*/
|
|
|
|
return QPointF(x, y);
|
|
}
|
|
|
|
};
|
|
|
|
typedef QList<CoordinateTransformation> CoordinateTransformationList;
|
|
|
|
}
|
|
|
|
#endif
|
|
|