##// END OF EJS Templates
Further changes
Marek Rosa -
r318:b5c990a4117f
parent child
Show More
@@ -1,13 +1,100
1 1 #include "qsplineseries.h"
2 2
3 3 QSplineSeries::QSplineSeries(QObject *parent) :
4 4 QObject(parent)
5 5 {
6 6 }
7 7
8 8 QSplineSeries& QSplineSeries::operator << (const QPointF &value)
9 9 {
10 10 d->m_data.append(value);
11 11 emit changed();
12 12 return *this;
13 13 }
14
15 void QSplineSeries::GetCurveControlPoints()
16 {
17 int n = m_data.size() - 1;
18 if (n < 1)
19 throw new ArgumentException
20 ("At least two knot points required", "knots");
21 if (n == 1)
22 { // Special case: Bezier curve should be a straight line.
23 firstControlPoints = new Point[1];
24 // 3P1 = 2P0 + P3
25 firstControlPoints[0].X = (2 * knots[0].X + knots[1].X) / 3;
26 firstControlPoints[0].Y = (2 * knots[0].Y + knots[1].Y) / 3;
27
28 secondControlPoints = new Point[1];
29 // P2 = 2P1 P0
30 secondControlPoints[0].X = 2 *
31 firstControlPoints[0].X - knots[0].X;
32 secondControlPoints[0].Y = 2 *
33 firstControlPoints[0].Y - knots[0].Y;
34 return;
35 }
36
37 // Calculate first Bezier control points
38 // Right hand side vector
39 double[] rhs = new double[n];
40
41 // Set right hand side X values
42 for (int i = 1; i < n - 1; ++i)
43 rhs[i] = 4 * knots[i].X + 2 * knots[i + 1].X;
44 rhs[0] = knots[0].X + 2 * knots[1].X;
45 rhs[n - 1] = (8 * knots[n - 1].X + knots[n].X) / 2.0;
46 // Get first control points X-values
47 double[] x = GetFirstControlPoints(rhs);
48
49 // Set right hand side Y values
50 for (int i = 1; i < n - 1; ++i)
51 rhs[i] = 4 * knots[i].Y + 2 * knots[i + 1].Y;
52 rhs[0] = knots[0].Y + 2 * knots[1].Y;
53 rhs[n - 1] = (8 * knots[n - 1].Y + knots[n].Y) / 2.0;
54 // Get first control points Y-values
55 double[] y = GetFirstControlPoints(rhs);
56
57 // Fill output arrays.
58 firstControlPoints = new Point[n];
59 secondControlPoints = new Point[n];
60 for (int i = 0; i < n; ++i)
61 {
62 // First control point
63 firstControlPoints[i] = new Point(x[i], y[i]);
64 // Second control point
65 if (i < n - 1)
66 secondControlPoints[i] = new Point(2 * knots
67 [i + 1].X - x[i + 1], 2 *
68 knots[i + 1].Y - y[i + 1]);
69 else
70 secondControlPoints[i] = new Point((knots
71 [n].X + x[n - 1]) / 2,
72 (knots[n].Y + y[n - 1]) / 2);
73 }
74 }
75
76 /// <summary>
77 /// Solves a tridiagonal system for one of coordinates (x or y)
78 /// of first Bezier control points.
79 /// </summary>
80 /// <param name="rhs">Right hand side vector.</param>
81 /// <returns>Solution vector.</returns>
82 void GetFirstControlPoints(qreal[] rhs)
83 {
84 int n = rhs.Length;
85 double[] x = new double[n]; // Solution vector.
86 double[] tmp = new double[n]; // Temp workspace.
87
88 double b = 2.0;
89 x[0] = rhs[0] / b;
90 for (int i = 1; i < n; i++) // Decomposition and forward substitution.
91 {
92 tmp[i] = 1 / b;
93 b = (i < n - 1 ? 4.0 : 3.5) - tmp[i];
94 x[i] = (rhs[i] - x[i - 1]) / b;
95 }
96 for (int i = 1; i < n; i++)
97 x[n - i - 1] -= tmp[n - i] * x[n - i]; // Backsubstitution.
98
99 return x;
100 }
@@ -1,29 +1,31
1 1 #ifndef QSPLINESERIES_H
2 2 #define QSPLINESERIES_H
3 3
4 4 #include "qchartseries.h"
5 5
6 6 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7 7
8 8 class QSplineSeries : public QChartSeries
9 9 {
10 10 Q_OBJECT
11 11 public:
12 12
13 13 QSplineSeries(QObject *parent = 0);
14 14 QChartSeriesType type() const { return QChartSeries::SeriesTypeSpline; }
15 15 void addData(QPointF value);
16 16 QSplineSeries& operator << (const QPointF &value);
17 void calculateControlPoints();
17 18
18 19 signals:
19 20
20 21 public slots:
21 22
22 23 private:
23 24 QList<QPointF> m_data;
25 QList<QPointF> m_controlPoints;
24 26
25 27 };
26 28
27 29 QTCOMMERCIALCHART_END_NAMESPACE
28 30
29 31 #endif // QSPLINESERIES_H
General Comments 0
You need to be logged in to leave comments. Login now