KD Chart API Documentation 3.1
Loading...
Searching...
No Matches
KDChartPolarCoordinatePlane.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 "KDChartPolarCoordinatePlane_p.h"
13
16#include "KDChartChart.h"
17#include "KDChartPaintContext.h"
18#include "KDChartPainterSaver_p.h"
19#include "KDChartPolarDiagram.h"
20
21#include <math.h>
22
23#include <QFont>
24#include <QList>
25#include <QPainter>
26#include <QTimer>
27#include <QtDebug>
28
29#include <KDABLibFakes>
30
31using namespace KDChart;
32
33#define d d_func()
34
36 : AbstractCoordinatePlane(new Private(), parent)
37{
38 // this block left empty intentionally
39}
40
42{
43 // this block left empty intentionally
44}
45
46void PolarCoordinatePlane::init()
47{
48 // this block left empty intentionally
49}
50
52{
54 "PolarCoordinatePlane::addDiagram", "Only polar"
55 "diagrams can be added to a polar coordinate plane!");
58}
59
61{
63 if (d->coordinateTransformations.size() != diags.size()) {
64 // diagrams have not been set up yet
65 return;
66 }
67 // need at least one so d->currentTransformation can be a valid pointer
68 Q_ASSERT(!d->coordinateTransformations.isEmpty());
69
71 ctx.setPainter(painter);
72 ctx.setCoordinatePlane(this);
73 ctx.setRectangle(geometry() /*d->contentRect*/);
74
75 // 1. ask (only!) PolarDiagrams if they need additional space for data labels / data comments
76
77 const qreal oldZoomX = zoomFactorX();
78 const qreal oldZoomY = zoomFactorY();
79 d->newZoomX = oldZoomX;
80 d->newZoomY = oldZoomY;
81 for (int i = 0; i < diags.size(); i++) {
82 d->currentTransformation = &(d->coordinateTransformations[i]);
85 auto *polarDia = dynamic_cast<PolarDiagram *>(diags[i]);
86 if (polarDia) {
87 polarDia->paint(&ctx, true, zoomX, zoomY);
88 d->newZoomX = qMin(d->newZoomX, zoomX);
89 d->newZoomY = qMin(d->newZoomY, zoomY);
90 }
91 }
92
93 if (d->newZoomX != oldZoomX || d->newZoomY != oldZoomY) {
94 // qDebug() << "new zoom:" << d->newZoomY << " old zoom:" << oldZoomY;
95 d->currentTransformation = nullptr; // not painting anymore until we get called again
96 QMetaObject::invokeMethod(this, "adjustZoomAndRepaint", Qt::QueuedConnection);
97 return;
98 }
99
100 // 2. there was room enough for the labels, so start drawing
101
102 // paint the coordinate system rulers:
103 d->currentTransformation = &d->coordinateTransformations.first();
104 d->grid->drawGrid(&ctx);
105
106 // paint the diagrams which will re-use their DataValueTextInfoList(s) filled in step 1:
107 for (int i = 0; i < diags.size(); i++) {
108 d->currentTransformation = &(d->coordinateTransformations[i]);
109 PainterSaver painterSaver(painter);
110 auto *polarDia = dynamic_cast<PolarDiagram *>(diags[i]);
111 if (polarDia) {
113 polarDia->paint(&ctx, false, dummy1, dummy2);
114 } else {
115 diags[i]->paint(&ctx);
116 }
117 }
118 d->currentTransformation = nullptr;
119}
120
122{
123 const qreal newZoom = qMin(d->newZoomX, d->newZoomY);
125 update();
126}
127
129{
130 d->initialResizeEventReceived = true;
132}
133
135{
136 // the rectangle the diagrams cover in the *plane*:
137 // (Why -3? We save 1px on each side for the antialiased drawing, and
138 // respect the way QPainter calculates the width of a painted rect (the
139 // size is the rectangle size plus the pen width). This way, most clipping
140 // for regular pens should be avoided. When pens with a penWidth or larger
141 // than 1 are used, this may not b sufficient.
142 const QRect rect(areaGeometry());
143 d->contentRect = QRectF(1, 1, rect.width() - 3, rect.height() - 3);
144
145 const ZoomParameters zoom = d->coordinateTransformations.isEmpty() ? ZoomParameters()
146 : d->coordinateTransformations.front().zoom;
147 // FIXME distribute space according to options:
149 d->coordinateTransformations.clear();
150 const auto constDiagrams = diagrams();
151 for (AbstractDiagram *diagram : constDiagrams) {
152 auto *polarDiagram = dynamic_cast<AbstractPolarDiagram *>(diagram);
153 Q_ASSERT(polarDiagram);
154 QPair<QPointF, QPointF> dataBoundariesPair = polarDiagram->dataBoundaries();
155
156 const qreal angleUnit = 360 / polarDiagram->valueTotals();
157 // qDebug() << "--------------------------------------------------------";
158 const qreal radius = qAbs(dataBoundariesPair.first.y()) + dataBoundariesPair.second.y();
159 // qDebug() << radius <<"="<<dataBoundariesPair.second.y();
160 const qreal diagramWidth = radius * 2; // == height
161 const qreal planeWidth = d->contentRect.width();
162 const qreal planeHeight = d->contentRect.height();
164 // qDebug() << radiusUnit <<"=" << "qMin( "<<planeWidth<<","<< planeHeight <<") / "<<diagramWidth;
166 coordinateOrigin += d->contentRect.topLeft();
167
169 diagramTransposition.originTranslation = coordinateOrigin;
170 diagramTransposition.radiusUnit = radiusUnit;
174 diagramTransposition.minValue = dataBoundariesPair.first.y() < 0 ? dataBoundariesPair.first.y() : 0.0;
175 d->coordinateTransformations.append(diagramTransposition);
176 }
177 update();
178}
179
180const QPointF PolarCoordinatePlane::translate(const QPointF &diagramPoint) const
181{
182 Q_ASSERT_X(d->currentTransformation != nullptr, "PolarCoordinatePlane::translate",
183 "Only call translate() from within paint().");
184 return d->currentTransformation->translate(diagramPoint);
185}
186
188{
189 Q_ASSERT_X(d->currentTransformation != nullptr, "PolarCoordinatePlane::translate",
190 "Only call translate() from within paint().");
191 return d->currentTransformation->translatePolar(diagramPoint);
192}
193
195{
196 Q_ASSERT_X(d->currentTransformation != nullptr, "PolarCoordinatePlane::angleUnit",
197 "Only call angleUnit() from within paint().");
198 return d->currentTransformation->angleUnit;
199}
200
202{
203 Q_ASSERT_X(d->currentTransformation != nullptr, "PolarCoordinatePlane::radiusUnit",
204 "Only call radiusUnit() from within paint().");
205 return d->currentTransformation->radiusUnit;
206}
207
209{
210 if (d->initialResizeEventReceived)
212}
213
215{
216 Q_ASSERT_X(diagram(), "PolarCoordinatePlane::setStartPosition",
217 "setStartPosition() needs a diagram to be associated to the plane.");
218 for (CoordinateTransformationList::iterator it = d->coordinateTransformations.begin();
219 it != d->coordinateTransformations.end();
220 ++it) {
222 trans.startPosition = degrees;
223 }
224}
225
227{
228 return d->coordinateTransformations.isEmpty()
229 ? 0.0
230 : d->coordinateTransformations.first().startPosition;
231}
232
234{
235 return d->coordinateTransformations.isEmpty()
236 ? 1.0
237 : d->coordinateTransformations.first().zoom.xFactor;
238}
239
241{
242 return d->coordinateTransformations.isEmpty()
243 ? 1.0
244 : d->coordinateTransformations.first().zoom.yFactor;
245}
246
247void PolarCoordinatePlane::setZoomFactors(qreal factorX, qreal factorY)
248{
251}
252
254{
255 for (CoordinateTransformationList::iterator it = d->coordinateTransformations.begin();
256 it != d->coordinateTransformations.end();
257 ++it) {
260 }
261}
262
264{
265 for (CoordinateTransformationList::iterator it = d->coordinateTransformations.begin();
266 it != d->coordinateTransformations.end();
267 ++it) {
270 }
271}
272
274{
275 return d->coordinateTransformations.isEmpty()
276 ? QPointF(0.5, 0.5)
277 : QPointF(d->coordinateTransformations.first().zoom.xCenter, d->coordinateTransformations.first().zoom.yCenter);
278}
279
281{
282 for (CoordinateTransformationList::iterator it = d->coordinateTransformations.begin();
283 it != d->coordinateTransformations.end();
284 ++it) {
286 trans.zoom.xCenter = center.x();
287 trans.zoom.yCenter = center.y();
288 }
289}
290
292{
294
295 // FIXME(khz): do the real calculation
296
297 return l;
298}
299
301 bool circular,
302 const GridAttributes &a)
303{
304 if (circular)
305 d->gridAttributesCircular = a;
306 else
307 d->gridAttributesSagittal = a;
308 setHasOwnGridAttributes(circular, true);
309 update();
310 Q_EMIT propertiesChanged();
311}
312
314 bool circular)
315{
316 setHasOwnGridAttributes(circular, false);
317 update();
318}
319
321 bool circular) const
322{
323 if (hasOwnGridAttributes(circular)) {
324 if (circular)
325 return d->gridAttributesCircular;
326 else
327 return d->gridAttributesSagittal;
328 } else {
329 return globalGridAttributes();
330 }
331}
332
333QRectF KDChart::PolarCoordinatePlane::Private::contentsRect(const KDChart::PolarCoordinatePlane *plane)
334{
335 QRectF contentsRect;
336 QPointF referencePointAtTop = plane->translate(QPointF(1, 0));
337 QPointF temp = plane->translate(QPointF(0, 0)) - referencePointAtTop;
338 const qreal offset = temp.y();
339 referencePointAtTop.setX(referencePointAtTop.x() - offset);
340 contentsRect.setTopLeft(referencePointAtTop);
341 contentsRect.setBottomRight(referencePointAtTop + QPointF(2.0 * offset, 2.0 * offset));
342 return contentsRect;
343}
344
345void KDChart::PolarCoordinatePlane::setHasOwnGridAttributes(
346 bool circular, bool on)
347{
348 if (circular)
349 d->hasOwnGridAttributesCircular = on;
350 else
351 d->hasOwnGridAttributesSagittal = on;
352 Q_EMIT propertiesChanged();
353}
354
356 bool circular) const
357{
358 return (circular)
359 ? d->hasOwnGridAttributesCircular
360 : d->hasOwnGridAttributesSagittal;
361}
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.
void layoutChanged(AbstractDiagram *)
Base class for diagrams based on a polar coordinate system.
A chart with one or more diagrams.
A set of attributes controlling the appearance of grids.
Stores information about painting diagrams.
void setPainter(QPainter *painter)
const GridAttributes gridAttributes(bool circular) const
void addDiagram(AbstractDiagram *diagram) override
void setZoomCenter(const QPointF &center) override
DataDimensionsList getDataDimensionsList() const override
void setStartPosition(qreal degrees)
Specify the rotation of the coordinate plane.
const QPointF translate(const QPointF &diagramPoint) const override
void setZoomFactors(qreal factorX, qreal factorY) override
void setGridAttributes(bool circular, const GridAttributes &)
void slotLayoutChanged(AbstractDiagram *diagram)
const QPointF translatePolar(const QPointF &diagramPoint) const
PolarDiagram defines a common polar diagram.
void paint(PaintContext *paintContext) override
bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0, QGenericArgument val1, QGenericArgument val2, QGenericArgument val3, QGenericArgument val4, QGenericArgument val5, QGenericArgument val6, QGenericArgument val7, QGenericArgument val8, QGenericArgument val9)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
T qobject_cast(QObject *object)
void setX(qreal x)
qreal x() const const
qreal y() const const
int height() const const
int width() const const
void setBottomRight(const QPointF &position)
void setTopLeft(const QPointF &position)
QueuedConnection

© 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 on Fri Apr 26 2024 00:04:57 for KD Chart API Documentation by doxygen 1.9.8