KD Chart API Documentation 3.1
Loading...
Searching...
No Matches
KDChartRadarGrid.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
11#include "KDChartRadarGrid.h"
12#include "KDChartPaintContext.h"
13#include "KDChartPieDiagram.h"
15#include "KDChartRadarDiagram.h"
16
17#include <QPainter>
18
19#include <KDABLibFakes>
20
21using namespace KDChart;
22
23DataDimensionsList RadarGrid::calculateGrid(
24 const DataDimensionsList &rawDataDimensions) const
25{
26 qDebug("Calling PolarGrid::calculateGrid()");
28
29 // FIXME(khz): do the real calculation
30
31 l = rawDataDimensions;
32
33 return l;
34}
35
36static qreal fitFontSizeToGeometry(const QString &text, const QFont &font, const QRectF &geometry, const TextAttributes &ta)
37{
38 QFont f = font;
39 const qreal origResult = f.pointSizeF();
40 qreal result = origResult;
41 const QSizeF mySize = geometry.size();
42 if (mySize.isNull())
43 return result;
44
45 const QString t = text;
46 QFontMetrics fm(f);
47 while (true) {
48 const QSizeF textSize = rotatedRect(fm.boundingRect(t), ta.rotation()).normalized().size();
49
50 if (textSize.height() <= mySize.height() && textSize.width() <= mySize.width())
51 return result;
52
53 result -= 0.5;
54 if (result <= 0.0)
55 return origResult;
56 f.setPointSizeF(result);
57 fm = QFontMetrics(f);
58 }
59}
60
61QPointF scaleToRealPosition(const QPointF &origin, const QRectF &sourceRect, const QRectF &destRect, const AbstractCoordinatePlane &plane)
62{
63 QPointF result = plane.translate(origin);
64 result -= sourceRect.topLeft();
65 result.setX(result.x() / sourceRect.width() * destRect.width());
66 result.setY(result.y() / sourceRect.height() * destRect.height());
67 result += destRect.topLeft();
68 return result;
69}
70
71QPointF scaleToRect(const QPointF &origin, const QRectF &sourceRect, const QRectF &destRect)
72{
73 QPointF result(origin);
74 result -= sourceRect.topLeft();
75 result.setX(result.x() / sourceRect.width() * destRect.width());
76 result.setY(result.y() / sourceRect.height() * destRect.height());
77 result += destRect.topLeft();
78 return result;
79}
80
82{
83 const QBrush backupBrush(context->painter()->brush());
84 context->painter()->setBrush(QBrush());
85 auto *plane = dynamic_cast<RadarCoordinatePlane *>(context->coordinatePlane());
86 Q_ASSERT(plane);
87 Q_ASSERT(plane->diagram());
88 QPair<QPointF, QPointF> boundaries = plane->diagram()->dataBoundaries();
89 Q_ASSERT_X(plane, "PolarGrid::drawGrid",
90 "Bad function call: PaintContext::coodinatePlane() NOT a polar plane.");
91
92 const GridAttributes gridAttrsCircular(plane->gridAttributes(true));
93 const GridAttributes gridAttrsSagittal(plane->gridAttributes(false));
94
95 // qDebug() << "OK:";
96 if (!gridAttrsCircular.isGridVisible() && !gridAttrsSagittal.isGridVisible())
97 return;
98 // qDebug() << "A";
99
100 // FIXME: we paint the rulers to the settings of the first diagram for now:
101 AbstractPolarDiagram *dgr = dynamic_cast<AbstractPolarDiagram *>(plane->diagrams().first());
102 Q_ASSERT(dgr); // only polar diagrams are allowed here
103
104 // Do not draw a grid for pie diagrams
105 if (dynamic_cast<PieDiagram *>(plane->diagrams().first()))
106 return;
107
109 const qreal min = dgr->dataBoundaries().first.y();
110 QPointF origin = plane->translate(QPointF(min, 0)) + context->rectangle().topLeft();
111 // qDebug() << "origin" << origin;
112
113 const qreal r = qAbs(min) + dgr->dataBoundaries().second.y(); // use the full extents
114
115 // distance between two axis lines
116 const qreal step = (r - qAbs(min)) / (dgr->numberOfGridRings());
117
118 // calculate the height needed for text to be displayed at the bottom and top of the chart
119 QPointF topLeft = context->rectangle().topLeft();
120 Q_ASSERT(plane->diagram()->model());
121 TextAttributes ta = plane->textAttributes();
122 const int numberOfSpokes = ( int )(360 / plane->angleUnit());
123 const qreal stepWidth = boundaries.second.y() / (dgr->numberOfGridRings());
124 QRectF destRect = context->rectangle();
125 if (ta.isVisible()) {
126 QAbstractItemModel *model = plane->diagram()->model();
127 QRectF fontRect = context->rectangle();
128 fontRect.setSize(QSizeF(fontRect.width(), step / 2.0));
129 const qreal labelFontSize = fitFontSizeToGeometry(QString::fromLatin1("TestXYWQgqy"), ta.font(), fontRect, ta);
130 QFont labelFont = ta.font();
131 context->painter()->setPen(ta.pen());
132 labelFont.setPointSizeF(labelFontSize);
133 const QFontMetricsF metric(labelFont);
134 const qreal labelHeight = metric.height();
135 QPointF offset;
136 destRect.setY(destRect.y() + 2 * labelHeight);
137 destRect.setHeight(destRect.height() - 4 * labelHeight);
138 offset.setY(labelHeight);
139 offset.setX(0);
140 topLeft += offset;
141 origin += offset;
142 origin = scaleToRealPosition(QPointF(min, 0), context->rectangle(), destRect, *plane);
143
144 const qreal aWidth = metric.horizontalAdvance(QString::fromLatin1("A"));
145 const QLineF startLine(origin, scaleToRealPosition(QPointF(r - qAbs(min), 0), context->rectangle(), destRect, *plane));
146 for (int i = 0; i < model->rowCount(); ++i) {
147 const QLineF currentLine(origin, scaleToRealPosition(QPointF(r - qAbs(min), i), context->rectangle(), destRect, *plane));
148 const int angle = ( int )startLine.angleTo(currentLine) % 360;
149 const qreal angleTest = qAbs(angle - 180);
150 const QString data = model->headerData(i, Qt::Vertical).toString();
151 const qreal xOffset = metric.horizontalAdvance(data) / 2.0;
152 if (angleTest < 5.0)
153 context->painter()->drawText(currentLine.pointAt(1) + QPointF(-xOffset, labelHeight + qAbs(min)), data);
154 else if (qAbs(angleTest - 180) < 5.0)
155 context->painter()->drawText(currentLine.pointAt(1) - QPointF(xOffset, labelHeight + qAbs(min)), data);
156 else if (angle < 175 && angle > 5)
157 context->painter()->drawText(currentLine.pointAt(1) - QPointF(xOffset * 2 + qAbs(min) + aWidth, -labelHeight / 2.0 + qAbs(min)), data);
158 else if (angle < 355 && angle > 185)
159 context->painter()->drawText(currentLine.pointAt(1) + QPointF(qAbs(min) + aWidth, labelHeight / 2.0 + qAbs(min)), data);
160 }
161 }
163 if (plane->globalGridAttributes().isGridVisible()) {
164 for (int j = 1; j < dgr->numberOfGridRings() + 1; ++j) {
165 QPointF oldPoint(scaleToRealPosition(QPointF(j * step - qAbs(min), numberOfSpokes - 1), context->rectangle(), destRect, *plane));
166 for (int i = 0; i < numberOfSpokes; ++i) {
167 const QPointF newPoint = scaleToRealPosition(QPointF(j * step - qAbs(min), i), context->rectangle(), destRect, *plane);
168 context->painter()->drawLine(oldPoint, newPoint);
169 oldPoint = newPoint;
170
171 context->painter()->drawLine(origin, newPoint);
172 }
173 }
174 context->painter()->setPen(ta.pen());
175 qreal fontSize = 0;
176 for (int i = 0; i < dgr->numberOfGridRings() + 1; ++i) {
177 const QString text = QString::number(i * stepWidth);
178 const QPointF translatedPoint = scaleToRealPosition(QPointF(i * step - qAbs(min), 0), context->rectangle(), destRect, *plane);
179 const QFontMetrics metric(ta.font() /*QFont( "Arial", 10 )*/);
180 const qreal textLength = metric.horizontalAdvance(text);
181 const qreal textHeight = metric.height() / 2.0;
182 QPointF textOffset(textLength, -textHeight);
183 textOffset = scaleToRect(textOffset, context->rectangle(), destRect);
184 QPointF _topLeft = topLeft;
185 _topLeft.setY(translatedPoint.y());
186 QRectF boundary(_topLeft, (translatedPoint + QPointF(0, step / 2.0)));
187 const qreal calcFontSize = fitFontSizeToGeometry(text, ta.font(), boundary, ta);
188 if (fontSize != calcFontSize) {
189 QFont paintFont(ta.font());
190 paintFont.setPointSizeF(calcFontSize);
191 ta.setFont(paintFont);
192 ta.setFontSize(calcFontSize);
193 const qreal textHeight2 = QFontMetricsF(paintFont).height() / 2.0;
194 textOffset.setY(-textHeight2);
195 textOffset = scaleToRect(textOffset, context->rectangle(), destRect);
196 context->painter()->setFont(paintFont);
197 fontSize = calcFontSize;
198 }
199 context->painter()->drawText(translatedPoint + destRect.topLeft() - textOffset, text);
200 }
201 }
202 plane->setTextAttributes(ta);
204 context->painter()->setBrush(backupBrush);
205}
QRectF rotatedRect(const QRectF &rect, qreal rotation)
static QPointF scaleToRealPosition(const QPointF &origin, const QRectF &sourceRect, const QRectF &destRect, const AbstractCoordinatePlane &plane)
static qreal fitFontSizeToGeometry(const QString &text, const QFont &font, const QRectF &geometry, const TextAttributes &ta)
QPointF scaleToRect(const QPointF &origin, const QRectF &sourceRect, const QRectF &destRect)
Base class common for all coordinate planes, CartesianCoordinatePlane, PolarCoordinatePlane,...
virtual const QPointF translate(const QPointF &diagramPoint) const =0
const QPair< QPointF, QPointF > dataBoundaries() const
Return the bottom left and top right data point, that the diagram will display (unless the grid adjus...
Base class for diagrams based on a polar coordinate system.
virtual qreal numberOfGridRings() const =0
A set of attributes controlling the appearance of grids.
Stores information about painting diagrams.
const QRectF rectangle() const
AbstractCoordinatePlane * coordinatePlane() const
PieDiagram defines a common pie diagram.
static QPen scalePen(const QPen &pen)
void drawGrid(PaintContext *context) override
A set of text attributes.
void setFontSize(const Measure &measure)
void setFont(const QFont &font)
virtual QVariant headerData(int section, Qt::Orientation orientation, int role) const const
virtual int rowCount(const QModelIndex &parent) const const=0
qreal pointSizeF() const const
void setPointSizeF(qreal pointSize)
QRect boundingRect(QChar ch) const const
int height() const const
int horizontalAdvance(const QString &text, int len) const const
qreal height() const const
qreal horizontalAdvance(const QString &text, int length) const const
qreal angleTo(const QLineF &line) const const
QPointF pointAt(qreal t) const const
const QBrush & brush() const const
void drawLine(const QLineF &line)
void drawText(const QPointF &position, const QString &text)
void setBrush(const QBrush &brush)
void setFont(const QFont &font)
void setPen(const QColor &color)
void setX(qreal x)
void setY(qreal y)
qreal x() const const
qreal y() const const
qreal height() const const
QRectF normalized() const const
void setHeight(qreal height)
void setSize(const QSizeF &size)
void setY(qreal y)
QSizeF size() const const
QPointF topLeft() const const
qreal width() const const
qreal y() const const
qreal height() const const
bool isNull() const const
qreal width() const const
QString fromLatin1(const char *str, int size)
QString number(int n, int base)
lightGray
Vertical
QString toString() const const

© 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