KChart

KChartTernaryCoordinatePlane.cpp
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 #include "KChartTernaryCoordinatePlane.h"
10 #include "KChartTernaryCoordinatePlane_p.h"
11 
12 #include <QtDebug>
13 #include <QPainter>
14 
15 #include "KChartPaintContext.h"
16 #include "KChartPainterSaver_p.h"
17 #include "KChartTernaryAxis.h"
18 #include "KChartAbstractTernaryDiagram.h"
19 
20 #include "TernaryConstants.h"
21 
22 using namespace KChart;
23 
24 #define d d_func()
25 
26 TernaryCoordinatePlane::Private::Private()
27  : AbstractCoordinatePlane::Private()
28 {
29 }
30 
31 TernaryCoordinatePlane::TernaryCoordinatePlane( Chart* parent )
32  : AbstractCoordinatePlane( new Private(), parent )
33 {
34 }
35 
36 TernaryCoordinatePlane::~TernaryCoordinatePlane()
37 {
38 }
39 
40 void TernaryCoordinatePlane::init()
41 {
42 }
43 
45 {
46  Q_ASSERT_X ( dynamic_cast<AbstractTernaryDiagram*>( diagram ),
47  "TernaryCoordinatePlane::addDiagram", "Only ternary "
48  "diagrams can be added to a ternary coordinate plane!" );
50 }
51 
53 { // this is our "resize event":
54  // all diagrams always take the same space, nothing to be done here
55  // the "inner" margin (adjustments to diagram coordinates)
56  QRectF diagramNativeRectangle ( QPointF( 0.0, 0.0 ),
57  QSizeF( TriangleWidth, TriangleHeight ) );
58  QPair<QSizeF, QSizeF> margins = grid()->requiredMargins();
59  d->diagramRect = areaGeometry();
60  diagramNativeRectangle.adjust
61  (-margins.first.width(), -margins.first.height(),
62  margins.second.width(), margins.second.height() );
63 
64  // the "outer" margin (distance between diagram contents and area,
65  // determined by axis label overlap
66  {
67  QSizeF topleft( 0.0, 0.0 );
68  QSizeF bottomRight( 0.0, 0.0 );
69  const auto ds = diagrams();
70  for ( AbstractDiagram* abstractDiagram : ds ) {
72  qobject_cast<AbstractTernaryDiagram*>( abstractDiagram );
73  Q_ASSERT( diagram );
74  const auto axes = diagram->axes();
75  for ( TernaryAxis* axis : axes ) {
76  QPair<QSizeF, QSizeF> margin = axis->requiredMargins();
77  topleft = topleft.expandedTo( margin.first );
78  bottomRight = bottomRight.expandedTo( margin.second );
79  }
80  }
81  d->diagramRectContainer =
82  d->diagramRect.adjusted( topleft.width(),
83  topleft.height(),
84  -bottomRight.width(),
85  -bottomRight.height() );
86  }
87 
88  // now calculate isometric projection, x and y widget coordinate
89  // units, and location of (0.0, 0.0) in diagram coordinates
90  QPointF zeroZeroPoint = d->diagramRectContainer.bottomLeft();
91  qreal w = d->diagramRectContainer.width();
92  qreal h = d->diagramRectContainer.height();
93  qreal usableWidth;
94  qreal usableHeight;
95 
96  if ( TriangleHeight * w > h ) {
97  // shorten width:
98  usableWidth = h / diagramNativeRectangle.height();
99  usableHeight = h;
100  zeroZeroPoint.setX( zeroZeroPoint.x() + ( w - usableWidth ) / 2 );
101  } else {
102  // reduce height:
103  usableWidth = w;
104  usableHeight = diagramNativeRectangle.height() * w;
105  zeroZeroPoint.setY( zeroZeroPoint.y() - ( h - usableHeight ) / 2 );
106  }
107  // the rectangle has 1 as it's width, and TriangleHeight as it's
108  // height - so this is how we translate that to widget coordinates:
109  d->xUnit = usableWidth / diagramNativeRectangle.width(); // only because we normalize the values to [0..1]
110  d->yUnit = -usableHeight / diagramNativeRectangle.height();
111 
112  // now move zeroZeroPoint so that it does not include the tick marks
113  {
114  qreal descent = diagramNativeRectangle.height() - TriangleHeight;
115  qreal rightShift = -diagramNativeRectangle.x();
116  zeroZeroPoint += QPointF( rightShift * d->xUnit, descent * d->yUnit );
117  }
118 
119  d->diagramRect.setBottomLeft( zeroZeroPoint );
120  d->diagramRect.setTopRight( QPointF( usableWidth, -usableHeight ) + zeroZeroPoint );
121 }
122 
124 {
125  return QPointF( d->diagramRect.bottomLeft().x() + point.x() * d->xUnit,
126  d->diagramRect.bottomLeft().y() + point.y() * d->yUnit );
127 }
128 
130 {
131  // FIXME temp
132  return QSize();
133 }
134 
136 {
139 }
140 
141 void TernaryCoordinatePlane::paint( QPainter* painter )
142 {
143  PainterSaver s( painter );
144  // FIXME: this is not a good location for that:
145  painter->setRenderHint(QPainter::Antialiasing, true );
146 
147  AbstractDiagramList diags = diagrams();
148  if ( !diags.isEmpty() )
149  {
150  PaintContext ctx;
151  ctx.setPainter ( painter );
152  ctx.setCoordinatePlane ( this );
153  const QRectF drawArea( areaGeometry() );
154  ctx.setRectangle ( drawArea );
155 
156  // paint the coordinate system rulers:
157  Q_ASSERT( d->grid != nullptr );
158  d->grid->drawGrid( &ctx );
159 
160  // paint the diagrams:
161  for ( int i = 0; i < diags.size(); i++ )
162  {
163  PainterSaver diagramPainterSaver( painter );
164  diags[i]->paint ( &ctx );
165  }
166  }
167 }
168 
169 DataDimensionsList TernaryCoordinatePlane::getDataDimensionsList() const
170 { // not needed
171  return DataDimensionsList();
172 }
173 
174 TernaryGrid* TernaryCoordinatePlane::grid() const
175 {
176  TernaryGrid* ternaryGrid = static_cast<TernaryGrid*>( d->grid );
177  Q_ASSERT( dynamic_cast<TernaryGrid*>( d->grid ) );
178  return ternaryGrid;
179 }
180 
181 #undef d
void layoutDiagrams() override
Distribute the available space among the diagrams and axes.
qreal height() const const
The class for ternary axes.
QRect areaGeometry() const override
qreal x() const const
const QPointF translate(const QPointF &diagramPoint) const override
Translate the given point in value space coordinates to a position in pixel space.
Base class common for all coordinate planes, CartesianCoordinatePlane, PolarCoordinatePlane,...
Stores information about painting diagrams.
void addDiagram(AbstractDiagram *diagram) override
Adds a diagram to this coordinate plane.
int size() const const
void setX(qreal x)
void setY(qreal y)
QSizeF expandedTo(const QSizeF &otherSize) const const
void adjust(qreal dx1, qreal dy1, qreal dx2, qreal dy2)
bool isEmpty() const const
virtual void addDiagram(AbstractDiagram *diagram)
Adds a diagram to this coordinate plane.
qreal x() const const
qreal y() const const
qreal width() const const
AbstractDiagram defines the interface for diagram classes.
void setRenderHint(QPainter::RenderHint hint, bool on)
A chart with one or more diagrams.
Definition: KChartChart.h:84
Base class for diagrams based on a ternary coordinate plane.
qreal width() const const
qreal height() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Tue Aug 9 2022 03:55:05 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.