##// END OF EJS Templates
QSplineSeries calculateControlPoints moved to splinechartitem. This way we don't need to deal with controlPoints on logaritmic scale
Marek Rosa -
r2372:d6a999e30ac3
parent child
Show More
@@ -49,8 +49,7 QVector<qreal> ChartLogValueAxisX::calculateLayout() const
49 49 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
50 50 qreal leftEdge = logMin < logMax ? logMin : logMax;
51 51 qreal ceilEdge = ceil(leftEdge);
52 int tickCount = qAbs(qRound(logMax - logMin));
53 tickCount++;
52 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
54 53
55 54 points.resize(tickCount);
56 55 const QRectF &gridRect = gridGeometry();
@@ -48,8 +48,7 QVector<qreal> ChartLogValueAxisY::calculateLayout() const
48 48 qreal logMin = log10(m_axis->min()) / log10(m_axis->base());
49 49 qreal leftEdge = logMin < logMax ? logMin : logMax;
50 50 qreal ceilEdge = ceil(leftEdge);
51 int tickCount = qAbs(qRound(logMax - logMin));
52 tickCount++;
51 int tickCount = qAbs(ceil(logMax) - ceil(logMin));
53 52
54 53 points.resize(tickCount);
55 54 const QRectF &gridRect = gridGeometry();
@@ -100,8 +99,6 QSizeF ChartLogValueAxisY::sizeHint(Qt::SizeHint which, const QSizeF &constraint
100 99 ticksList = createLogValueLabels(m_axis->min(), m_axis->max(), m_axis->base(), tickCount, m_axis->labelFormat());
101 100 else
102 101 ticksList.append(QString(" "));
103 qDebug() << ticksList;
104 qDebug() << tickCount;
105 102 qreal width = 0;
106 103 qreal height = 0;
107 104
@@ -89,11 +89,6 QTCOMMERCIALCHART_BEGIN_NAMESPACE
89 89 QSplineSeries::QSplineSeries(QObject *parent)
90 90 : QLineSeries(*new QSplineSeriesPrivate(this), parent)
91 91 {
92 Q_D(QSplineSeries);
93 QObject::connect(this, SIGNAL(pointAdded(int)), d, SLOT(updateControlPoints()));
94 QObject::connect(this, SIGNAL(pointRemoved(int)), d, SLOT(updateControlPoints()));
95 QObject::connect(this, SIGNAL(pointReplaced(int)), d, SLOT(updateControlPoints()));
96 QObject::connect(this, SIGNAL(pointsReplaced()), d, SLOT(updateControlPoints()));
97 92 }
98 93
99 94 /*!
@@ -118,120 +113,6 QSplineSeriesPrivate::QSplineSeriesPrivate(QSplineSeries *q)
118 113 {
119 114 }
120 115
121 /*!
122 Calculates control points which are needed by QPainterPath.cubicTo function to draw the cubic Bezier cureve between two points.
123 */
124 void QSplineSeriesPrivate::calculateControlPoints()
125 {
126 Q_Q(QSplineSeries);
127
128 const QList<QPointF>& points = q->points();
129
130 int n = points.count() - 1;
131
132 if (n == 1) {
133 //for n==1
134 m_controlPoints[0].setX((2 * points[0].x() + points[1].x()) / 3);
135 m_controlPoints[0].setY((2 * points[0].y() + points[1].y()) / 3);
136 m_controlPoints[1].setX(2 * m_controlPoints[0].x() - points[0].x());
137 m_controlPoints[1].setY(2 * m_controlPoints[0].y() - points[0].y());
138 return;
139 }
140
141 // Calculate first Bezier control points
142 // Set of equations for P0 to Pn points.
143 //
144 // | 2 1 0 0 ... 0 0 0 ... 0 0 0 | | P1_1 | | P0 + 2 * P1 |
145 // | 1 4 1 0 ... 0 0 0 ... 0 0 0 | | P1_2 | | 4 * P1 + 2 * P2 |
146 // | 0 1 4 1 ... 0 0 0 ... 0 0 0 | | P1_3 | | 4 * P2 + 2 * P3 |
147 // | . . . . . . . . . . . . | | ... | | ... |
148 // | 0 0 0 0 ... 1 4 1 ... 0 0 0 | * | P1_i | = | 4 * P(i-1) + 2 * Pi |
149 // | . . . . . . . . . . . . | | ... | | ... |
150 // | 0 0 0 0 0 0 0 0 ... 1 4 1 | | P1_(n-1)| | 4 * P(n-2) + 2 * P(n-1) |
151 // | 0 0 0 0 0 0 0 0 ... 0 2 7 | | P1_n | | 8 * P(n-1) + Pn |
152 //
153 QVector<qreal> vector;
154 vector.resize(n);
155
156 vector[0] = points[0].x() + 2 * points[1].x();
157
158
159 for (int i = 1; i < n - 1; ++i)
160 vector[i] = 4 * points[i].x() + 2 * points[i + 1].x();
161
162 vector[n - 1] = (8 * points[n - 1].x() + points[n].x()) / 2.0;
163
164 QVector<qreal> xControl = firstControlPoints(vector);
165
166 vector[0] = points[0].y() + 2 * points[1].y();
167
168 for (int i = 1; i < n - 1; ++i)
169 vector[i] = 4 * points[i].y() + 2 * points[i + 1].y();
170
171 vector[n - 1] = (8 * points[n - 1].y() + points[n].y()) / 2.0;
172
173 QVector<qreal> yControl = firstControlPoints(vector);
174
175 for (int i = 0, j = 0; i < n; ++i, ++j) {
176
177 m_controlPoints[j].setX(xControl[i]);
178 m_controlPoints[j].setY(yControl[i]);
179
180 j++;
181
182 if (i < n - 1) {
183 m_controlPoints[j].setX(2 * points[i + 1].x() - xControl[i + 1]);
184 m_controlPoints[j].setY(2 * points[i + 1].y() - yControl[i + 1]);
185 } else {
186 m_controlPoints[j].setX((points[n].x() + xControl[n - 1]) / 2);
187 m_controlPoints[j].setY((points[n].y() + yControl[n - 1]) / 2);
188 }
189 }
190 }
191
192 QVector<qreal> QSplineSeriesPrivate::firstControlPoints(const QVector<qreal>& vector)
193 {
194 QVector<qreal> result;
195
196 int count = vector.count();
197 result.resize(count);
198 result[0] = vector[0] / 2.0;
199
200 QVector<qreal> temp;
201 temp.resize(count);
202 temp[0] = 0;
203
204 qreal b = 2.0;
205
206 for (int i = 1; i < count; i++) {
207 temp[i] = 1 / b;
208 b = (i < count - 1 ? 4.0 : 3.5) - temp[i];
209 result[i] = (vector[i] - result[i - 1]) / b;
210 }
211
212 for (int i = 1; i < count; i++)
213 result[count - i - 1] -= temp[count - i] * result[count - i];
214
215 return result;
216 }
217
218 QPointF QSplineSeriesPrivate::controlPoint(int index) const
219 {
220 return m_controlPoints[index];
221 }
222
223 /*!
224 Updates the control points, besed on currently avaiable knots.
225 */
226 void QSplineSeriesPrivate::updateControlPoints()
227 {
228 Q_Q(QSplineSeries);
229 if (q->count() > 1) {
230 m_controlPoints.resize(2 * q->count() - 2);
231 calculateControlPoints();
232 }
233 }
234
235 116 void QSplineSeriesPrivate::initializeGraphics(QGraphicsItem* parent)
236 117 {
237 118 Q_Q(QSplineSeries);
@@ -253,7 +134,6 void QSplineSeriesPrivate::initializeTheme(int index, ChartTheme* theme, bool fo
253 134 }
254 135 }
255 136
256
257 137 void QSplineSeriesPrivate::initializeAnimations(QtCommercialChart::QChart::AnimationOptions options)
258 138 {
259 139 SplineChartItem *item = static_cast<SplineChartItem *>(m_item.data());
@@ -45,17 +45,6 public:
45 45 void initializeGraphics(QGraphicsItem* parent);
46 46 void initializeAnimations(QtCommercialChart::QChart::AnimationOptions options);
47 47
48 QPointF controlPoint(int index) const;
49
50 public Q_SLOTS:
51 void updateControlPoints();
52
53 private:
54 void calculateControlPoints();
55 QVector<qreal> firstControlPoints(const QVector<qreal>& vector);
56
57 public:
58 QVector<QPointF> m_controlPoints;
59 48 private:
60 49 Q_DECLARE_PUBLIC(QSplineSeries)
61 50 };
@@ -77,14 +77,8 QVector<QPointF> SplineChartItem::controlGeometryPoints() const
77 77 void SplineChartItem::updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index)
78 78 {
79 79 QVector<QPointF> controlPoints;
80
81 80 if (newPoints.count() >= 2)
82 controlPoints.resize(newPoints.count() * 2 - 2);
83
84 for (int i = 0; i < newPoints.size() - 1; i++) {
85 controlPoints[2 * i] = calculateGeometryControlPoint(2 * i);
86 controlPoints[2 * i + 1] = calculateGeometryControlPoint(2 * i + 1);
87 }
81 controlPoints = calculateControlPoints(newPoints);
88 82
89 83 if (m_animation)
90 84 m_animation->setup(oldPoints, newPoints, m_controlPoints, controlPoints, index);
@@ -99,12 +93,6 void SplineChartItem::updateChart(QVector<QPointF> &oldPoints, QVector<QPointF>
99 93 updateGeometry();
100 94 }
101 95
102 QPointF SplineChartItem::calculateGeometryControlPoint(int index) const
103 {
104 bool ok;
105 return domain()->calculateGeometryPoint(m_series->d_func()->controlPoint(index), ok);
106 }
107
108 96 void SplineChartItem::updateGeometry()
109 97 {
110 98 const QVector<QPointF> &points = m_points;
@@ -135,6 +123,103 void SplineChartItem::updateGeometry()
135 123
136 124 }
137 125
126 /*!
127 Calculates control points which are needed by QPainterPath.cubicTo function to draw the cubic Bezier cureve between two points.
128 */
129 QVector<QPointF> SplineChartItem::calculateControlPoints(const QVector<QPointF> &points)
130 {
131 QVector<QPointF> controlPoints;
132 controlPoints.resize(points.count() * 2 - 2);
133
134 int n = points.count() - 1;
135
136 if (n == 1) {
137 //for n==1
138 controlPoints[0].setX((2 * points[0].x() + points[1].x()) / 3);
139 controlPoints[0].setY((2 * points[0].y() + points[1].y()) / 3);
140 controlPoints[1].setX(2 * controlPoints[0].x() - points[0].x());
141 controlPoints[1].setY(2 * controlPoints[0].y() - points[0].y());
142 return controlPoints;
143 }
144
145 // Calculate first Bezier control points
146 // Set of equations for P0 to Pn points.
147 //
148 // | 2 1 0 0 ... 0 0 0 ... 0 0 0 | | P1_1 | | P0 + 2 * P1 |
149 // | 1 4 1 0 ... 0 0 0 ... 0 0 0 | | P1_2 | | 4 * P1 + 2 * P2 |
150 // | 0 1 4 1 ... 0 0 0 ... 0 0 0 | | P1_3 | | 4 * P2 + 2 * P3 |
151 // | . . . . . . . . . . . . | | ... | | ... |
152 // | 0 0 0 0 ... 1 4 1 ... 0 0 0 | * | P1_i | = | 4 * P(i-1) + 2 * Pi |
153 // | . . . . . . . . . . . . | | ... | | ... |
154 // | 0 0 0 0 0 0 0 0 ... 1 4 1 | | P1_(n-1)| | 4 * P(n-2) + 2 * P(n-1) |
155 // | 0 0 0 0 0 0 0 0 ... 0 2 7 | | P1_n | | 8 * P(n-1) + Pn |
156 //
157 QVector<qreal> vector;
158 vector.resize(n);
159
160 vector[0] = points[0].x() + 2 * points[1].x();
161
162
163 for (int i = 1; i < n - 1; ++i)
164 vector[i] = 4 * points[i].x() + 2 * points[i + 1].x();
165
166 vector[n - 1] = (8 * points[n - 1].x() + points[n].x()) / 2.0;
167
168 QVector<qreal> xControl = firstControlPoints(vector);
169
170 vector[0] = points[0].y() + 2 * points[1].y();
171
172 for (int i = 1; i < n - 1; ++i)
173 vector[i] = 4 * points[i].y() + 2 * points[i + 1].y();
174
175 vector[n - 1] = (8 * points[n - 1].y() + points[n].y()) / 2.0;
176
177 QVector<qreal> yControl = firstControlPoints(vector);
178
179 for (int i = 0, j = 0; i < n; ++i, ++j) {
180
181 controlPoints[j].setX(xControl[i]);
182 controlPoints[j].setY(yControl[i]);
183
184 j++;
185
186 if (i < n - 1) {
187 controlPoints[j].setX(2 * points[i + 1].x() - xControl[i + 1]);
188 controlPoints[j].setY(2 * points[i + 1].y() - yControl[i + 1]);
189 } else {
190 controlPoints[j].setX((points[n].x() + xControl[n - 1]) / 2);
191 controlPoints[j].setY((points[n].y() + yControl[n - 1]) / 2);
192 }
193 }
194 return controlPoints;
195 }
196
197 QVector<qreal> SplineChartItem::firstControlPoints(const QVector<qreal>& vector)
198 {
199 QVector<qreal> result;
200
201 int count = vector.count();
202 result.resize(count);
203 result[0] = vector[0] / 2.0;
204
205 QVector<qreal> temp;
206 temp.resize(count);
207 temp[0] = 0;
208
209 qreal b = 2.0;
210
211 for (int i = 1; i < count; i++) {
212 temp[i] = 1 / b;
213 b = (i < count - 1 ? 4.0 : 3.5) - temp[i];
214 result[i] = (vector[i] - result[i - 1]) / b;
215 }
216
217 for (int i = 1; i < count; i++)
218 result[count - i - 1] -= temp[count - i] * result[count - i];
219
220 return result;
221 }
222
138 223 //handlers
139 224
140 225 void SplineChartItem::handleUpdated()
@@ -60,15 +60,14 public Q_SLOTS:
60 60
61 61 protected:
62 62 void updateGeometry();
63 QVector<QPointF> calculateControlPoints(const QVector<QPointF> &points);
64 QVector<qreal> firstControlPoints(const QVector<qreal>& vector);
63 65 void updateChart(QVector<QPointF> &oldPoints, QVector<QPointF> &newPoints, int index);
64 66 void mousePressEvent(QGraphicsSceneMouseEvent *event);
65 67 void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
66 68 void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
67 69
68 70 private:
69 QPointF calculateGeometryControlPoint(int index) const;
70
71 private:
72 71 QSplineSeries *m_series;
73 72 QPainterPath m_path;
74 73 QRectF m_rect;
General Comments 0
You need to be logged in to leave comments. Login now