KChart

CartesianCoordinateTransformation.h
1/*
2 * SPDX-FileCopyrightText: 2001-2015 Klaralvdalens Datakonsult AB. All rights reserved.
3 *
4 * This file is part of the KD Chart library.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9#ifndef CARTESIANCOORDINATETRANSFORMATION_H
10#define CARTESIANCOORDINATETRANSFORMATION_H
11
12#include <QList>
13#include <QRectF>
14#include <QPointF>
15
16#include "KChartZoomParameters.h"
17
18#include <cmath>
19#include <limits>
20
21namespace KChart {
22
23 // FIXME: if this struct is used more often, we need to make it a class
24 // with proper accessor methods:
25
26 /**
27 * \internal
28 */
30
32 : axesCalcModeY( CartesianCoordinatePlane::Linear ),
33 axesCalcModeX( CartesianCoordinatePlane::Linear ),
34 isPositiveX( true ),
35 isPositiveY( true )
36 {}
37
38 CartesianCoordinatePlane::AxesCalcMode axesCalcModeY;
39 CartesianCoordinatePlane::AxesCalcMode axesCalcModeX;
40
41 ZoomParameters zoom;
42
43 QTransform transform;
44 QTransform backTransform;
45 // a logarithmic scale cannot cross zero, so we have to know which side we are on.
46 bool isPositiveX;
47 bool isPositiveY;
48
49 qreal logTransform( qreal value, bool isPositiveRange ) const
50 {
51 if ( isPositiveRange ) {
52 return log10( value );
53 } else {
54 return -log10( -value );
55 }
56 }
57
58 qreal logTransformBack( qreal value, bool wasPositive ) const
59 {
60 if ( wasPositive ) {
61 return pow( 10.0, value );
62 } else {
63 return -pow( 10.0, -value );
64 }
65 }
66
67 void updateTransform( const QRectF& constDataRect, const QRectF& screenRect )
68 {
69 QRectF dataRect = constDataRect;
70 if ( axesCalcModeX == CartesianCoordinatePlane::Logarithmic ) {
71 // the data will be scaled by logTransform() later, so scale its bounds as well
72 isPositiveX = dataRect.left() >= 0.0;
73 dataRect.setLeft( logTransform( dataRect.left(), isPositiveX ) );
74 dataRect.setRight( logTransform( dataRect.right(), isPositiveX ) );
75 }
76 if ( axesCalcModeY == CartesianCoordinatePlane::Logarithmic ) {
77 isPositiveY = dataRect.top() >= 0.0;
78 dataRect.setTop( logTransform( dataRect.top(), isPositiveY ) );
79 dataRect.setBottom( logTransform( dataRect.bottom(), isPositiveY ) );
80 }
81
82 transform.reset();
83 // read the following transformation sequence from bottom to top(!)
84 transform.translate( screenRect.left(), screenRect.bottom() );
85 transform.scale( screenRect.width(), screenRect.height() );
86
87 // TODO: mirror in case of "reverse" axes?
88
89 // transform into screen space
90 transform.translate( 0.5, -0.5 );
91 transform.scale( zoom.xFactor, zoom.yFactor );
92 transform.translate( -zoom.xCenter, 1.0 - zoom.yCenter );
93 // zoom
94 transform.scale( 1.0 / dataRect.width(), 1.0 / dataRect.height() );
95 transform.translate( -dataRect.left(), -dataRect.bottom() );
96 // transform into the unit square
97
98 backTransform = transform.inverted();
99 }
100
101 // convert data space point to screen point
102 inline QPointF translate( const QPointF& dataPoint ) const
103 {
104 QPointF data = dataPoint;
105 if ( axesCalcModeX == CartesianCoordinatePlane::Logarithmic ) {
106 data.setX( logTransform( data.x(), isPositiveX ) );
107 }
108 if ( axesCalcModeY == CartesianCoordinatePlane::Logarithmic ) {
109 data.setY( logTransform( data.y(), isPositiveY ) );
110 }
111
112 return transform.map( data );
113 }
114
115 // convert screen point to data space point
116 inline const QPointF translateBack( const QPointF& screenPoint ) const
117 {
118 QPointF ret = backTransform.map( screenPoint );
119 if ( axesCalcModeX == CartesianCoordinatePlane::Logarithmic ) {
120 ret.setX( logTransformBack( ret.x(), isPositiveX ) );
121 }
122 if ( axesCalcModeY == CartesianCoordinatePlane::Logarithmic ) {
123 ret.setY( logTransformBack( ret.y(), isPositiveY ) );
124 }
125 return ret;
126 }
127 };
128
130
131}
132
133#endif
ZoomParameters stores the center and the factor of zooming internally.
void setX(qreal x)
void setY(qreal y)
qreal x() const const
qreal y() const const
qreal bottom() const const
qreal height() const const
qreal left() const const
qreal right() const const
void setBottom(qreal y)
void setLeft(qreal x)
void setRight(qreal x)
void setTop(qreal y)
qreal top() const const
qreal width() const const
QLine map(const QLine &l) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:24 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.