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 
21 namespace 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
void reset()
void setRight(qreal x)
QPoint map(const QPoint &point) const const
qreal top() const const
qreal left() const const
QTransform inverted(bool *invertible) const const
void setLeft(qreal x)
qreal bottom() const const
QTransform & translate(qreal dx, qreal dy)
qreal x() const const
qreal y() const const
QTransform & scale(qreal sx, qreal sy)
ZoomParameters stores the center and the factor of zooming internally.
qreal right() const const
qreal width() const const
void setBottom(qreal y)
void setTop(qreal y)
void setX(qreal x)
void setY(qreal y)
qreal height() const const
Global namespace.
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Jul 31 2021 22:38:24 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.