1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
|
#include "ChartAxes.h"
#include "ChartScene.h"
#include <cmath>
const QPointF ChartAxes::XLabelOffset(0, 5);
const QPointF ChartAxes::YLabelOffset(-10, -7);
const QFont ChartAxes::TickLabelFont("Sans Serif", 11);
ChartAxes::ChartAxes(ChartScene* scene, int xTickInterval):
scene(scene), xTickInterval(xTickInterval)
{
}
void ChartAxes::paint()
{
addAxisLines();
addTicks();
}
void ChartAxes::addAxisLines()
{
QPointF chartOrigin = scene->getChartOrigin();
QRectF chartRect = scene->getChartRect();
scene->addLine(QLineF(chartOrigin, chartRect.topLeft()));
scene->addLine(QLineF(chartOrigin, chartRect.bottomRight()));
}
void ChartAxes::addTicks()
{
addXTicks();
addYTicks();
}
void ChartAxes::addXTicks()
{
qreal tickSpacing = scene->getDataDirection() * scene->getXTickSpacing();
QPointF pos = getTickOrigin(XTick);
for(int i = 0; i < scene->getDataSet().size(); i++)
{
addLabelledXTick(i, pos);
pos.rx() += tickSpacing;
}
}
void ChartAxes::addLabelledXTick(int index, QPointF& pos)
{
if(index % xTickInterval == 0)
{
addTick(pos, XTick);
DataPoint point = scene->getDataSet().at(index);
addLabel(point.label, pos, XTick);
}
}
QPointF ChartAxes::getTickOrigin(TickOrientation orientation) const
{
QPointF res = scene->getChartOrigin();
if(orientation == XTick)
{
if(scene->getDataDirection() == 1)
res.rx() += ChartScene::DataSetPadding.width();
else
res.rx() += scene->getChartRect().width();
}
else
res.ry() -= ChartScene::DataSetPadding.height();
return res;
}
void ChartAxes::addTick(const QPointF& pos, TickOrientation orientation)
{
QPointF end = pos + getTickVector(orientation);
scene->addLine(QLineF(pos, end));
}
QPointF ChartAxes::getTickVector(TickOrientation orientation)
{
if(orientation == XTick)
return QPointF(0, TickLength);
else
return QPointF(-TickLength, 0);
}
void ChartAxes::addLabel(const QString& labelText, const QPointF& pos,
TickOrientation orientation)
{
QPointF labelOffset = getLabelOffset(orientation);
QGraphicsItem* textItem = scene->addSimpleText(labelText, TickLabelFont);
qreal xAlignOffset = getLabelXAlignOffset(
textItem->boundingRect().width(), orientation);
textItem->setPos(pos + labelOffset + QPointF(xAlignOffset, 0));
}
QPointF ChartAxes::getLabelOffset(TickOrientation orientation)
{
if(orientation == XTick)
return XLabelOffset;
else
return YLabelOffset;
}
qreal ChartAxes::getLabelXAlignOffset(qreal labelWidth, TickOrientation orientation)
{
if(orientation == XTick)
return -labelWidth / 2;
else
return -labelWidth;
}
void ChartAxes::addYTicks()
{
int valueSpacing = scene->getYTickSpacing();
qreal posSpacing = scene->getYPosFromValue(valueSpacing);
QPointF pos = getTickOrigin(YTick);
for(int value = scene->getMinY(); value <= scene->getMaxY();
value += valueSpacing)
{
addLabelledYTick(value, pos, posSpacing);
if(valueSpacing == 0)
break;
}
}
void ChartAxes::addLabelledYTick(int value, QPointF& pos, qreal posSpacing)
{
addTick(pos, YTick);
addLabel(QString::number(value), pos, YTick);
addHRuler(pos);
pos.ry() -= posSpacing;
}
void ChartAxes::addHRuler(const QPointF& pos)
{
QPointF end = pos;
end.rx() += scene->getChartRect().width();
scene->addLine(QLineF(pos, end), QPen(Qt::lightGray));
}
|