##// END OF EJS Templates
Fixed a bug with last two control points calculation
Marek Rosa -
r429:cbe57d7d97d6
parent child
Show More
@@ -1,67 +1,77
1 #include "splinewidget.h"
1 #include "splinewidget.h"
2 #include "qchartview.h"
2 #include "qchartview.h"
3 #include "qsplineseries.h"
3 #include "qsplineseries.h"
4 #include "qlineseries.h"
4 #include "qlineseries.h"
5 #include <QGridLayout>
5 #include <QGridLayout>
6
6
7 QTCOMMERCIALCHART_USE_NAMESPACE
7 QTCOMMERCIALCHART_USE_NAMESPACE
8
8
9 SplineWidget::SplineWidget(QWidget *parent)
9 SplineWidget::SplineWidget(QWidget *parent)
10 : QWidget(parent)
10 : QWidget(parent)
11 {
11 {
12 //create QSplineSeries
12 //create QSplineSeries
13 QSplineSeries* series = new QSplineSeries(this);
13 QSplineSeries* series = new QSplineSeries(this);
14 // series->add(QPointF(150, 100));
14 // series->add(QPointF(150, 100));
15 // series->add(QPointF(200, 130));
15 // series->add(QPointF(200, 130));
16 // series->add(QPointF(250, 120));
16 // series->add(QPointF(250, 120));
17 // series->add(QPointF(300, 140));
17 // series->add(QPointF(300, 140));
18 // series->add(QPointF(350, 100));
18 // series->add(QPointF(350, 100));
19 // series->add(QPointF(400, 120));
19 // series->add(QPointF(400, 120));
20 // series->add(QPointF(450, 150));
20 // series->add(QPointF(450, 150));
21 //// series->add(QPointF(600, 150));
21 //// series->add(QPointF(600, 150));
22 // series->add(QPointF(500, 145));
22 // series->add(QPointF(500, 145));
23 // series->add(QPointF(550, 170));
23 // series->add(QPointF(550, 170));
24 // series->add(QPointF(600, 190));
24 // series->add(QPointF(600, 190));
25 // series->add(QPointF(650, 210));
25 // series->add(QPointF(650, 210));
26 // series->add(QPointF(700, 190));
26 // series->add(QPointF(700, 190));
27 // series->add(QPointF(750, 180));
27 // series->add(QPointF(750, 180));
28 // series->add(QPointF(800, 170));
28 // series->add(QPointF(800, 170));
29
29
30 qsrand(time(NULL));
30 // qsrand(time(NULL));
31 for (int i = 0; i < 100; i++)
31 // for (int i = 0; i < 100; i++)
32 // {
33 // series->add(QPointF(i*7, qrand()%600));
34 // }
35 int k = 10;
36 for (int i = 0; i < 25; i++)
32 {
37 {
33 series->add(QPointF(i*7, qrand()%600));
38 if (k > 60)
39 {
40 k = 10;
41 }
42 series->add(QPointF(i*50, k));
43 k +=10;
34 }
44 }
35
45
36 series->calculateControlPoints();
46 series->calculateControlPoints();
37
47
38 // QLineSeries* lineSeries = new QLineSeries;
48 // QLineSeries* lineSeries = new QLineSeries;
39 // for (int i = 0; i < series->count() - 1; i++)
49 // for (int i = 0; i < series->count() - 1; i++)
40 // {
50 // {
41 // lineSeries->add(series->at(i).x(), series->at(i).y());
51 // lineSeries->add(series->at(i).x(), series->at(i).y());
42 // lineSeries->add(series->controlPoint(2*i).x(), series->controlPoint(2*i).y());
52 // lineSeries->add(series->controlPoint(2*i).x(), series->controlPoint(2*i).y());
43 // lineSeries->add(series->controlPoint(2*i + 1).x(), series->controlPoint(2*i + 1).y());
53 // lineSeries->add(series->controlPoint(2*i + 1).x(), series->controlPoint(2*i + 1).y());
44 // }
54 // }
45
55
46 // QLineChartSeries* lineSeries2 = new QLineChartSeries;
56 // QLineChartSeries* lineSeries2 = new QLineChartSeries;
47 // lineSeries2->add(10, 50);
57 // lineSeries2->add(10, 50);
48 // lineSeries2->add(30, 15);
58 // lineSeries2->add(30, 15);
49 // lineSeries2->add(60, 40);
59 // lineSeries2->add(60, 40);
50 // lineSeries2->add(90, 70);
60 // lineSeries2->add(90, 70);
51 // lineSeries2->add(100, 20);
61 // lineSeries2->add(100, 20);
52
62
53 //create chart view
63 //create chart view
54 QChartView* chart = new QChartView;
64 QChartView* chart = new QChartView;
55 chart->setMinimumSize(800,600);
65 chart->setMinimumSize(800,600);
56 // chart->setGeometry(50, 50, 400, 300);
66 // chart->setGeometry(50, 50, 400, 300);
57 chart->addSeries(series);
67 chart->addSeries(series);
58
68
59 QGridLayout* mainLayout = new QGridLayout;
69 QGridLayout* mainLayout = new QGridLayout;
60 mainLayout->addWidget(chart);
70 mainLayout->addWidget(chart);
61 setLayout(mainLayout);
71 setLayout(mainLayout);
62 }
72 }
63
73
64 SplineWidget::~SplineWidget()
74 SplineWidget::~SplineWidget()
65 {
75 {
66
76
67 }
77 }
@@ -1,110 +1,110
1 #include "qsplineseries.h"
1 #include "qsplineseries.h"
2
2
3 QTCOMMERCIALCHART_BEGIN_NAMESPACE
3 QTCOMMERCIALCHART_BEGIN_NAMESPACE
4
4
5 QSplineSeries::QSplineSeries(QObject *parent) :
5 QSplineSeries::QSplineSeries(QObject *parent) :
6 QLineSeries(parent)
6 QLineSeries(parent)
7 {
7 {
8 }
8 }
9
9
10 //QSplineSeries& QSplineSeries::operator << (const QPointF &value)
10 //QSplineSeries& QSplineSeries::operator << (const QPointF &value)
11 //{
11 //{
12 //// d->m_data.append(value);
12 //// d->m_data.append(value);
13 // m_data.append(value);
13 // m_data.append(value);
14 //// emit changed();
14 //// emit changed();
15 // return *this;
15 // return *this;
16 //}
16 //}
17
17
18 //void QSplineSeries::addData(QPointF value)
18 //void QSplineSeries::addData(QPointF value)
19 //{
19 //{
20 // m_data.append(value);
20 // m_data.append(value);
21 //}
21 //}
22
22
23 void QSplineSeries::calculateControlPoints()
23 void QSplineSeries::calculateControlPoints()
24 {
24 {
25
25
26 // Based on http://www.codeproject.com/Articles/31859/Draw-a-Smooth-Curve-through-a-Set-of-2D-Points-wit
26 // Based on http://www.codeproject.com/Articles/31859/Draw-a-Smooth-Curve-through-a-Set-of-2D-Points-wit
27 // CPOL Licence
27 // CPOL Licence
28
28
29 int n = m_x.size() - 1;
29 int n = m_x.size() - 1;
30 if (n == 1)
30 if (n == 1)
31 { // Special case: Bezier curve should be a straight line.
31 { // Special case: Bezier curve should be a straight line.
32 // firstControlPoints = new Point[1];
32 // firstControlPoints = new Point[1];
33 // 3P1 = 2P0 + P3
33 // 3P1 = 2P0 + P3
34 m_controlPoints.append(QPointF((2 * m_x[0] + m_x[1]) / 3, (2 * m_y[0] + m_y[1]) / 3));
34 m_controlPoints.append(QPointF((2 * m_x[0] + m_x[1]) / 3, (2 * m_y[0] + m_y[1]) / 3));
35
35
36 // P2 = 2P1 P0
36 // P2 = 2P1 P0
37 m_controlPoints.append(QPointF(2 * m_controlPoints[0].x() - m_x[0], 2 * m_controlPoints[0].y() - m_y[0]));
37 m_controlPoints.append(QPointF(2 * m_controlPoints[0].x() - m_x[0], 2 * m_controlPoints[0].y() - m_y[0]));
38 return;
38 return;
39 }
39 }
40
40
41 // Calculate first Bezier control points
41 // Calculate first Bezier control points
42 // Right hand side vector
42 // Right hand side vector
43 // Set of equations for P0 to Pn points.
43 // Set of equations for P0 to Pn points.
44 //
44 //
45 // | 2 1 0 0 ... 0 0 0 ... 0 0 0 | | P1_1 | | P0 + 2 * P1 |
45 // | 2 1 0 0 ... 0 0 0 ... 0 0 0 | | P1_1 | | P0 + 2 * P1 |
46 // | 1 4 1 0 ... 0 0 0 ... 0 0 0 | | P1_2 | | 4 * P1 + 2 * P2 |
46 // | 1 4 1 0 ... 0 0 0 ... 0 0 0 | | P1_2 | | 4 * P1 + 2 * P2 |
47 // | 0 1 4 1 ... 0 0 0 ... 0 0 0 | | P1_3 | | 4 * P2 + 2 * P3 |
47 // | 0 1 4 1 ... 0 0 0 ... 0 0 0 | | P1_3 | | 4 * P2 + 2 * P3 |
48 // | . . . . . . . . . . . . | | ... | | ... |
48 // | . . . . . . . . . . . . | | ... | | ... |
49 // | 0 0 0 0 ... 1 4 1 ... 0 0 0 | * | P1_i | = | 4 * P(i-1) + 2 * Pi |
49 // | 0 0 0 0 ... 1 4 1 ... 0 0 0 | * | P1_i | = | 4 * P(i-1) + 2 * Pi |
50 // | . . . . . . . . . . . . | | ... | | ... |
50 // | . . . . . . . . . . . . | | ... | | ... |
51 // | 0 0 0 0 0 0 0 0 ... 1 4 1 | | P1_(n-1)| | 4 * P(n-2) + 2 * P(n-1) |
51 // | 0 0 0 0 0 0 0 0 ... 1 4 1 | | P1_(n-1)| | 4 * P(n-2) + 2 * P(n-1) |
52 // | 0 0 0 0 0 0 0 0 ... 0 2 7 | | P1_n | | 8 * P(n-1) + Pn |
52 // | 0 0 0 0 0 0 0 0 ... 0 2 7 | | P1_n | | 8 * P(n-1) + Pn |
53 //
53 //
54 QList<qreal> rhs;
54 QList<qreal> rhs;
55 rhs.append(m_x[0] + 2 * m_x[1]);
55 rhs.append(m_x[0] + 2 * m_x[1]);
56
56
57 // Set right hand side X values
57 // Set right hand side X values
58 for (int i = 1; i < m_x.size() - 1; ++i)
58 for (int i = 1; i < n - 1; ++i)
59 rhs.append(4 * m_x[i] + 2 * m_x[i + 1]);
59 rhs.append(4 * m_x[i] + 2 * m_x[i + 1]);
60
60
61 rhs.append((8 * m_x[n - 1] + m_x[n]) / 2.0);
61 rhs.append((8 * m_x[n - 1] + m_x[n]) / 2.0);
62 // Get first control points X-values
62 // Get first control points X-values
63 QList<qreal> x = getFirstControlPoints(rhs);
63 QList<qreal> x = getFirstControlPoints(rhs);
64 rhs[0] = m_y[0] + 2 * m_y[1];
64 rhs[0] = m_y[0] + 2 * m_y[1];
65
65
66 // Set right hand side Y values
66 // Set right hand side Y values
67 for (int i = 1; i < m_y.size() - 1; ++i)
67 for (int i = 1; i < n - 1; ++i)
68 rhs[i] = 4 * m_y[i] + 2 * m_y[i + 1];
68 rhs[i] = 4 * m_y[i] + 2 * m_y[i + 1];
69
69
70 rhs[n - 1] = (8 * m_y[n - 1] + m_y[n]) / 2.0;
70 rhs[n - 1] = (8 * m_y[n - 1] + m_y[n]) / 2.0;
71 // Get first control points Y-values
71 // Get first control points Y-values
72 QList<qreal> y = getFirstControlPoints(rhs);
72 QList<qreal> y = getFirstControlPoints(rhs);
73
73
74 // Fill output arrays.
74 // Fill output arrays.
75 // firstControlPoints = new Point[n];
75 // firstControlPoints = new Point[n];
76 // secondControlPoints = new Point[n];
76 // secondControlPoints = new Point[n];
77 for (int i = 0; i < m_x.size(); ++i)
77 for (int i = 0; i < n; ++i)
78 {
78 {
79 // First control point
79 // First control point
80 m_controlPoints.append(QPointF(x[i], y[i]));
80 m_controlPoints.append(QPointF(x[i], y[i]));
81 // Second control point
81 // Second control point
82 if (i < n - 1)
82 if (i < n - 1)
83 m_controlPoints.append(QPointF(2 * m_x[i + 1] - x[i + 1], 2 * m_y[i + 1] - y[i + 1]));
83 m_controlPoints.append(QPointF(2 * m_x[i + 1] - x[i + 1], 2 * m_y[i + 1] - y[i + 1]));
84 else
84 else
85 m_controlPoints.append(QPointF((m_x[n] + x[n - 1]) / 2, (m_y[n] + y[n - 1]) / 2));
85 m_controlPoints.append(QPointF((m_x[n] + x[n - 1]) / 2, (m_y[n] + y[n - 1]) / 2));
86 }
86 }
87 }
87 }
88
88
89 QList<qreal> QSplineSeries::getFirstControlPoints(QList<qreal> rhs)
89 QList<qreal> QSplineSeries::getFirstControlPoints(QList<qreal> rhs)
90 {
90 {
91 QList<qreal> x; // Solution vector.
91 QList<qreal> x; // Solution vector.
92 QList<qreal> tmp; // Temp workspace.
92 QList<qreal> tmp; // Temp workspace.
93
93
94 qreal b = 2.0;
94 qreal b = 2.0;
95 x.append(rhs[0] / b);
95 x.append(rhs[0] / b);
96 tmp.append(0);
96 tmp.append(0);
97 for (int i = 1; i < rhs.size(); i++) // Decomposition and forward substitution.
97 for (int i = 1; i < rhs.size(); i++) // Decomposition and forward substitution.
98 {
98 {
99 tmp.append(1 / b);
99 tmp.append(1 / b);
100 b = (i < rhs.size() - 1 ? 4.0 : 3.5) - tmp[i];
100 b = (i < rhs.size() - 1 ? 4.0 : 3.5) - tmp[i];
101 x.append((rhs[i] - x[i - 1]) / b);
101 x.append((rhs[i] - x[i - 1]) / b);
102 }
102 }
103 for (int i = 1; i < rhs.size(); i++)
103 for (int i = 1; i < rhs.size(); i++)
104 x[rhs.size() - i - 1] -= tmp[rhs.size() - i] * x[rhs.size() - i]; // Backsubstitution.
104 x[rhs.size() - i - 1] -= tmp[rhs.size() - i] * x[rhs.size() - i]; // Backsubstitution.
105
105
106 return x;
106 return x;
107 }
107 }
108 #include "moc_qsplineseries.cpp"
108 #include "moc_qsplineseries.cpp"
109
109
110 QTCOMMERCIALCHART_END_NAMESPACE
110 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now