KD Chart API Documentation  3.1
KDChartTernaryCoordinatePlane.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** This file is part of the KD Chart library.
4 **
5 ** SPDX-FileCopyrightText: 2001 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
6 **
7 ** SPDX-License-Identifier: MIT
8 **
9 ****************************************************************************/
10 
12 #include "KDChartTernaryCoordinatePlane_p.h"
13 
14 #include <QPainter>
15 #include <QtDebug>
16 
18 #include "KDChartPaintContext.h"
19 #include "KDChartPainterSaver_p.h"
20 #include "KDChartTernaryAxis.h"
21 
22 #include "TernaryConstants.h"
23 
24 using namespace KDChart;
25 
26 #define d d_func()
27 
28 TernaryCoordinatePlane::Private::Private()
29  : AbstractCoordinatePlane::Private()
30 {
31 }
32 
33 TernaryCoordinatePlane::TernaryCoordinatePlane(Chart *parent)
34  : AbstractCoordinatePlane(new Private(), parent)
35 {
36 }
37 
39 {
40 }
41 
42 void TernaryCoordinatePlane::init()
43 {
44 }
45 
47 {
48  Q_ASSERT_X(dynamic_cast<AbstractTernaryDiagram *>(diagram),
49  "TernaryCoordinatePlane::addDiagram", "Only ternary "
50  "diagrams can be added to a ternary coordinate plane!");
52 }
53 
55 { // this is our "resize event":
56  // all diagrams always take the same space, nothing to be done here
57  // the "inner" margin (adjustments to diagram coordinates)
58  QRectF diagramNativeRectangle(QPointF(0.0, 0.0),
59  QSizeF(TriangleWidth, TriangleHeight));
60  QPair<QSizeF, QSizeF> margins = grid()->requiredMargins();
61  d->diagramRect = areaGeometry();
62  diagramNativeRectangle.adjust(-margins.first.width(), -margins.first.height(),
63  margins.second.width(), margins.second.height());
64 
65  // the "outer" margin (distance between diagram contents and area,
66  // determined by axis label overlap
67  {
68  QSizeF topleft(0.0, 0.0);
69  QSizeF bottomRight(0.0, 0.0);
70  const auto constDiagrams = diagrams();
71  for (AbstractDiagram *abstractDiagram : constDiagrams) {
72  auto *diagram =
73  qobject_cast<AbstractTernaryDiagram *>(abstractDiagram);
74  Q_ASSERT(diagram);
75  const auto constAxes = diagram->axes();
76  for (TernaryAxis *axis : constAxes) {
77  QPair<QSizeF, QSizeF> margin = axis->requiredMargins();
78  topleft = topleft.expandedTo(margin.first);
79  bottomRight = bottomRight.expandedTo(margin.second);
80  }
81  }
82  d->diagramRectContainer =
83  d->diagramRect.adjusted(topleft.width(),
84  topleft.height(),
85  -bottomRight.width(),
86  -bottomRight.height());
87  }
88 
89  // now calculate isometric projection, x and y widget coordinate
90  // units, and location of (0.0, 0.0) in diagram coordinates
91  QPointF zeroZeroPoint = d->diagramRectContainer.bottomLeft();
92  qreal w = d->diagramRectContainer.width();
93  qreal h = d->diagramRectContainer.height();
94  qreal usableWidth;
95  qreal usableHeight;
96 
97  if (TriangleHeight * w > h) {
98  // shorten width:
99  usableWidth = h / diagramNativeRectangle.height();
100  usableHeight = h;
101  zeroZeroPoint.setX(zeroZeroPoint.x() + (w - usableWidth) / 2);
102  } else {
103  // reduce height:
104  usableWidth = w;
105  usableHeight = diagramNativeRectangle.height() * w;
106  zeroZeroPoint.setY(zeroZeroPoint.y() - (h - usableHeight) / 2);
107  }
108  // the rectangle has 1 as it's width, and TriangleHeight as it's
109  // height - so this is how we translate that to widget coordinates:
110  d->xUnit = usableWidth / diagramNativeRectangle.width(); // only because we normalize the values to [0..1]
111  d->yUnit = -usableHeight / diagramNativeRectangle.height();
112 
113  // now move zeroZeroPoint so that it does not include the tick marks
114  {
115  qreal descent = diagramNativeRectangle.height() - TriangleHeight;
116  qreal rightShift = -diagramNativeRectangle.x();
117  zeroZeroPoint += QPointF(rightShift * d->xUnit, descent * d->yUnit);
118  }
119 
120  d->diagramRect.setBottomLeft(zeroZeroPoint);
121  d->diagramRect.setTopRight(QPointF(usableWidth, -usableHeight) + zeroZeroPoint);
122 }
123 
124 const QPointF TernaryCoordinatePlane::translate(const QPointF &point) const
125 {
126  return QPointF(d->diagramRect.bottomLeft().x() + point.x() * d->xUnit,
127  d->diagramRect.bottomLeft().y() + point.y() * d->yUnit);
128 }
129 
131 {
132  // FIXME temp
133  return QSize();
134 }
135 
137 {
138  return QSizePolicy(QSizePolicy::MinimumExpanding,
139  QSizePolicy::MinimumExpanding);
140 }
141 
142 void TernaryCoordinatePlane::paint(QPainter *painter)
143 {
144  PainterSaver s(painter);
145  // FIXME: this is not a good location for that:
146  painter->setRenderHint(QPainter::Antialiasing, true);
147 
148  AbstractDiagramList diags = diagrams();
149  if (!diags.isEmpty()) {
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  PainterSaver diagramPainterSaver(painter);
163  diags[i]->paint(&ctx);
164  }
165  }
166 }
167 
169 { // not needed
170  return DataDimensionsList();
171 }
172 
173 TernaryGrid *TernaryCoordinatePlane::grid() const
174 {
175  auto *ternaryGrid = static_cast<TernaryGrid *>(d->grid);
176  Q_ASSERT(dynamic_cast<TernaryGrid *>(d->grid));
177  return ternaryGrid;
178 }
179 
180 #undef d
const qreal TriangleHeight
const qreal TriangleWidth
QRect areaGeometry() const override
Base class common for all coordinate planes, CartesianCoordinatePlane, PolarCoordinatePlane,...
virtual void addDiagram(AbstractDiagram *diagram)
AbstractDiagram defines the interface for diagram classes.
Base class for diagrams based on a ternary coordinate plane.
A chart with one or more diagrams.
Definition: KDChartChart.h:84
Stores information about painting diagrams.
void setPainter(QPainter *painter)
void setCoordinatePlane(AbstractCoordinatePlane *plane)
void setRectangle(const QRectF &rect)
DataDimensionsList getDataDimensionsList() const override
void addDiagram(AbstractDiagram *diagram) override
const QPointF translate(const QPointF &diagramPoint) const override
QPair< QSizeF, QSizeF > requiredMargins() const
QList< AbstractDiagram * > AbstractDiagramList
QList< DataDimension > DataDimensionsList

© 2001 Klarälvdalens Datakonsult AB (KDAB)
"The Qt, C++ and OpenGL Experts"
https://www.kdab.com/
https://www.kdab.com/development-resources/qt-tools/kd-chart/
Generated by doxygen 1.9.1