1 #include "Wt/Chart/WGridData.h"
2 
3 #include "Wt/WAbstractItemModel.h"
4 #include "Wt/WException.h"
5 #include "WebUtils.h"
6 
7 namespace Wt {
8   namespace Chart {
9 
WGridData(std::shared_ptr<WAbstractItemModel> model)10 WGridData::WGridData(std::shared_ptr<WAbstractItemModel> model)
11   : WAbstractGridData(model),
12     XAbscisColumn_(0),
13     YAbscisRow_(0)
14 {}
15 
~WGridData()16 WGridData::~WGridData()
17 {}
18 
setXSeriesColumn(int modelColumn)19 void WGridData::setXSeriesColumn(int modelColumn)
20 {
21   XAbscisColumn_ = modelColumn;
22   rangeCached_ = false;
23 }
24 
setYSeriesRow(int modelRow)25 void WGridData::setYSeriesRow(int modelRow)
26 {
27   YAbscisRow_ = modelRow;
28   rangeCached_ = false;
29 }
30 
nbXPoints()31 int WGridData::nbXPoints() const
32 {
33   return model_->rowCount() - 1;
34 }
35 
nbYPoints()36 int WGridData::nbYPoints() const
37 {
38   return model_->columnCount() - 1;
39 }
40 
axisLabel(int u,Axis axis)41 WString WGridData::axisLabel(int u, Axis axis) const
42 {
43   if (axis == Axis::X3D) {
44     if (u >= YAbscisRow_)
45       u++;
46     return asString(model_->data(u, XAbscisColumn_));
47   } else if (axis == Axis::Y3D) {
48     if (u >= XAbscisColumn_)
49       u++;
50     return asString(model_->data(YAbscisRow_, u));
51   } else {
52     throw WException("WGridData: don't know this type of axis");
53   }
54 }
55 
countSimpleData()56 int WGridData::countSimpleData() const
57 {
58   int result = 0;
59   int nbModelRows = model_->rowCount();
60   int nbModelCols = model_->columnCount();
61   for (int i=0; i<nbModelRows; i++) {
62     if (i == YAbscisRow_)
63       continue;
64     for (int j=0; j<nbModelCols; j++) {
65       if (j == XAbscisColumn_)
66 	continue;
67 
68       if (!cpp17::any_has_value(model_->data(i,j,ItemDataRole::MarkerBrushColor))) {
69 	result++;
70       }
71     }
72   }
73 
74   return result;
75 }
76 
data(int i,int j)77 cpp17::any WGridData::data(int i, int j) const
78 {
79   if (i >= XAbscisColumn_) {
80     i++;
81   }
82   if (j >= YAbscisRow_) {
83     j++;
84   }
85 
86   return model_->data(i,j);
87 }
88 
minimum(Axis axis)89 double WGridData::minimum(Axis axis) const
90 {
91   if (axis == Axis::X3D) {
92     if (YAbscisRow_ != 0) {
93       return Wt::asNumber(model_->data(0, XAbscisColumn_));
94     } else {
95       return Wt::asNumber(model_->data(1, XAbscisColumn_));
96     }
97   } else if (axis == Axis::Y3D) {
98     if (XAbscisColumn_ != 0) {
99       return Wt::asNumber(model_->data(YAbscisRow_, 0));
100     } else {
101       return Wt::asNumber(model_->data(YAbscisRow_, 1));
102     }
103   } else if (axis == Axis::Z3D) {
104     if (!rangeCached_) {
105       findRange();
106     }
107     return zMin_;
108   } else {
109     throw WException("WAbstractGridData.C: unknown Axis-type");
110   }
111 }
112 
maximum(Axis axis)113 double WGridData::maximum(Axis axis) const
114 {
115   if (axis == Axis::X3D) {
116     if (seriesType_ == Series3DType::Bar) {
117       return model_->rowCount() - 1 - 0.5;
118     }
119     if (YAbscisRow_ != model_->rowCount()) {
120       return Wt::asNumber(model_->data(model_->rowCount()-1, XAbscisColumn_));
121     } else {
122       return Wt::asNumber(model_->data(model_->rowCount()-2, XAbscisColumn_));
123     }
124   } else if (axis == Axis::Y3D) {
125     if (seriesType_ == Series3DType::Bar) {
126       return model_->columnCount() - 1 - 0.5;
127     }
128     if (XAbscisColumn_ != model_->columnCount()) {
129       return Wt::asNumber(model_->data(YAbscisRow_, model_->columnCount()-1));
130     } else {
131       return Wt::asNumber(model_->data(YAbscisRow_, model_->columnCount()-2));
132     }
133   } else if (axis == Axis::Z3D) {
134     if (!rangeCached_) {
135       findRange();
136     }
137     return zMax_;
138   } else {
139     throw WException("WAbstractGridData.C: unknown Axis-type");
140   }
141 }
142 
findRange()143 void WGridData::findRange() const
144 {
145   double minSoFar = std::numeric_limits<double>::max();
146   double maxSoFar = -std::numeric_limits<double>::max();
147 
148   double zVal;
149   int nbModelRows = model_->rowCount();
150   int nbModelCols = model_->columnCount();
151   for (int i=0; i<nbModelRows; i++) {
152     if (i == YAbscisRow_)
153       continue;
154     for (int j=0; j<nbModelCols; j++) {
155       if (j == XAbscisColumn_)
156 	continue;
157       zVal = Wt::asNumber(model_->data(i,j));
158       if (zVal < minSoFar) {
159 	minSoFar = zVal;
160       }
161       if (zVal > maxSoFar) {
162 	maxSoFar = zVal;
163       }
164     }
165   }
166 
167   zMin_ = minSoFar;
168   zMax_ = maxSoFar;
169   rangeCached_ = true;
170 }
171 
pointDataFromModel(FloatBuffer & simplePtsArray,FloatBuffer & simplePtsSize,FloatBuffer & coloredPtsArray,FloatBuffer & coloredPtsSize,FloatBuffer & coloredPtsColor)172 void WGridData::pointDataFromModel(FloatBuffer& simplePtsArray,
173 				   FloatBuffer& simplePtsSize,
174 				   FloatBuffer& coloredPtsArray,
175 				   FloatBuffer& coloredPtsSize,
176 				   FloatBuffer& coloredPtsColor) const {
177   int nbModelRows = model_->rowCount();
178   int nbModelCols = model_->columnCount();
179 
180   // scale the x- and y-axis to the plotbox
181   FloatBuffer scaledXAxis = Utils::createFloatBuffer(nbModelRows-1);
182   FloatBuffer scaledYAxis = Utils::createFloatBuffer(nbModelCols-1);
183 
184   double xMin = chart_->axis(Axis::X3D).minimum();
185   double xMax = chart_->axis(Axis::X3D).maximum();
186   double yMin = chart_->axis(Axis::Y3D).minimum();
187   double yMax = chart_->axis(Axis::Y3D).maximum();
188   double zMin = chart_->axis(Axis::Z3D).minimum();
189   double zMax = chart_->axis(Axis::Z3D).maximum();
190 
191   for (int i=0; i<nbModelRows; i++) {
192     if (i == YAbscisRow_)
193       continue;
194     scaledXAxis.push_back((float)((Wt::asNumber(model_->data(i,XAbscisColumn_))
195 				   - xMin)/(xMax - xMin)));
196   }
197   for (int j=0; j<nbModelCols; j++) {
198     if (j == XAbscisColumn_)
199       continue;
200     scaledYAxis.push_back((float)((Wt::asNumber(model_->data(YAbscisRow_,j))
201 				   - yMin)/(yMax - yMin)));
202   }
203 
204   int rowOffset = 0, colOffset = 0;
205   for (int i=0; i<nbModelRows; i++) {
206     if (i == YAbscisRow_) {
207       rowOffset = 1;
208       continue;
209     }
210     colOffset = 0;
211     for (int j=0; j<nbModelCols; j++) {
212       if (j == XAbscisColumn_) {
213 	colOffset = 1;
214 	continue;
215       }
216       if (!cpp17::any_has_value(model_->data(i,j,ItemDataRole::MarkerBrushColor))) {
217 	simplePtsArray.push_back(scaledXAxis[i-rowOffset]);
218 	simplePtsArray.push_back(scaledYAxis[j-colOffset]);
219 	simplePtsArray.push_back((float)((Wt::asNumber(model_->data(i,j,ItemDataRole::Display))-zMin)/(zMax-zMin)));
220 	if (cpp17::any_has_value(model_->data(i,j,ItemDataRole::MarkerScaleFactor))) {
221 	  simplePtsSize.push_back((float)(Wt::asNumber(model_->data(i,j,ItemDataRole::MarkerScaleFactor))));
222 	} else {
223 	  simplePtsSize.push_back((float)pointSize());
224 	}
225       } else {
226 	coloredPtsArray.push_back(scaledXAxis[i-rowOffset]);
227 	coloredPtsArray.push_back(scaledYAxis[j-colOffset]);
228 	coloredPtsArray.push_back((float)((Wt::asNumber(model_->data(i,j))-zMin)
229 					  /(zMax-zMin)));
230 	WColor color = cpp17::any_cast<WColor>(model_->data(i,j,ItemDataRole::MarkerBrushColor));
231 	coloredPtsColor.push_back((float)color.red());
232 	coloredPtsColor.push_back((float)color.green());
233 	coloredPtsColor.push_back((float)color.blue());
234 	coloredPtsColor.push_back((float)color.alpha());
235 
236 	if (cpp17::any_has_value(model_->data(i,j,ItemDataRole::MarkerScaleFactor))) {
237 	  coloredPtsSize.push_back
238 	    ((float)(Wt::asNumber
239 		     (model_->data(i,j, ItemDataRole::MarkerScaleFactor))));
240 	} else {
241 	  coloredPtsSize.push_back((float)pointSize());
242 	}
243       }
244     }
245   }
246 }
247 
surfaceDataFromModel(std::vector<FloatBuffer> & simplePtsArrays)248 void WGridData::surfaceDataFromModel(std::vector<FloatBuffer>& simplePtsArrays) const {
249   int nbModelRows = model_->rowCount();
250   int nbModelCols = model_->columnCount();
251 
252   // scale the x- and y-axis to the plotbox
253   FloatBuffer scaledXAxis = Utils::createFloatBuffer(nbModelRows-1);
254   FloatBuffer scaledYAxis = Utils::createFloatBuffer(nbModelCols-1);
255 
256   double xMin = chart_->axis(Axis::X3D).minimum();
257   double xMax = chart_->axis(Axis::X3D).maximum();
258   double yMin = chart_->axis(Axis::Y3D).minimum();
259   double yMax = chart_->axis(Axis::Y3D).maximum();
260   double zMin = chart_->axis(Axis::Z3D).minimum();
261   double zMax = chart_->axis(Axis::Z3D).maximum();
262 
263   for (int i=0; i<nbModelRows; i++) {
264     if (i == YAbscisRow_)
265       continue;
266     scaledXAxis.push_back((float)((Wt::asNumber(model_->data(i,XAbscisColumn_))
267 				   - xMin)/(xMax - xMin)));
268   }
269   for (int j=0; j<nbModelCols; j++) {
270     if (j == XAbscisColumn_)
271       continue;
272     scaledYAxis.push_back((float)((Wt::asNumber(model_->data(YAbscisRow_,j))
273 				   - yMin)/(yMax - yMin)));
274   }
275 
276   int nbXaxisBuffers = nbXPoints()/(SURFACE_SIDE_LIMIT-1);
277   int nbYaxisBuffers = nbYPoints()/(SURFACE_SIDE_LIMIT-1);
278   if (nbXPoints() % (SURFACE_SIDE_LIMIT-1) != 0) {
279     nbXaxisBuffers++;
280   }
281   if (nbYPoints() % (SURFACE_SIDE_LIMIT-1) != 0) {
282     nbYaxisBuffers++;
283   }
284   int SURFACE_SIDE_LIMIT = WGridData::SURFACE_SIDE_LIMIT - 1;
285   int rowOffset = 0, colOffset = 0;
286   int bufferIndex = 0;
287   for (int k=0; k < nbXaxisBuffers-1; k++) {
288     for (int l=0; l < nbYaxisBuffers-1; l++) {
289       bufferIndex = k*nbYaxisBuffers + l;
290       int cnt1 = 0;
291       int i = k*SURFACE_SIDE_LIMIT;
292       rowOffset = 0;
293       for (; i < (k+1)*SURFACE_SIDE_LIMIT + 1; i++) {
294 	if (i >= YAbscisRow_) {
295 	  rowOffset = 1;
296 	}
297 	int cnt2 = 0;
298 	int j = l*SURFACE_SIDE_LIMIT;
299 	colOffset = 0;
300 	for (; j < (l+1)*SURFACE_SIDE_LIMIT + 1; j++) {
301 	  if (j >= XAbscisColumn_) {
302 	    colOffset = 1;
303 	  }
304 	  simplePtsArrays[bufferIndex].push_back(scaledXAxis[i]);
305 	  simplePtsArrays[bufferIndex].push_back(scaledYAxis[j]);
306 	  simplePtsArrays[bufferIndex].push_back((float)((Wt::asNumber(model_->data(i+rowOffset,j+colOffset))-zMin)/(zMax-zMin)));
307 	  cnt2++;
308 	}
309 	cnt1++;
310       }
311     }
312     bufferIndex = k*nbYaxisBuffers + nbYaxisBuffers - 1;
313     int cnt1 = 0;
314     int i = k*SURFACE_SIDE_LIMIT;
315     rowOffset = 0;
316     for (; i < (k+1)*SURFACE_SIDE_LIMIT + 1; i++) {
317       if (i >= YAbscisRow_) {
318 	rowOffset = 1;
319       }
320       int j = (nbYaxisBuffers-1)*SURFACE_SIDE_LIMIT;
321       colOffset = 0;
322       for (; j < nbModelCols - 1; j++) {
323 	if (j >= XAbscisColumn_) {
324 	  colOffset = 1;
325 	}
326 	simplePtsArrays[bufferIndex].push_back(scaledXAxis[i]);
327 	simplePtsArrays[bufferIndex].push_back(scaledYAxis[j]);
328 	simplePtsArrays[bufferIndex].push_back((float)((Wt::asNumber(model_->data(i+rowOffset,j+colOffset))-zMin)/(zMax-zMin)));
329       }
330       cnt1++;
331     }
332   }
333   for (int l=0; l < nbYaxisBuffers-1; l++) {
334     bufferIndex = (nbXaxisBuffers-1)*nbYaxisBuffers + l;
335     int i = (nbXaxisBuffers-1)*SURFACE_SIDE_LIMIT;
336     rowOffset = 0;
337     for (; i < nbModelRows - 1; i++) {
338       if (i >= YAbscisRow_) {
339 	rowOffset = 1;
340       }
341       int cnt2 = 0;
342       int j = l*SURFACE_SIDE_LIMIT;
343       colOffset = 0;
344       for (; j < (l+1)*SURFACE_SIDE_LIMIT + 1; j++) {
345 	if (j >= XAbscisColumn_) {
346 	  colOffset = 1;
347 	}
348 	simplePtsArrays[bufferIndex].push_back(scaledXAxis[i]);
349 	simplePtsArrays[bufferIndex].push_back(scaledYAxis[j]);
350 	simplePtsArrays[bufferIndex].push_back((float)((Wt::asNumber(model_->data(i+rowOffset,j+colOffset))-zMin)/(zMax-zMin)));
351 	cnt2++;
352       }
353     }
354   }
355   bufferIndex = (nbXaxisBuffers-1)*nbYaxisBuffers + (nbYaxisBuffers-1);
356   int i = (nbXaxisBuffers-1)*SURFACE_SIDE_LIMIT;
357   rowOffset = 0;
358   for (; i < nbModelRows - 1; i++) {
359     if (i >= YAbscisRow_) {
360       rowOffset = 1;
361     }
362     int j = (nbYaxisBuffers-1)*SURFACE_SIDE_LIMIT;
363     colOffset = 0;
364     for (; j < nbModelCols - 1; j++) {
365       if (j >= XAbscisColumn_) {
366 	colOffset = 1;
367       }
368       simplePtsArrays[bufferIndex].push_back(scaledXAxis[i]);
369       simplePtsArrays[bufferIndex].push_back(scaledYAxis[j]);
370       simplePtsArrays[bufferIndex].push_back((float)((Wt::asNumber(model_->data(i+rowOffset,j+colOffset))-zMin)/(zMax-zMin)));
371     }
372   }
373 }
374 
barDataFromModel(std::vector<FloatBuffer> & simplePtsArrays)375 void WGridData::barDataFromModel(std::vector<FloatBuffer>& simplePtsArrays) const
376 {
377   // search for previously initialized barSeries data
378   const std::vector<WAbstractDataSeries3D*> dataseries = chart_->dataSeries();
379   std::vector<WAbstractGridData*> prevDataseries;
380   bool first = true;
381   int xDim = 0, yDim = 0;
382   for (unsigned i = 0; i < dataseries.size(); i++) {
383     if (dynamic_cast<WAbstractGridData*>(dataseries[i]) != nullptr) {
384       WAbstractGridData* griddata = dynamic_cast<WAbstractGridData*>(dataseries[i]);
385       if (griddata == this ||
386 	  griddata->type() != Series3DType::Bar) {
387 	break;
388       }
389       if (first) {
390 	xDim = griddata->nbXPoints();
391 	yDim = griddata->nbYPoints();
392 	first = false;
393       }
394       if ( griddata->nbXPoints() != xDim || griddata->nbYPoints() != yDim
395 	   || griddata->isHidden()) {
396 	continue;
397       }
398       prevDataseries.push_back( griddata );
399     }
400   }
401   if ( !prevDataseries.empty() &&
402        (xDim != nbXPoints() || yDim != nbYPoints()) ) {
403     throw WException("WGridData.C: Dimensions of multiple bar-series data do not match");
404   }
405 
406   // scale the x- and y-axis to the plotbox
407   int nbModelRows = model_->rowCount();
408   int nbModelCols = model_->columnCount();
409   FloatBuffer scaledXAxis = Utils::createFloatBuffer(nbModelRows-1);
410   FloatBuffer scaledYAxis = Utils::createFloatBuffer(nbModelCols-1);
411 
412   double xMin = chart_->axis(Axis::X3D).minimum();
413   double xMax = chart_->axis(Axis::X3D).maximum();
414   double yMin = chart_->axis(Axis::Y3D).minimum();
415   double yMax = chart_->axis(Axis::Y3D).maximum();
416   double zMin = chart_->axis(Axis::Z3D).minimum();
417   double zMax = chart_->axis(Axis::Z3D).maximum();
418 
419   for (int i=0; i<nbModelRows-1; i++) {
420     scaledXAxis.push_back((float)((xMin + 0.5 + i - xMin)/(xMax-xMin)));
421   }
422   for (int j=0; j<nbModelCols-1; j++) {
423     scaledYAxis.push_back((float)((yMin + 0.5 + j - yMin)/(yMax-yMin)));
424   }
425 
426   // fill the buffers
427   int rowOffset = 0, colOffset = 0;
428   int simpleBufferIndex = 0;
429   int simpleCount = 0;
430   for (int i=0; i < nbModelRows - 1; i++) {
431     if (i >= YAbscisRow_) {
432       rowOffset = 1;
433     }
434     colOffset = 0;
435     for (int j=0; j < nbModelCols - 1; j++) {
436       if (j >= XAbscisColumn_) {
437 	colOffset = 1;
438       }
439       float z0 = stackAllValues(prevDataseries, i,j);
440 
441       if (simpleCount == BAR_BUFFER_LIMIT) {
442 	simpleBufferIndex++;
443 	simpleCount = 0;
444       }
445       simplePtsArrays[simpleBufferIndex].push_back(scaledXAxis[i]);
446       simplePtsArrays[simpleBufferIndex].push_back(scaledYAxis[j]);
447       // first the value of all previous series stacked,then the current value
448       simplePtsArrays[simpleBufferIndex].push_back(z0);
449       double modelVal = Wt::asNumber(model_->data(i+rowOffset,j+colOffset));
450       float delta = (modelVal <= 0) ? zeroBarCompensation : 0;
451       simplePtsArrays[simpleBufferIndex].push_back((float)((modelVal-zMin)/(zMax-zMin))+delta);
452       simpleCount++;
453     }
454   }
455 }
456 
barDataFromModel(std::vector<FloatBuffer> & simplePtsArrays,std::vector<FloatBuffer> & coloredPtsArrays,std::vector<FloatBuffer> & coloredPtsColors)457 void WGridData::barDataFromModel(std::vector<FloatBuffer>& simplePtsArrays,
458 				 std::vector<FloatBuffer>& coloredPtsArrays,
459 				 std::vector<FloatBuffer>& coloredPtsColors) const
460 {
461   // search for previously initialized barSeries data
462   const std::vector<WAbstractDataSeries3D*> dataseries = chart_->dataSeries();
463   std::vector<WAbstractGridData*> prevDataseries;
464   bool first = true;
465   int xDim = 0, yDim = 0;
466   for (unsigned i = 0; i < dataseries.size(); i++) {
467     if ( dynamic_cast<WAbstractGridData*>(dataseries[i]) != 0) {
468       WAbstractGridData* griddata = dynamic_cast<WAbstractGridData*>(dataseries[i]);
469       if (griddata == this ||
470 	  griddata->type() != Series3DType::Bar) {
471 	break;
472       }
473       if (first) {
474 	xDim = griddata->nbXPoints();
475 	yDim = griddata->nbYPoints();
476 	first = false;
477       }
478       if ( griddata->nbXPoints() != xDim || griddata->nbYPoints() != yDim
479 	   || griddata->isHidden()) {
480 	continue;
481       }
482       prevDataseries.push_back( griddata );
483     }
484   }
485   if ( !prevDataseries.empty() &&
486        (xDim != nbXPoints() || yDim != nbYPoints()) ) {
487     throw WException("WGridData.C: Dimensions of multiple bar-series data do not match");
488   }
489 
490   // scale the x- and y-axis to the plotbox
491   int nbModelRows = model_->rowCount();
492   int nbModelCols = model_->columnCount();
493   FloatBuffer scaledXAxis = Utils::createFloatBuffer(nbModelRows-1);
494   FloatBuffer scaledYAxis = Utils::createFloatBuffer(nbModelCols-1);
495 
496   double xMin = chart_->axis(Axis::X3D).minimum();
497   double xMax = chart_->axis(Axis::X3D).maximum();
498   double yMin = chart_->axis(Axis::Y3D).minimum();
499   double yMax = chart_->axis(Axis::Y3D).maximum();
500   double zMin = chart_->axis(Axis::Z3D).minimum();
501   double zMax = chart_->axis(Axis::Z3D).maximum();
502 
503   for (int i=0; i<nbModelRows-1; i++) {
504     scaledXAxis.push_back((float)((xMin + 0.5 + i - xMin)/(xMax-xMin)));
505   }
506   for (int j=0; j<nbModelCols-1; j++) {
507     scaledYAxis.push_back((float)((yMin + 0.5 + j - yMin)/(yMax-yMin)));
508   }
509 
510   // fill the buffers
511   int rowOffset = 0, colOffset = 0;
512   int simpleBufferIndex = 0, coloredBufferIndex = 0;
513   int simpleCount = 0, coloredCount = 0;
514   for (int i=0; i < nbModelRows - 1; i++) {
515     if (i >= YAbscisRow_) {
516       rowOffset = 1;
517     }
518     colOffset = 0;
519     for (int j=0; j < nbModelCols - 1; j++) {
520       if (j >= XAbscisColumn_) {
521 	colOffset = 1;
522       }
523       float z0 = stackAllValues(prevDataseries, i,j);
524 
525       if (!cpp17::any_has_value(model_->data(i+rowOffset,j+colOffset,ItemDataRole::MarkerBrushColor))) {
526 	if (simpleCount == BAR_BUFFER_LIMIT) {
527 	  simpleBufferIndex++;
528 	  simpleCount = 0;
529 	}
530 	simplePtsArrays[simpleBufferIndex].push_back(scaledXAxis[i]);
531 	simplePtsArrays[simpleBufferIndex].push_back(scaledYAxis[j]);
532 	// first the value of all previous series stacked,then the current value
533 	simplePtsArrays[simpleBufferIndex].push_back(z0);
534 	double modelVal = Wt::asNumber(model_->data(i+rowOffset,j+colOffset));
535 	float delta = (modelVal <= 0) ? zeroBarCompensation : 0;
536 	simplePtsArrays[simpleBufferIndex].push_back((float)((modelVal-zMin)/(zMax-zMin))+delta);
537 	simpleCount++;
538       } else {
539 	if (coloredCount == BAR_BUFFER_LIMIT) {
540 	  coloredBufferIndex++;
541 	  coloredCount = 0;
542 	}
543 	coloredPtsArrays[coloredBufferIndex].push_back(scaledXAxis[i]);
544 	coloredPtsArrays[coloredBufferIndex].push_back(scaledYAxis[j]);
545 	coloredPtsArrays[coloredBufferIndex].push_back(z0);
546 	double modelVal = Wt::asNumber(model_->data(i+rowOffset,j+colOffset));
547 	float delta = (modelVal <= 0) ? zeroBarCompensation : 0;
548 	coloredPtsArrays[coloredBufferIndex].push_back((float)((modelVal-zMin)/(zMax-zMin))+delta);
549 
550 	WColor color = cpp17::any_cast<WColor>(model_->data(i+rowOffset,j+colOffset,ItemDataRole::MarkerBrushColor));
551 	for (int k=0; k < 8; k++) {
552 	  coloredPtsColors[coloredBufferIndex].push_back((float)color.red());
553 	  coloredPtsColors[coloredBufferIndex].push_back((float)color.green());
554 	  coloredPtsColors[coloredBufferIndex].push_back((float)color.blue());
555 	  coloredPtsColors[coloredBufferIndex].push_back((float)color.alpha());
556 	}
557 	coloredCount++;
558       }
559     }
560   }
561 }
562 
563 
564 
565   }
566 }
567