1 /*
2  * Copyright (C) 2013 Emweb bv, Herent, Belgium.
3  *
4  * See the LICENSE file for terms of use.
5  */
6 
7 #include "Wt/Chart/WAbstractDataSeries3D.h"
8 
9 #include "Wt/WAbstractItemModel.h"
10 #include "Wt/WApplication.h"
11 #include "Wt/WCanvasPaintDevice.h"
12 #include "Wt/WEnvironment.h"
13 #include "Wt/WPainter.h"
14 #include "Wt/Chart/WAbstractColorMap.h"
15 #include "Wt/Chart/WCartesian3DChart.h"
16 
17 using namespace Wt;
18 
19 namespace {
clearConnections(std::vector<Wt::Signals::connection> connections)20   void clearConnections(std::vector<Wt::Signals::connection> connections) {
21     for (unsigned i=0; i < connections.size(); i++)
22       connections[i].disconnect();
23     connections.clear();
24   }
25 }
26 
27 namespace Wt {
28   namespace Chart {
29 
WAbstractDataSeries3D(std::shared_ptr<WAbstractItemModel> model)30 WAbstractDataSeries3D::WAbstractDataSeries3D(std::shared_ptr<WAbstractItemModel> model)
31   : chart_(0),
32     rangeCached_(false),
33     pointSize_(2.0),
34     colormap_(0),
35     showColorMap_(false),
36     colorMapSide_(Side::Right),
37     legendEnabled_(true),
38     hidden_(false),
39     /* in webGL, the z-direction is out of the screen, in model coordinates
40      * it's the vertical direction */
41     mvMatrix_(1.0f, 0.0f, 0.0f, 0.0f,
42 	      0.0f, 0.0f, 1.0f, 0.0f,
43 	      0.0f, 1.0f, 0.0f, 0.0f,
44 	      0.0f, 0.0f, 0.0f, 1.0f)
45 {
46   model_ = model;
47 }
48 
~WAbstractDataSeries3D()49 WAbstractDataSeries3D::~WAbstractDataSeries3D()
50 {
51 }
52 
53 void WAbstractDataSeries3D
setModel(const std::shared_ptr<WAbstractItemModel> & model)54 ::setModel(const std::shared_ptr<WAbstractItemModel>& model)
55 {
56   if (model != model_) {
57     // handle previous model
58     if (model_ && chart_) {
59       clearConnections(connections_);
60     }
61     rangeCached_ = false;
62 
63     // set new model
64     model_ = model;
65 
66     if (model_ && chart_) {
67       chart_->updateChart(ChartUpdates::GLContext);
68       connections_.push_back
69 	(model_->modelReset().connect
70 	 (chart_, std::bind(&WCartesian3DChart::updateChart, chart_,
71 			    ChartUpdates::GLTextures | ChartUpdates::GLContext)));
72       connections_.push_back
73 	(model_->dataChanged().connect
74 	 (chart_, std::bind(&WCartesian3DChart::updateChart, chart_,
75 			    ChartUpdates::GLTextures | ChartUpdates::GLContext)));
76       connections_.push_back
77 	(model_->rowsInserted().connect
78 	 (chart_, std::bind(&WCartesian3DChart::updateChart, chart_,
79 			    ChartUpdates::GLTextures | ChartUpdates::GLContext)));
80       connections_.push_back
81 	(model_->columnsInserted().connect
82 	 (chart_, std::bind(&WCartesian3DChart::updateChart, chart_,
83 			    ChartUpdates::GLTextures | ChartUpdates::GLContext)));
84       connections_.push_back
85 	(model_->rowsRemoved().connect
86 	 (chart_, std::bind(&WCartesian3DChart::updateChart, chart_,
87 			    ChartUpdates::GLTextures | ChartUpdates::GLContext)));
88       connections_.push_back
89 	(model_->columnsRemoved().connect
90 	 (chart_, std::bind(&WCartesian3DChart::updateChart, chart_,
91 			    ChartUpdates::GLTextures | ChartUpdates::GLContext)));
92     }
93   }
94 }
95 
setTitle(const WString & name)96 void WAbstractDataSeries3D::setTitle(const WString& name)
97 {
98   name_ = name;
99   if (chart_)
100     chart_->updateChart(ChartUpdates::GLTextures);
101 }
102 
setPointSize(double size)103 void WAbstractDataSeries3D::setPointSize(double size)
104 {
105   if (size != pointSize_) {
106     pointSize_ = size;
107     if (chart_)
108       chart_->updateChart(ChartUpdates::GLContext | ChartUpdates::GLTextures);
109   }
110 }
111 
setPointSprite(const std::string & image)112 void WAbstractDataSeries3D::setPointSprite(const std::string &image)
113 {
114   if (image != pointSprite_) {
115     pointSprite_ = image;
116     if (chart_)
117       chart_->updateChart(ChartUpdates::GLContext | ChartUpdates::GLTextures);
118   }
119 }
120 
121 void WAbstractDataSeries3D
setColorMap(const std::shared_ptr<WAbstractColorMap> & colormap)122 ::setColorMap(const std::shared_ptr<WAbstractColorMap>& colormap)
123 {
124   colormap_ = colormap;
125   if (chart_)
126     chart_->updateChart(ChartUpdates::GLContext | ChartUpdates::GLTextures);
127 }
128 
setColorMapVisible(bool enabled)129 void WAbstractDataSeries3D::setColorMapVisible(bool enabled)
130 {
131   if (showColorMap_ == enabled)
132     return;
133 
134   showColorMap_ = enabled;
135   if (chart_)
136     chart_->updateChart(ChartUpdates::GLTextures);
137 }
138 
setColorMapSide(Side side)139 void WAbstractDataSeries3D::setColorMapSide(Side side)
140 {
141   if (colorMapSide_ == side)
142     return;
143 
144   colorMapSide_ = side;
145   if (chart_)
146     chart_->updateChart(ChartUpdates::GLTextures);
147 }
148 
setHidden(bool enabled)149 void WAbstractDataSeries3D::setHidden(bool enabled)
150 {
151   if (enabled != hidden_) {
152     hidden_ = enabled;
153     if (chart_)
154       chart_->updateChart(ChartUpdates::GLContext | ChartUpdates::GLTextures);
155   }
156 }
157 
colorTexture()158 WGLWidget::Texture WAbstractDataSeries3D::colorTexture()
159 {
160   std::unique_ptr<WPaintDevice> cpd;
161   if (!colormap_) {
162     cpd = chart_->createPaintDevice(WLength(1),WLength(1));
163     WColor seriesColor = chartpaletteColor();
164     WPainter painter(cpd.get());
165     painter.setPen(WPen(seriesColor));
166     painter.drawLine(0,0.5,1,0.5);
167     painter.end();
168   } else {
169     cpd = chart_->createPaintDevice(WLength(1),WLength(1024));
170     WPainter painter(cpd.get());
171     colormap_->createStrip(&painter);
172     painter.end();
173   }
174 
175   WGLWidget::Texture tex = chart_->createTexture();
176   chart_->bindTexture(WGLWidget::TEXTURE_2D, tex);
177   chart_->pixelStorei(WGLWidget::UNPACK_FLIP_Y_WEBGL, 1);
178   chart_->texImage2D(WGLWidget::TEXTURE_2D, 0,
179 		     WGLWidget::RGBA, WGLWidget::RGBA,
180 		     WGLWidget::UNSIGNED_BYTE, cpd.get());
181 
182   return tex;
183 }
184 
pointSpriteTexture()185 WGLWidget::Texture WAbstractDataSeries3D::pointSpriteTexture()
186 {
187   WGLWidget::Texture tex = chart_->createTexture();
188   chart_->bindTexture(WGLWidget::TEXTURE_2D, tex);
189   if (pointSprite_.empty()) {
190     std::unique_ptr<WPaintDevice> cpd
191       = chart_->createPaintDevice(WLength(1), WLength(1));
192     WColor color = WColor(255, 255, 255, 255);
193     WPainter painter(cpd.get());
194     painter.setPen(WPen(color));
195     painter.drawLine(0,0.5,1,0.5);
196     painter.end();
197     chart_->texImage2D(WGLWidget::TEXTURE_2D, 0,
198 		       WGLWidget::RGBA, WGLWidget::RGBA,
199 		       WGLWidget::UNSIGNED_BYTE, cpd.get());
200   }
201 
202   return tex;
203 }
204 
205 void WAbstractDataSeries3D
loadPointSpriteTexture(const WGLWidget::Texture & tex)206 ::loadPointSpriteTexture(const WGLWidget::Texture &tex) const
207 {
208   chart_->bindTexture(WGLWidget::TEXTURE_2D, tex);
209   if (!pointSprite_.empty()) {
210     chart_->texImage2D(WGLWidget::TEXTURE_2D, 0, WGLWidget::RGBA,
211 		       WGLWidget::RGBA, WGLWidget::UNSIGNED_BYTE, pointSprite_);
212   }
213 }
214 
setDefaultTitle(int i)215 void WAbstractDataSeries3D::setDefaultTitle(int i)
216 {
217   std::string tmp = std::string("dataset ");
218   tmp.append(std::to_string(i));
219   name_ = WString(tmp);
220 }
221 
chartpaletteColor()222 WColor WAbstractDataSeries3D::chartpaletteColor() const
223 {
224   if (colormap_)
225     return WColor();
226 
227   int index = 0;
228   for (unsigned i=0; i < chart_->dataSeries().size(); i++) { // which colorscheme
229     if (chart_->dataSeries()[i] == this) {
230       break;
231     } else if (chart_->dataSeries()[i]->colorMap() == 0) {
232       index++;
233     }
234   }
235   return chart_->palette()->brush(index).color();
236 }
237 
setChart(WCartesian3DChart * chart)238 void WAbstractDataSeries3D::setChart(WCartesian3DChart *chart)
239 {
240   if (chart == chart_)
241     return;
242   else if (chart_)
243     chart_->removeDataSeries(this);
244 
245   if (chart_ && model_)
246     clearConnections(connections_);
247 
248   chart_ = chart;
249 
250   if (chart_ && model_) {
251     connections_.push_back
252       (model_->modelReset().connect
253        (chart_, std::bind(&WCartesian3DChart::updateChart, chart_,
254 			  ChartUpdates::GLTextures | ChartUpdates::GLContext)));
255     connections_.push_back
256       (model_->dataChanged().connect
257        (chart_, std::bind(&WCartesian3DChart::updateChart, chart_,
258 			  ChartUpdates::GLTextures | ChartUpdates::GLContext)));
259     connections_.push_back
260       (model_->rowsInserted().connect
261        (chart_, std::bind(&WCartesian3DChart::updateChart, chart_,
262 			  ChartUpdates::GLTextures | ChartUpdates::GLContext)));
263     connections_.push_back
264       (model_->columnsInserted().connect
265        (chart_, std::bind(&WCartesian3DChart::updateChart, chart_,
266 			  ChartUpdates::GLTextures | ChartUpdates::GLContext)));
267     connections_.push_back
268       (model_->rowsRemoved().connect
269        (chart_, std::bind(&WCartesian3DChart::updateChart, chart_,
270 			  ChartUpdates::GLTextures | ChartUpdates::GLContext)));
271     connections_.push_back
272       (model_->columnsRemoved().connect
273        (chart_, std::bind(&WCartesian3DChart::updateChart, chart_,
274 			  ChartUpdates::GLTextures | ChartUpdates::GLContext)));
275   }
276 }
277 
getGlObjects()278 std::vector<cpp17::any> WAbstractDataSeries3D::getGlObjects()
279 {
280   return std::vector<cpp17::any>();
281 }
282 
283   }
284 }
285