##// END OF EJS Templates
Spline working somewhat
Marek Rosa -
r401:e71d8c300b9c
parent child
Show More
@@ -0,0 +1,11
1 #include <QtGui/QApplication>
2 #include "splinewidget.h"
3
4 int main(int argc, char *argv[])
5 {
6 QApplication a(argc, argv);
7 SplineWidget w;
8 w.show();
9
10 return a.exec();
11 }
@@ -0,0 +1,20
1 #-------------------------------------------------
2 #
3 # Project created by QtCreator 2012-02-29T12:37:46
4 #
5 #-------------------------------------------------
6
7 !include( ../example.pri ) {
8 error( "Couldn't find the example.pri file!" )
9 }
10
11 QT += core gui
12
13 TARGET = splinechart
14 TEMPLATE = app
15
16
17 SOURCES += main.cpp\
18 splinewidget.cpp
19
20 HEADERS += splinewidget.h
@@ -0,0 +1,53
1 #include "splinewidget.h"
2 #include "qchartview.h"
3 #include "qsplineseries.h"
4 #include "qlinechartseries.h"
5 #include <QGridLayout>
6
7 QTCOMMERCIALCHART_USE_NAMESPACE
8
9 SplineWidget::SplineWidget(QWidget *parent)
10 : QWidget(parent)
11 {
12 //create QSplineSeries
13 QSplineSeries* series = new QSplineSeries(this);
14 series->addData(QPointF(150, 100));
15 series->addData(QPointF(200, 180));
16 series->addData(QPointF(240, 130));
17 series->addData(QPointF(270, 120));
18 series->addData(QPointF(310, 120));
19 series->addData(QPointF(420, 160));
20 series->addData(QPointF(535, 250));
21
22 series->calculateControlPoints();
23
24 QLineChartSeries* lineSeries = new QLineChartSeries;
25 for (int i = 0; i < series->count() - 1; i++)
26 {
27 lineSeries->add(series->at(i).x(), series->at(i).y());
28 lineSeries->add(series->controlPoint(2*i).x(), series->controlPoint(2*i).y());
29 lineSeries->add(series->controlPoint(2*i + 1).x(), series->controlPoint(2*i + 1).y());
30 }
31
32 // QLineChartSeries* lineSeries2 = new QLineChartSeries;
33 // lineSeries2->add(10, 50);
34 // lineSeries2->add(30, 15);
35 // lineSeries2->add(60, 40);
36 // lineSeries2->add(90, 70);
37 // lineSeries2->add(100, 20);
38
39 //create chart view
40 QChartView* chart = new QChartView;
41 chart->setMinimumSize(800,600);
42 // chart->setGeometry(50, 50, 400, 300);
43 chart->addSeries(series);
44
45 QGridLayout* mainLayout = new QGridLayout;
46 mainLayout->addWidget(chart);
47 setLayout(mainLayout);
48 }
49
50 SplineWidget::~SplineWidget()
51 {
52
53 }
@@ -0,0 +1,15
1 #ifndef SPLINEWIDGET_H
2 #define SPLINEWIDGET_H
3
4 #include <QtGui/QWidget>
5
6 class SplineWidget : public QWidget
7 {
8 Q_OBJECT
9
10 public:
11 SplineWidget(QWidget *parent = 0);
12 ~SplineWidget();
13 };
14
15 #endif // SPLINEWIDGET_H
@@ -11,4 +11,5 SUBDIRS += linechart \
11 11 axischart \
12 12 multichart \
13 13 gdpbarchart \
14 presenterchart
14 presenterchart \
15 splinechart
@@ -7,14 +7,15
7 7 #include "qpercentbarchartseries.h"
8 8 #include "qpieseries.h"
9 9 #include "qscatterseries.h"
10 #include "qsplineseries.h"
10 11
11 12 QTCOMMERCIALCHART_BEGIN_NAMESPACE
12 13
13 14 ChartDataSet::ChartDataSet(QObject *parent):QObject(parent),
14 m_axisX(new QChartAxis(this)),
15 m_axisY(new QChartAxis(this)),
16 m_domainIndex(0),
17 m_axisXInitialized(false)
15 m_axisX(new QChartAxis(this)),
16 m_axisY(new QChartAxis(this)),
17 m_domainIndex(0),
18 m_axisXInitialized(false)
18 19 {
19 20 }
20 21
@@ -25,11 +26,11 ChartDataSet::~ChartDataSet()
25 26
26 27 const Domain ChartDataSet::domain(QChartAxis *axisY) const
27 28 {
28 int i = m_domainMap.count(axisY);
29 if(i == 0){
30 return Domain();
31 }
32 i = i - m_domainIndex -1;
29 int i = m_domainMap.count(axisY);
30 if(i == 0){
31 return Domain();
32 }
33 i = i - m_domainIndex -1;
33 34 return m_domainMap.values(axisY).at(i);
34 35 }
35 36
@@ -55,79 +56,94 void ChartDataSet::addSeries(QChartSeries* series, QChartAxis *axisY)
55 56
56 57 switch(series->type())
57 58 {
58 case QChartSeries::SeriesTypeLine: {
59
60 QLineChartSeries* xyseries = static_cast<QLineChartSeries*>(series);
61
62 for (int i = 0; i < xyseries->count(); i++)
63 {
64 qreal x = xyseries->x(i);
65 qreal y = xyseries->y(i);
66 domain.m_minX = qMin(domain.m_minX,x);
67 domain.m_minY = qMin(domain.m_minY,y);
68 domain.m_maxX = qMax(domain.m_maxX,x);
69 domain.m_maxY = qMax(domain.m_maxY,y);
70 }
71 break;
72 }
73 case QChartSeries::SeriesTypeBar: {
74 qDebug() << "QChartSeries::SeriesTypeBar";
75 QBarChartSeries* barSeries = static_cast<QBarChartSeries*>(series);
76 qreal x = barSeries->countCategories();
77 qreal y = barSeries->max();
59 case QChartSeries::SeriesTypeLine: {
60
61 QLineChartSeries* xyseries = static_cast<QLineChartSeries*>(series);
62
63 for (int i = 0; i < xyseries->count(); i++)
64 {
65 qreal x = xyseries->x(i);
66 qreal y = xyseries->y(i);
78 67 domain.m_minX = qMin(domain.m_minX,x);
79 68 domain.m_minY = qMin(domain.m_minY,y);
80 69 domain.m_maxX = qMax(domain.m_maxX,x);
81 70 domain.m_maxY = qMax(domain.m_maxY,y);
82 break;
83 71 }
84 case QChartSeries::SeriesTypeStackedBar: {
72 break;
73 }
74 case QChartSeries::SeriesTypeBar: {
75 qDebug() << "QChartSeries::SeriesTypeBar";
76 QBarChartSeries* barSeries = static_cast<QBarChartSeries*>(series);
77 qreal x = barSeries->countCategories();
78 qreal y = barSeries->max();
79 domain.m_minX = qMin(domain.m_minX,x);
80 domain.m_minY = qMin(domain.m_minY,y);
81 domain.m_maxX = qMax(domain.m_maxX,x);
82 domain.m_maxY = qMax(domain.m_maxY,y);
83 break;
84 }
85 case QChartSeries::SeriesTypeStackedBar: {
85 86 qDebug() << "QChartSeries::SeriesTypeStackedBar";
86 87
87 QStackedBarChartSeries* stackedBarSeries = static_cast<QStackedBarChartSeries*>(series);
88 qreal x = stackedBarSeries->countCategories();
89 qreal y = stackedBarSeries->maxCategorySum();
90 domain.m_minX = qMin(domain.m_minX,x);
91 domain.m_minY = qMin(domain.m_minY,y);
92 domain.m_maxX = qMax(domain.m_maxX,x);
93 domain.m_maxY = qMax(domain.m_maxY,y);
94 break;
95 }
96 case QChartSeries::SeriesTypePercentBar: {
88 QStackedBarChartSeries* stackedBarSeries = static_cast<QStackedBarChartSeries*>(series);
89 qreal x = stackedBarSeries->countCategories();
90 qreal y = stackedBarSeries->maxCategorySum();
91 domain.m_minX = qMin(domain.m_minX,x);
92 domain.m_minY = qMin(domain.m_minY,y);
93 domain.m_maxX = qMax(domain.m_maxX,x);
94 domain.m_maxY = qMax(domain.m_maxY,y);
95 break;
96 }
97 case QChartSeries::SeriesTypePercentBar: {
97 98 qDebug() << "QChartSeries::SeriesTypePercentBar";
98 99
99 QPercentBarChartSeries* percentBarSeries = static_cast<QPercentBarChartSeries*>(series);
100 qreal x = percentBarSeries->countCategories();
101 domain.m_minX = qMin(domain.m_minX,x);
102 domain.m_minY = 0;
103 domain.m_maxX = qMax(domain.m_maxX,x);
104 domain.m_maxY = 100;
105 break;
106 }
100 QPercentBarChartSeries* percentBarSeries = static_cast<QPercentBarChartSeries*>(series);
101 qreal x = percentBarSeries->countCategories();
102 domain.m_minX = qMin(domain.m_minX,x);
103 domain.m_minY = 0;
104 domain.m_maxX = qMax(domain.m_maxX,x);
105 domain.m_maxY = 100;
106 break;
107 }
107 108
108 case QChartSeries::SeriesTypePie: {
109 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
110 // TODO: domain stuff
111 break;
112 }
109 case QChartSeries::SeriesTypePie: {
110 QPieSeries *pieSeries = static_cast<QPieSeries *>(series);
111 // TODO: domain stuff
112 break;
113 }
113 114
114 case QChartSeries::SeriesTypeScatter: {
115 QScatterSeries *scatterSeries = qobject_cast<QScatterSeries *>(series);
116 Q_ASSERT(scatterSeries);
117 foreach (QPointF point, scatterSeries->data()) {
118 domain.m_minX = qMin(domain.m_minX, point.x());
119 domain.m_maxX = qMax(domain.m_maxX, point.x());
120 domain.m_minY = qMin(domain.m_minY, point.y());
121 domain.m_maxY = qMax(domain.m_maxY, point.y());
122 }
123 break;
115 case QChartSeries::SeriesTypeScatter: {
116 QScatterSeries *scatterSeries = qobject_cast<QScatterSeries *>(series);
117 Q_ASSERT(scatterSeries);
118 foreach (QPointF point, scatterSeries->data()) {
119 domain.m_minX = qMin(domain.m_minX, point.x());
120 domain.m_maxX = qMax(domain.m_maxX, point.x());
121 domain.m_minY = qMin(domain.m_minY, point.y());
122 domain.m_maxY = qMax(domain.m_maxY, point.y());
124 123 }
124 break;
125 }
125 126
126 default: {
127 qDebug()<<__FUNCTION__<<"type" << series->type()<<"not supported";
128 return;
129 break;
127 case QChartSeries::SeriesTypeSpline: {
128 QSplineSeries* splineSeries = static_cast<QSplineSeries*>(series);
129
130 for (int i = 0; i < splineSeries->count(); i++)
131 {
132 qreal x = splineSeries->at(i).x();
133 qreal y = splineSeries->at(i).y();
134 domain.m_minX = qMin(domain.m_minX,x);
135 domain.m_minY = qMin(domain.m_minY,y);
136 domain.m_maxX = qMax(domain.m_maxX,x);
137 domain.m_maxY = qMax(domain.m_maxY,y);
130 138 }
139 break;
140 }
141
142 default: {
143 qDebug()<<__FUNCTION__<<"type" << series->type()<<"not supported";
144 return;
145 break;
146 }
131 147
132 148 }
133 149
@@ -172,7 +188,7 void ChartDataSet::removeSeries(QChartSeries* series)
172 188 emit axisRemoved(axis);
173 189 m_domainMap.remove(axis);
174 190 if(axis != m_axisY)
175 delete axis;
191 delete axis;
176 192 }
177 193 series->setParent(0);
178 194 break;
@@ -194,7 +210,7 void ChartDataSet::removeAllSeries()
194 210 m_domainMap.remove(axis);
195 211 emit axisRemoved(axis);
196 212 if(axis != m_axisY) delete axis;
197 }
213 }
198 214 m_domainIndex=0;
199 215 }
200 216
@@ -25,13 +25,13
25 25 QTCOMMERCIALCHART_BEGIN_NAMESPACE
26 26
27 27 ChartPresenter::ChartPresenter(QChart* chart,ChartDataSet* dataset):QObject(chart),
28 m_chart(chart),
29 m_dataset(dataset),
30 m_chartTheme(0),
31 m_marginSize(0),
32 m_rect(QRectF(QPoint(0,0),m_chart->size()))
28 m_chart(chart),
29 m_dataset(dataset),
30 m_chartTheme(0),
31 m_marginSize(0),
32 m_rect(QRectF(QPoint(0,0),m_chart->size()))
33 33 {
34 createConnections();
34 createConnections();
35 35 setChartTheme(QChart::ChartThemeDefault);
36 36
37 37 }
@@ -60,7 +60,7 QRectF ChartPresenter::geometry() const
60 60 void ChartPresenter::handleGeometryChanged()
61 61 {
62 62 m_rect = QRectF(QPoint(0,0),m_chart->size());
63 m_rect.adjust(m_marginSize,m_marginSize, -m_marginSize, -m_marginSize);
63 // m_rect.adjust(m_marginSize,m_marginSize, -m_marginSize, -m_marginSize);
64 64 Q_ASSERT(m_rect.isValid());
65 65 emit geometryChanged(m_rect);
66 66 }
@@ -80,9 +80,9 void ChartPresenter::handleAxisAdded(QChartAxis* axis)
80 80 AxisItem* item ;
81 81
82 82 if(axis==m_dataset->axisX()){
83 item = new AxisItem(AxisItem::X_AXIS,m_chart);
83 item = new AxisItem(AxisItem::X_AXIS,m_chart);
84 84 }else{
85 item = new AxisItem(AxisItem::Y_AXIS,m_chart);
85 item = new AxisItem(AxisItem::Y_AXIS,m_chart);
86 86 }
87 87 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
88 88 QObject::connect(axis,SIGNAL(update(QChartAxis*)),item,SLOT(handleAxisUpdate(QChartAxis*)));
@@ -105,74 +105,77 void ChartPresenter::handleSeriesAdded(QChartSeries* series)
105 105 {
106 106 switch(series->type())
107 107 {
108 case QChartSeries::SeriesTypeLine: {
109 QLineChartSeries* lineSeries = static_cast<QLineChartSeries*>(series);
110 LineChartItem* item = new LineChartAnimationItem(this,lineSeries,m_chart);
111 m_chartTheme->decorate(item,lineSeries,m_chartItems.count());
112 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
113 QObject::connect(lineSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
114 m_chartItems.insert(series,item);
115 break;
116 }
117
118 case QChartSeries::SeriesTypeBar: {
119 QBarChartSeries* barSeries = static_cast<QBarChartSeries*>(series);
120 BarPresenter* item = new BarPresenter(barSeries,m_chart);
121 m_chartTheme->decorate(item,barSeries,m_chartItems.count());
122 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
123 QObject::connect(barSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
124 m_chartItems.insert(series,item);
125 // m_axisXItem->setVisible(false);
126 break;
127 }
128
129 case QChartSeries::SeriesTypeStackedBar: {
130
131 QStackedBarChartSeries* stackedBarSeries = static_cast<QStackedBarChartSeries*>(series);
132 StackedBarPresenter* item = new StackedBarPresenter(stackedBarSeries,m_chart);
133 m_chartTheme->decorate(item,stackedBarSeries,m_chartItems.count());
134 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
135 QObject::connect(stackedBarSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
136 m_chartItems.insert(series,item);
137 break;
138 }
139
140 case QChartSeries::SeriesTypePercentBar: {
141
142 QPercentBarChartSeries* percentBarSeries = static_cast<QPercentBarChartSeries*>(series);
143 PercentBarPresenter* item = new PercentBarPresenter(percentBarSeries,m_chart);
144 m_chartTheme->decorate(item,percentBarSeries ,m_chartItems.count());
145 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
146 QObject::connect(percentBarSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
147 m_chartItems.insert(series,item);
148 break;
149 }
150 case QChartSeries::SeriesTypeScatter: {
151 QScatterSeries *scatterSeries = qobject_cast<QScatterSeries *>(series);
152 ScatterPresenter *scatterPresenter = new ScatterPresenter(scatterSeries, m_chart);
153 QObject::connect(this, SIGNAL(geometryChanged(const QRectF&)),
154 scatterPresenter, SLOT(handleGeometryChanged(const QRectF&)));
155 m_chartTheme->decorate(scatterPresenter, scatterSeries, m_chartItems.count());
156 m_chartItems.insert(scatterSeries, scatterPresenter);
157 break;
158 }
159 case QChartSeries::SeriesTypePie: {
160 QPieSeries *s = qobject_cast<QPieSeries *>(series);
161 PiePresenter* pie = new PiePresenter(m_chart, s);
162 m_chartTheme->decorate(pie, s, m_chartItems.count());
163 QObject::connect(this, SIGNAL(geometryChanged(const QRectF&)), pie, SLOT(handleGeometryChanged(const QRectF&)));
164 m_chartItems.insert(series, pie);
165 break;
166 }
108 case QChartSeries::SeriesTypeLine: {
109 QLineChartSeries* lineSeries = static_cast<QLineChartSeries*>(series);
110 LineChartItem* item = new LineChartAnimationItem(this,lineSeries,m_chart);
111 m_chartTheme->decorate(item,lineSeries,m_chartItems.count());
112 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
113 QObject::connect(lineSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
114 m_chartItems.insert(series,item);
115 break;
116 }
117
118 case QChartSeries::SeriesTypeBar: {
119 QBarChartSeries* barSeries = static_cast<QBarChartSeries*>(series);
120 BarPresenter* item = new BarPresenter(barSeries,m_chart);
121 m_chartTheme->decorate(item,barSeries,m_chartItems.count());
122 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
123 QObject::connect(barSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
124 m_chartItems.insert(series,item);
125 // m_axisXItem->setVisible(false);
126 break;
127 }
128
129 case QChartSeries::SeriesTypeStackedBar: {
130
131 QStackedBarChartSeries* stackedBarSeries = static_cast<QStackedBarChartSeries*>(series);
132 StackedBarPresenter* item = new StackedBarPresenter(stackedBarSeries,m_chart);
133 m_chartTheme->decorate(item,stackedBarSeries,m_chartItems.count());
134 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
135 QObject::connect(stackedBarSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
136 m_chartItems.insert(series,item);
137 break;
138 }
139
140 case QChartSeries::SeriesTypePercentBar: {
141
142 QPercentBarChartSeries* percentBarSeries = static_cast<QPercentBarChartSeries*>(series);
143 PercentBarPresenter* item = new PercentBarPresenter(percentBarSeries,m_chart);
144 m_chartTheme->decorate(item,percentBarSeries ,m_chartItems.count());
145 QObject::connect(this,SIGNAL(geometryChanged(const QRectF&)),item,SLOT(handleGeometryChanged(const QRectF&)));
146 QObject::connect(percentBarSeries,SIGNAL(changed(int)),item,SLOT(handleModelChanged(int)));
147 m_chartItems.insert(series,item);
148 break;
149 }
150 case QChartSeries::SeriesTypeScatter: {
151 QScatterSeries *scatterSeries = qobject_cast<QScatterSeries *>(series);
152 ScatterPresenter *scatterPresenter = new ScatterPresenter(scatterSeries, m_chart);
153 QObject::connect(this, SIGNAL(geometryChanged(const QRectF&)),
154 scatterPresenter, SLOT(handleGeometryChanged(const QRectF&)));
155 m_chartTheme->decorate(scatterPresenter, scatterSeries, m_chartItems.count());
156 m_chartItems.insert(scatterSeries, scatterPresenter);
157 break;
158 }
159 case QChartSeries::SeriesTypePie: {
160 QPieSeries *s = qobject_cast<QPieSeries *>(series);
161 PiePresenter* pie = new PiePresenter(m_chart, s);
162 m_chartTheme->decorate(pie, s, m_chartItems.count());
163 QObject::connect(this, SIGNAL(geometryChanged(const QRectF&)), pie, SLOT(handleGeometryChanged(const QRectF&)));
164 m_chartItems.insert(series, pie);
165 break;
166 }
167 167 case QChartSeries::SeriesTypeSpline: {
168 168 QSplineSeries* splineSeries = qobject_cast<QSplineSeries*>(series);
169 SplinePresenter* splinePresenter = new SplinePresenter
169 SplinePresenter* splinePresenter = new SplinePresenter(splineSeries, m_chart);
170 QObject::connect(this, SIGNAL(geometryChanged(const QRectF&)), splinePresenter, SLOT(handleGeometryChanged(const QRectF&)));
171 m_chartTheme->decorate(splinePresenter, splineSeries, m_chartItems.count());
172 m_chartItems.insert(splineSeries, splinePresenter);
173 break;
174 }
175 default: {
176 qDebug()<< "Series type" << series->type() << "not implemented.";
170 177 break;
171 178 }
172 default: {
173 qDebug()<< "Series type" << series->type() << "not implemented.";
174 break;
175 }
176 179 }
177 180
178 181 if(m_rect.isValid()) emit geometryChanged(m_rect);
@@ -180,8 +183,8 void ChartPresenter::handleSeriesAdded(QChartSeries* series)
180 183
181 184 void ChartPresenter::handleSeriesRemoved(QChartSeries* series)
182 185 {
183 ChartItem* item = m_chartItems.take(series);
184 delete item;
186 ChartItem* item = m_chartItems.take(series);
187 delete item;
185 188 }
186 189
187 190 void ChartPresenter::handleSeriesChanged(QChartSeries* series)
@@ -217,8 +220,8 void ChartPresenter::setChartTheme(QChart::ChartTheme theme)
217 220
218 221 QMapIterator<QChartAxis*,AxisItem*> j(m_axisItems);
219 222 while (j.hasNext()) {
220 j.next();
221 m_chartTheme->decorate(j.key(),j.value());
223 j.next();
224 m_chartTheme->decorate(j.key(),j.value());
222 225 }
223 226 }
224 227
@@ -12,6 +12,7
12 12 #include "qscatterseries.h"
13 13 #include "qpieseries.h"
14 14 #include "qpieslice.h"
15 #include "qsplineseries.h"
15 16
16 17 //items
17 18 #include "axisitem_p.h"
@@ -21,6 +22,7
21 22 #include "percentbarpresenter.h"
22 23 #include "scatterpresenter_p.h"
23 24 #include "piepresenter.h"
25 #include "splinepresenter_p.h"
24 26
25 27 //themes
26 28 #include "chartthemevanilla_p.h"
@@ -226,4 +228,21 void ChartTheme::decorate(QChartAxis* axis,AxisItem* item)
226 228 axis->setShadesOpacity(0.5);
227 229 }
228 230
231 void ChartTheme::decorate(SplinePresenter* presenter, QSplineSeries* series, int count)
232 {
233 Q_ASSERT(presenter);
234 Q_ASSERT(series);
235
236 // QColor color = m_seriesColor.at(count % m_seriesColor.size());
237 // TODO: define alpha in the theme? or in the series?
238 //color.setAlpha(120);
239
240 // QBrush brush(color, Qt::SolidPattern);
241 // presenter->m_markerBrush = brush;
242
243 // QPen pen(brush, 3);
244 // pen.setColor(color);
245 // presenter->m_markerPen = pen;
246 }
247
229 248 QTCOMMERCIALCHART_END_NAMESPACE
@@ -21,6 +21,8 class QScatterSeries;
21 21 class ScatterPresenter;
22 22 class PiePresenter;
23 23 class QPieSeries;
24 class SplinePresenter;
25 class QSplineSeries;
24 26
25 27 class ChartTheme
26 28 {
@@ -38,6 +40,7 public:
38 40 void decorate(ScatterPresenter* presenter, QScatterSeries* series, int count);
39 41 void decorate(PiePresenter* item, QPieSeries* series, int count);
40 42 void decorate(QChartAxis* axis,AxisItem* item);
43 void decorate(SplinePresenter* presenter, QSplineSeries* series, int count);
41 44
42 45 protected:
43 46 QChart::ChartTheme m_id;
@@ -1,100 +1,110
1 1 #include "qsplineseries.h"
2 2
3 QTCOMMERCIALCHART_BEGIN_NAMESPACE
4
3 5 QSplineSeries::QSplineSeries(QObject *parent) :
4 QObject(parent)
6 QChartSeries(parent)
5 7 {
6 8 }
7 9
8 10 QSplineSeries& QSplineSeries::operator << (const QPointF &value)
9 11 {
10 d->m_data.append(value);
11 emit changed();
12 // d->m_data.append(value);
13 m_data.append(value);
14 // emit changed();
12 15 return *this;
13 16 }
14 17
15 void QSplineSeries::GetCurveControlPoints()
16 {
18 void QSplineSeries::addData(QPointF value)
19 {
20 m_data.append(value);
21 }
22
23 void QSplineSeries::calculateControlPoints()
24 {
25
26 // Based on http://www.codeproject.com/Articles/31859/Draw-a-Smooth-Curve-through-a-Set-of-2D-Points-wit
27 // CPOL Licence
28
17 29 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 }
30 if (n == 1)
31 { // Special case: Bezier curve should be a straight line.
32 // firstControlPoints = new Point[1];
33 // 3P1 = 2P0 + P3
34 m_controlPoints.append(QPointF((2 * m_data[0].x() + m_data[1].x()) / 3, (2 * m_data[0].y() + m_data[1].y()) / 3));
35
36 // P2 = 2P1 P0
37 m_controlPoints.append(QPointF(2 * m_controlPoints[0].x() - m_data[0].x(), 2 * m_controlPoints[0].y() - m_data[0].y()));
38 return;
74 39 }
75 40
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)
41 // Calculate first Bezier control points
42 // Right hand side vector
43 // Set of equations for P0 to Pn points.
44 //
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 |
47 // | 0 1 4 1 ... 0 0 0 ... 0 0 0 | | P1_3 | | 4 * P2 + 2 * P3 |
48 // | . . . . . . . . . . . . | | ... | | ... |
49 // | 0 0 0 0 ... 1 4 1 ... 0 0 0 | * | P1_i | = | 4 * P(i-1) + 2 * Pi |
50 // | . . . . . . . . . . . . | | ... | | ... |
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 |
53 //
54 QList<qreal> rhs;
55 rhs.append(m_data[0].x() + 2 * m_data[1].x());
56
57 // Set right hand side X values
58 for (int i = 1; i < m_data.size() - 1; ++i)
59 rhs.append(4 * m_data[i].x() + 2 * m_data[i + 1].x());
60
61 rhs.append((8 * m_data[n - 1].x() + m_data[n].x()) / 2.0);
62 // Get first control points X-values
63 QList<qreal> x = getFirstControlPoints(rhs);
64 rhs[0] = m_data[0].y() + 2 * m_data[1].y();
65
66 // Set right hand side Y values
67 for (int i = 1; i < m_data.size() - 1; ++i)
68 rhs[i] = 4 * m_data[i].y() + 2 * m_data[i + 1].y();
69
70 rhs[n - 1] = (8 * m_data[n - 1].y() + m_data[n].y()) / 2.0;
71 // Get first control points Y-values
72 QList<qreal> y = getFirstControlPoints(rhs);
73
74 // Fill output arrays.
75 // firstControlPoints = new Point[n];
76 // secondControlPoints = new Point[n];
77 for (int i = 0; i < m_data.size(); ++i)
83 78 {
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;
79 // First control point
80 m_controlPoints.append(QPointF(x[i], y[i]));
81 // Second control point
82 if (i < n - 1)
83 m_controlPoints.append(QPointF(2 * m_data[i + 1].x() - x[i + 1], 2 * m_data[i + 1].y() - y[i + 1]));
84 else
85 m_controlPoints.append(QPointF((m_data[n].x() + x[n - 1]) / 2, (m_data[n].y() + y[n - 1]) / 2));
100 86 }
87 }
88
89 QList<qreal> QSplineSeries::getFirstControlPoints(QList<qreal> rhs)
90 {
91 QList<qreal> x; // Solution vector.
92 QList<qreal> tmp; // Temp workspace.
93
94 qreal b = 2.0;
95 x.append(rhs[0] / b);
96 tmp.append(0);
97 for (int i = 1; i < rhs.size(); i++) // Decomposition and forward substitution.
98 {
99 tmp.append(1 / b);
100 b = (i < rhs.size() - 1 ? 4.0 : 3.5) - tmp[i];
101 x.append((rhs[i] - x[i - 1]) / b);
102 }
103 for (int i = 1; i < rhs.size(); i++)
104 x[rhs.size() - i - 1] -= tmp[rhs.size() - i] * x[rhs.size() - i]; // Backsubstitution.
105
106 return x;
107 }
108 #include "moc_qsplineseries.cpp"
109
110 QTCOMMERCIALCHART_END_NAMESPACE
@@ -1,7 +1,11
1 1 #ifndef QSPLINESERIES_H
2 2 #define QSPLINESERIES_H
3 3
4 #include "qchartglobal.h"
5 #include <QtGlobal>
4 6 #include "qchartseries.h"
7 #include <QList>
8 #include <QPointF>
5 9
6 10 QTCOMMERCIALCHART_BEGIN_NAMESPACE
7 11
@@ -15,6 +19,12 class QSplineSeries : public QChartSeries
15 19 void addData(QPointF value);
16 20 QSplineSeries& operator << (const QPointF &value);
17 21 void calculateControlPoints();
22 QList<qreal> getFirstControlPoints(QList<qreal> rhs);
23
24 int count() const { return m_data.size(); }
25
26 QPointF at(int index) const { return m_data[index]; }
27 QPointF controlPoint(int index) const { return m_controlPoints[index]; }
18 28
19 29 signals:
20 30
@@ -3,13 +3,10 DEPENDPATH += $$PWD
3 3
4 4 SOURCES += \
5 5 $$PWD/qsplineseries.cpp \
6 splinechart/splinepresenter.cpp
6 $$PWD/splinepresenter.cpp
7 7
8 PRIVATE_HEADERS +=
8 PRIVATE_HEADERS += \
9 $$PWD/splinepresenter_p.h
9 10
10 11 PUBLIC_HEADERS += \
11 12 $$PWD/qsplineseries.h
12
13 HEADERS += \
14 splinechart/qsplineseries.h \
15 splinechart/splinepresenter_p.h
@@ -1,16 +1,54
1 1 #include "splinepresenter_p.h"
2 #include <QPainter>
2 3
3 SplinePresenter::SplinePresenter(QObject *parent) :
4 QObject(parent)
4 QTCOMMERCIALCHART_BEGIN_NAMESPACE
5
6 SplinePresenter::SplinePresenter(QSplineSeries* series, QGraphicsObject *parent) :
7 ChartItem(parent),m_series(series),m_boundingRect()
5 8 {
9 if (parent)
10 m_boundingRect = parent->boundingRect();
11 else
12 m_boundingRect = QRectF(10,50, 250, 250);
6 13 }
7 14
8 15 void SplinePresenter::handleGeometryChanged(const QRectF&)
9 16 {
10 //
17 update();
11 18 }
12 19
13 20 void SplinePresenter::handleDomainChanged(const Domain& domain)
14 21 {
15 22 //
16 23 }
24
25 void SplinePresenter::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
26 {
27 Q_UNUSED(widget);
28 Q_UNUSED(option);
29 painter->save();
30
31 painter->setPen(Qt::SolidLine);
32
33 QPainterPath splinePath;
34 splinePath.moveTo(m_series->at(0));
35 for (int i = 0; i < m_series->count() - 1; i++)
36 {
37 painter->setPen(Qt::red);
38 splinePath.cubicTo(m_series->controlPoint(2 * i), m_series->controlPoint(2 * i + 1), m_series->at(i + 1));
39 painter->drawEllipse(m_series->at(i), 4, 4);
40
41 painter->setPen(Qt::blue);
42 painter->drawLine(m_series->at(i), m_series->controlPoint(2 * i));
43 painter->drawLine(m_series->at(i + 1), m_series->controlPoint(2 * i + 1));
44 painter->drawEllipse(m_series->controlPoint(2 * i), 4, 4);
45 painter->drawEllipse(m_series->controlPoint(2 * i + 1), 4, 4);
46 }
47 painter->setPen(Qt::red);
48 painter->drawPath(splinePath);
49 painter->restore();
50 }
51
52 #include "moc_splinepresenter_p.cpp"
53
54 QTCOMMERCIALCHART_END_NAMESPACE
@@ -3,6 +3,7
3 3
4 4 #include "chartitem_p.h"
5 5 #include <QObject>
6 #include "qsplineseries.h"
6 7
7 8 QTCOMMERCIALCHART_BEGIN_NAMESPACE
8 9
@@ -10,14 +11,20 class SplinePresenter : public QObject, public ChartItem
10 11 {
11 12 Q_OBJECT
12 13 public:
13 SplinePresenter(QObject *parent = 0);
14 SplinePresenter(QSplineSeries* series, QGraphicsObject *parent = 0);
14 15
15 void handleGeometryChanged(const QRectF&);
16 void handleDomainChanged(const Domain& domain);
16 QRectF boundingRect() const { return m_boundingRect; }
17 void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
17 18
18 19 signals:
19 20
20 21 public slots:
22 void handleDomainChanged(const Domain& domain);
23 void handleGeometryChanged(const QRectF& rect);
24
25 private:
26 QSplineSeries* m_series;
27 QRectF m_boundingRect;
21 28
22 29 };
23 30
@@ -1,7 +1,7
1 1 #include "dataseriedialog.h"
2 2 #include <QDialogButtonBox>
3 3 #include <QGridLayout>
4 #include <QCheckbox>
4 #include <QCheckBox>
5 5 #include <QPushButton>
6 6 #include <QGroupBox>
7 7 #include <QRadioButton>
General Comments 0
You need to be logged in to leave comments. Login now