@@ -1,51 +1,52 | |||||
1 | /*! |
|
1 | /*! | |
2 | \page classes.html |
|
2 | \page classes.html | |
3 | \title QtCommercial Charts API |
|
3 | \title QtCommercial Charts API | |
4 | \keyword All Classes |
|
4 | \keyword All Classes | |
5 |
|
5 | |||
6 | \raw HTML |
|
6 | \raw HTML | |
7 | <table cellpadding="2" cellspacing="1" border="0" width="100%" class="indextable"> |
|
7 | <table cellpadding="2" cellspacing="1" border="0" width="100%" class="indextable"> | |
8 | <tr> |
|
8 | <tr> | |
9 | <th class="titleheader" width="33%"> |
|
9 | <th class="titleheader" width="33%"> | |
10 | List of classes |
|
10 | List of classes | |
11 | </th> |
|
11 | </th> | |
12 | </tr> |
|
12 | </tr> | |
13 | <tr> |
|
13 | <tr> | |
14 | <td valign="top"> |
|
14 | <td valign="top"> | |
15 | <ul> |
|
15 | <ul> | |
16 | <li><a href="qareaseries.html">QAreaSeries</a></li> |
|
16 | <li><a href="qareaseries.html">QAreaSeries</a></li> | |
17 | <li><a href="qbarseries.html">QBarSeries</a></li> |
|
17 | <li><a href="qbarseries.html">QBarSeries</a></li> | |
18 | <li><a href="qbarset.html">QBarSet</a></li> |
|
18 | <li><a href="qbarset.html">QBarSet</a></li> | |
19 | <li><a href="qchart.html">QChart</a></li> |
|
19 | <li><a href="qchart.html">QChart</a></li> | |
20 | <li><a href="qchartaxis.html">QChartAxis</a></li> |
|
20 | <li><a href="qchartaxis.html">QChartAxis</a></li> | |
21 | <li><a href="qchartview.html">QChartView</a></li> |
|
21 | <li><a href="qchartview.html">QChartView</a></li> | |
22 | <li><a href="qlineseries.html">QLineSeries</a></li> |
|
22 | <li><a href="qlineseries.html">QLineSeries</a></li> | |
23 | <li><a href="qpercentbarseries.html">QPercentBarSeries</a></li> |
|
23 | <li><a href="qpercentbarseries.html">QPercentBarSeries</a></li> | |
24 | <li><a href="qpieseries.html">QPieSeries</a></li> |
|
24 | <li><a href="qpieseries.html">QPieSeries</a></li> | |
25 | <li><a href="qpieslice.html">QPieSlice</a></li> |
|
25 | <li><a href="qpieslice.html">QPieSlice</a></li> | |
26 | <li><a href="qscatterseries.html">QScatterSeries</a></li> |
|
26 | <li><a href="qscatterseries.html">QScatterSeries</a></li> | |
27 | <li><a href="qseries.html">QSeries</a></li> |
|
27 | <li><a href="qseries.html">QSeries</a></li> | |
|
28 | <li><a href="qsplineseries.html">QSplineSeries</a></li> | |||
28 | <li><a href="qstackedbarseries.html">QStackedBarSeries</a></li> |
|
29 | <li><a href="qstackedbarseries.html">QStackedBarSeries</a></li> | |
29 | </ul> |
|
30 | </ul> | |
30 | </td> |
|
31 | </td> | |
31 | </tr> |
|
32 | </tr> | |
32 | </table> |
|
33 | </table> | |
33 |
|
34 | |||
34 | <table cellpadding="2" cellspacing="1" border="0" width="100%" class="indextable"> |
|
35 | <table cellpadding="2" cellspacing="1" border="0" width="100%" class="indextable"> | |
35 | <tr> |
|
36 | <tr> | |
36 | <th class="titleheader" width="33%"> |
|
37 | <th class="titleheader" width="33%"> | |
37 | Other files: |
|
38 | Other files: | |
38 | </th> |
|
39 | </th> | |
39 | </tr> |
|
40 | </tr> | |
40 | <tr> |
|
41 | <tr> | |
41 | <td valign="top"> |
|
42 | <td valign="top"> | |
42 | <ul> |
|
43 | <ul> | |
43 | <li><a href="qchartglobal.html">QChartGlobal</a></li> |
|
44 | <li><a href="qchartglobal.html">QChartGlobal</a></li> | |
44 | </ul> |
|
45 | </ul> | |
45 | </td> |
|
46 | </td> | |
46 | </tr> |
|
47 | </tr> | |
47 | </table> |
|
48 | </table> | |
48 |
|
49 | |||
49 | \endraw |
|
50 | \endraw | |
50 |
|
51 | |||
51 | */ |
|
52 | */ |
@@ -1,108 +1,142 | |||||
1 | #include "qsplineseries.h" |
|
1 | #include "qsplineseries.h" | |
2 |
|
2 | |||
|
3 | /*! | |||
|
4 | \class QSplineSeries | |||
|
5 | \brief Series type used to store data needed to draw a spline. | |||
|
6 | ||||
|
7 | QSplineSeries stores the data points along with the segment control points needed by QPainterPath to draw spline | |||
|
8 | Control points are automatically calculated when data changes. The algorithm computes the points so that the normal spline can be drawn. | |||
|
9 | */ | |||
|
10 | ||||
|
11 | /*! | |||
|
12 | \fn QSeriesType QSplineSeries::type() const | |||
|
13 | Returns the type of the series | |||
|
14 | */ | |||
|
15 | ||||
|
16 | /*! | |||
|
17 | \fn QSeriesType QSplineSeries::controlPoint(int index) const | |||
|
18 | Returns the control point specified by \a index | |||
|
19 | */ | |||
|
20 | ||||
3 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
21 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |
4 |
|
22 | |||
|
23 | /*! | |||
|
24 | Constructs empty series object which is a child of \a parent. | |||
|
25 | When series object is added to QChartView or QChart instance then the ownerships is transfered. | |||
|
26 | */ | |||
|
27 | ||||
5 | QSplineSeries::QSplineSeries(QObject *parent) : |
|
28 | QSplineSeries::QSplineSeries(QObject *parent) : | |
6 | QLineSeries(parent) |
|
29 | QLineSeries(parent) | |
7 | { |
|
30 | { | |
8 | connect(this,SIGNAL(pointAdded(int)), this, SLOT(updateControlPoints())); |
|
31 | connect(this,SIGNAL(pointAdded(int)), this, SLOT(updateControlPoints())); | |
9 | connect(this,SIGNAL(pointRemoved(int)), this, SLOT(updateControlPoints())); |
|
32 | connect(this,SIGNAL(pointRemoved(int)), this, SLOT(updateControlPoints())); | |
10 | connect(this,SIGNAL(pointReplaced(int)), this, SLOT(updateControlPoints())); |
|
33 | connect(this,SIGNAL(pointReplaced(int)), this, SLOT(updateControlPoints())); | |
11 | } |
|
34 | } | |
12 |
|
35 | |||
|
36 | /*! | |||
|
37 | \internal | |||
|
38 | Calculates control points which are needed by QPainterPath.cubicTo function to draw the cubic Bezier cureve between two points. | |||
|
39 | */ | |||
13 | void QSplineSeries::calculateControlPoints() |
|
40 | void QSplineSeries::calculateControlPoints() | |
14 | { |
|
41 | { | |
15 |
|
42 | |||
16 | // Based on http://www.codeproject.com/Articles/31859/Draw-a-Smooth-Curve-through-a-Set-of-2D-Points-wit |
|
43 | // Based on http://www.codeproject.com/Articles/31859/Draw-a-Smooth-Curve-through-a-Set-of-2D-Points-wit | |
17 |
// CPOL Licen |
|
44 | // CPOL License | |
18 |
|
45 | |||
19 | int n = m_x.size() - 1; |
|
46 | int n = m_x.size() - 1; | |
20 | if (n == 1) |
|
47 | if (n == 1) | |
21 | { // Special case: Bezier curve should be a straight line. |
|
48 | { // Special case: Bezier curve should be a straight line. | |
22 | // firstControlPoints = new Point[1]; |
|
49 | // firstControlPoints = new Point[1]; | |
23 | // 3P1 = 2P0 + P3 |
|
50 | // 3P1 = 2P0 + P3 | |
24 | m_controlPoints.append(QPointF((2 * m_x[0] + m_x[1]) / 3, (2 * m_y[0] + m_y[1]) / 3)); |
|
51 | m_controlPoints.append(QPointF((2 * m_x[0] + m_x[1]) / 3, (2 * m_y[0] + m_y[1]) / 3)); | |
25 |
|
52 | |||
26 | // P2 = 2P1 P0 |
|
53 | // P2 = 2P1 P0 | |
27 | m_controlPoints.append(QPointF(2 * m_controlPoints[0].x() - m_x[0], 2 * m_controlPoints[0].y() - m_y[0])); |
|
54 | m_controlPoints.append(QPointF(2 * m_controlPoints[0].x() - m_x[0], 2 * m_controlPoints[0].y() - m_y[0])); | |
28 | return; |
|
55 | return; | |
29 | } |
|
56 | } | |
30 |
|
57 | |||
31 | // Calculate first Bezier control points |
|
58 | // Calculate first Bezier control points | |
32 | // Right hand side vector |
|
59 | // Right hand side vector | |
33 | // Set of equations for P0 to Pn points. |
|
60 | // Set of equations for P0 to Pn points. | |
34 | // |
|
61 | // | |
35 | // | 2 1 0 0 ... 0 0 0 ... 0 0 0 | | P1_1 | | P0 + 2 * P1 | |
|
62 | // | 2 1 0 0 ... 0 0 0 ... 0 0 0 | | P1_1 | | P0 + 2 * P1 | | |
36 | // | 1 4 1 0 ... 0 0 0 ... 0 0 0 | | P1_2 | | 4 * P1 + 2 * P2 | |
|
63 | // | 1 4 1 0 ... 0 0 0 ... 0 0 0 | | P1_2 | | 4 * P1 + 2 * P2 | | |
37 | // | 0 1 4 1 ... 0 0 0 ... 0 0 0 | | P1_3 | | 4 * P2 + 2 * P3 | |
|
64 | // | 0 1 4 1 ... 0 0 0 ... 0 0 0 | | P1_3 | | 4 * P2 + 2 * P3 | | |
38 | // | . . . . . . . . . . . . | | ... | | ... | |
|
65 | // | . . . . . . . . . . . . | | ... | | ... | | |
39 | // | 0 0 0 0 ... 1 4 1 ... 0 0 0 | * | P1_i | = | 4 * P(i-1) + 2 * Pi | |
|
66 | // | 0 0 0 0 ... 1 4 1 ... 0 0 0 | * | P1_i | = | 4 * P(i-1) + 2 * Pi | | |
40 | // | . . . . . . . . . . . . | | ... | | ... | |
|
67 | // | . . . . . . . . . . . . | | ... | | ... | | |
41 | // | 0 0 0 0 0 0 0 0 ... 1 4 1 | | P1_(n-1)| | 4 * P(n-2) + 2 * P(n-1) | |
|
68 | // | 0 0 0 0 0 0 0 0 ... 1 4 1 | | P1_(n-1)| | 4 * P(n-2) + 2 * P(n-1) | | |
42 | // | 0 0 0 0 0 0 0 0 ... 0 2 7 | | P1_n | | 8 * P(n-1) + Pn | |
|
69 | // | 0 0 0 0 0 0 0 0 ... 0 2 7 | | P1_n | | 8 * P(n-1) + Pn | | |
43 | // |
|
70 | // | |
44 | QList<qreal> rhs; |
|
71 | QList<qreal> rhs; | |
45 | rhs.append(m_x[0] + 2 * m_x[1]); |
|
72 | rhs.append(m_x[0] + 2 * m_x[1]); | |
46 |
|
73 | |||
47 | // Set right hand side X values |
|
74 | // Set right hand side X values | |
48 | for (int i = 1; i < n - 1; ++i) |
|
75 | for (int i = 1; i < n - 1; ++i) | |
49 | rhs.append(4 * m_x[i] + 2 * m_x[i + 1]); |
|
76 | rhs.append(4 * m_x[i] + 2 * m_x[i + 1]); | |
50 |
|
77 | |||
51 | rhs.append((8 * m_x[n - 1] + m_x[n]) / 2.0); |
|
78 | rhs.append((8 * m_x[n - 1] + m_x[n]) / 2.0); | |
52 | // Get first control points X-values |
|
79 | // Get first control points X-values | |
53 | QList<qreal> x = getFirstControlPoints(rhs); |
|
80 | QList<qreal> x = getFirstControlPoints(rhs); | |
54 | rhs[0] = m_y[0] + 2 * m_y[1]; |
|
81 | rhs[0] = m_y[0] + 2 * m_y[1]; | |
55 |
|
82 | |||
56 | // Set right hand side Y values |
|
83 | // Set right hand side Y values | |
57 | for (int i = 1; i < n - 1; ++i) |
|
84 | for (int i = 1; i < n - 1; ++i) | |
58 | rhs[i] = 4 * m_y[i] + 2 * m_y[i + 1]; |
|
85 | rhs[i] = 4 * m_y[i] + 2 * m_y[i + 1]; | |
59 |
|
86 | |||
60 | rhs[n - 1] = (8 * m_y[n - 1] + m_y[n]) / 2.0; |
|
87 | rhs[n - 1] = (8 * m_y[n - 1] + m_y[n]) / 2.0; | |
61 | // Get first control points Y-values |
|
88 | // Get first control points Y-values | |
62 | QList<qreal> y = getFirstControlPoints(rhs); |
|
89 | QList<qreal> y = getFirstControlPoints(rhs); | |
63 |
|
90 | |||
64 | // Fill output arrays. |
|
91 | // Fill output arrays. | |
65 | for (int i = 0; i < n; ++i) |
|
92 | for (int i = 0; i < n; ++i) | |
66 | { |
|
93 | { | |
67 | // First control point |
|
94 | // First control point | |
68 | m_controlPoints.append(QPointF(x[i], y[i])); |
|
95 | m_controlPoints.append(QPointF(x[i], y[i])); | |
69 | // Second control point |
|
96 | // Second control point | |
70 | if (i < n - 1) |
|
97 | if (i < n - 1) | |
71 | m_controlPoints.append(QPointF(2 * m_x[i + 1] - x[i + 1], 2 * m_y[i + 1] - y[i + 1])); |
|
98 | m_controlPoints.append(QPointF(2 * m_x[i + 1] - x[i + 1], 2 * m_y[i + 1] - y[i + 1])); | |
72 | else |
|
99 | else | |
73 | m_controlPoints.append(QPointF((m_x[n] + x[n - 1]) / 2, (m_y[n] + y[n - 1]) / 2)); |
|
100 | m_controlPoints.append(QPointF((m_x[n] + x[n - 1]) / 2, (m_y[n] + y[n - 1]) / 2)); | |
74 | } |
|
101 | } | |
75 | } |
|
102 | } | |
76 |
|
103 | |||
|
104 | /*! | |||
|
105 | \internal | |||
|
106 | */ | |||
77 | QList<qreal> QSplineSeries::getFirstControlPoints(QList<qreal> rhs) |
|
107 | QList<qreal> QSplineSeries::getFirstControlPoints(QList<qreal> rhs) | |
78 | { |
|
108 | { | |
79 | QList<qreal> x; // Solution vector. |
|
109 | QList<qreal> x; // Solution vector. | |
80 | QList<qreal> tmp; // Temp workspace. |
|
110 | QList<qreal> tmp; // Temp workspace. | |
81 |
|
111 | |||
82 | qreal b = 2.0; |
|
112 | qreal b = 2.0; | |
83 | x.append(rhs[0] / b); |
|
113 | x.append(rhs[0] / b); | |
84 | tmp.append(0); |
|
114 | tmp.append(0); | |
85 | for (int i = 1; i < rhs.size(); i++) // Decomposition and forward substitution. |
|
115 | for (int i = 1; i < rhs.size(); i++) // Decomposition and forward substitution. | |
86 | { |
|
116 | { | |
87 | tmp.append(1 / b); |
|
117 | tmp.append(1 / b); | |
88 | b = (i < rhs.size() - 1 ? 4.0 : 3.5) - tmp[i]; |
|
118 | b = (i < rhs.size() - 1 ? 4.0 : 3.5) - tmp[i]; | |
89 | x.append((rhs[i] - x[i - 1]) / b); |
|
119 | x.append((rhs[i] - x[i - 1]) / b); | |
90 | } |
|
120 | } | |
91 | for (int i = 1; i < rhs.size(); i++) |
|
121 | for (int i = 1; i < rhs.size(); i++) | |
92 | x[rhs.size() - i - 1] -= tmp[rhs.size() - i] * x[rhs.size() - i]; // Backsubstitution. |
|
122 | x[rhs.size() - i - 1] -= tmp[rhs.size() - i] * x[rhs.size() - i]; // Backsubstitution. | |
93 |
|
123 | |||
94 | return x; |
|
124 | return x; | |
95 | } |
|
125 | } | |
96 |
|
126 | |||
|
127 | /*! | |||
|
128 | \internal | |||
|
129 | Updates the control points, besed on currently avaiable knots. | |||
|
130 | */ | |||
97 | void QSplineSeries::updateControlPoints() |
|
131 | void QSplineSeries::updateControlPoints() | |
98 | { |
|
132 | { | |
99 | if(m_x.size() > 1) |
|
133 | if(m_x.size() > 1) | |
100 | { |
|
134 | { | |
101 | m_controlPoints.clear(); |
|
135 | m_controlPoints.clear(); | |
102 | calculateControlPoints(); |
|
136 | calculateControlPoints(); | |
103 | } |
|
137 | } | |
104 | } |
|
138 | } | |
105 |
|
139 | |||
106 | #include "moc_qsplineseries.cpp" |
|
140 | #include "moc_qsplineseries.cpp" | |
107 |
|
141 | |||
108 | QTCOMMERCIALCHART_END_NAMESPACE |
|
142 | QTCOMMERCIALCHART_END_NAMESPACE |
@@ -1,37 +1,37 | |||||
1 | #ifndef QSPLINESERIES_H |
|
1 | #ifndef QSPLINESERIES_H | |
2 | #define QSPLINESERIES_H |
|
2 | #define QSPLINESERIES_H | |
3 |
|
3 | |||
4 | #include "qchartglobal.h" |
|
4 | #include "qchartglobal.h" | |
5 | #include <QtGlobal> |
|
5 | #include <QtGlobal> | |
6 | #include "qlineseries.h" |
|
6 | #include "qlineseries.h" | |
7 | #include <QList> |
|
7 | #include <QList> | |
8 | #include <QPointF> |
|
8 | #include <QPointF> | |
9 |
|
9 | |||
10 | QTCOMMERCIALCHART_BEGIN_NAMESPACE |
|
10 | QTCOMMERCIALCHART_BEGIN_NAMESPACE | |
11 |
|
11 | |||
12 | class QSplineSeries : public QLineSeries |
|
12 | class QSplineSeries : public QLineSeries | |
13 | { |
|
13 | { | |
14 | Q_OBJECT |
|
14 | Q_OBJECT | |
15 | public: |
|
15 | public: | |
16 |
|
16 | |||
17 | QSplineSeries(QObject *parent = 0); |
|
17 | QSplineSeries(QObject *parent = 0); | |
18 | QSeriesType type() const { return QSeries::SeriesTypeSpline; } |
|
18 | QSeriesType type() const { return QSeries::SeriesTypeSpline; } | |
19 |
|
19 | |||
20 | int count() const { return m_x.size(); } |
|
20 | // int count() const { return m_x.size(); } | |
21 | QPointF controlPoint(int index) const { return m_controlPoints[index]; } |
|
21 | QPointF controlPoint(int index) const { return m_controlPoints[index]; } | |
22 |
|
22 | |||
23 | private: |
|
23 | private: | |
24 | void calculateControlPoints(); |
|
24 | void calculateControlPoints(); | |
25 | QList<qreal> getFirstControlPoints(QList<qreal> rhs); |
|
25 | QList<qreal> getFirstControlPoints(QList<qreal> rhs); | |
26 |
|
26 | |||
27 | private slots: |
|
27 | private slots: | |
28 | void updateControlPoints(); |
|
28 | void updateControlPoints(); | |
29 |
|
29 | |||
30 | private: |
|
30 | private: | |
31 | QList<QPointF> m_controlPoints; |
|
31 | QList<QPointF> m_controlPoints; | |
32 |
|
32 | |||
33 | }; |
|
33 | }; | |
34 |
|
34 | |||
35 | QTCOMMERCIALCHART_END_NAMESPACE |
|
35 | QTCOMMERCIALCHART_END_NAMESPACE | |
36 |
|
36 | |||
37 | #endif // QSPLINESERIES_H |
|
37 | #endif // QSPLINESERIES_H |
General Comments 0
You need to be logged in to leave comments.
Login now