summaryrefslogtreecommitdiff
path: root/src/charts/ChartScene.cpp
blob: 559ecc5edd4d6a7cccaec7c72d47e8224c55f3d4 (plain)
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
#include "ChartScene.h"
#include "ChartAxes.h"
#include <cstdlib>
#include <cmath>
#include "ChartDataLine.h"

const QSizeF ChartScene::Margin(30, 20);
const QSizeF ChartScene::Padding(20, 20);
const QSizeF ChartScene::DataSetPadding(10, 10);

ChartScene::ChartScene(Chart* chart):
    QGraphicsScene(chart), chart(chart), dataDirection(1)
{
    setSceneRect(0, 0, 600, 300);
}

void ChartScene::setDataSet(const QList<DataPoint>& dataSet, int xTickInterval)
{
    clear();
    this->dataSet = dataSet;
    initYScale();
    ChartAxes(this, xTickInterval).paint();
    ChartDataLine(this).paint();
}

void ChartScene::initYScale()
{
    yMin = computeMinY();
    yMax = computeMaxY();
    yTickSpacing = computeYTickSpacing();
    extendYMinMax();
    yScale = getDataSetSize().height() / getYDiff();
}

int ChartScene::computeMinY() const
{
    int min = 1000000;
    foreach(DataPoint point, dataSet)
        if(point.value < min)
            min = point.value;
    return min;
}

int ChartScene::computeMaxY() const
{
    int max = -1000000;
    foreach(DataPoint point, dataSet)
        if(point.value > max)
            max = point.value;
    return max;
}

int ChartScene::computeYTickSpacing() const
{
    const int higherZonesLimit = 4;
    const int lowerZonesLimit = 3;

    double order = floor(log10(getYDiff()));
    double base = pow(10, order);
    double zonesNum = ceil(getYDiff() / base);
    if(zonesNum > higherZonesLimit)
        base *= 2;
    else if(zonesNum < lowerZonesLimit)
        base /= 2;
    int res = (int)base;
    if(res == 0)
        res = 10;
    return res;
}

void ChartScene::extendYMinMax()
{
    yMin = int(floor(yMin / double(yTickSpacing))) * yTickSpacing;
    yMax = int(ceil(yMax / double(yTickSpacing))) * yTickSpacing;
    if (yMax == yMin)
        yMax = yMin + yTickSpacing;
}

QSizeF ChartScene::getBorder()
{
    return Margin + Padding;
}

QRectF ChartScene::getChartRect() const
{
    QSizeF border = getBorder();
    return sceneRect().adjusted(border.width(), border.height(),
        -border.width(), -border.height());
}

QPointF ChartScene::getChartOrigin() const
{
    QRectF chartRect = getChartRect();
    return QPointF(chartRect.left(), chartRect.bottom());
}

QSizeF ChartScene::getDataSetSize() const
{
    QSizeF dataSetBorder(2 * getBorder() + DataSetPadding);
    return sceneRect().size() - dataSetBorder;
}

qreal ChartScene::getXTickSpacing() const
{
    return getDataSetSize().width() / (dataSet.size() - 1);
}

qreal ChartScene::getYPosFromValue(int value) const
{
    return yScale * value;
}