Remove useless declarations (Visual Warnings)
[scilab.git] / scilab / modules / graphic_objects / src / cpp / PolylineDecomposer.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2010 - DIGITEO - Pierre Lando
4  *  Copyright (C) 2011-2012 - DIGITEO - Manuel Juliachs
5  *
6  *  This file must be used under the terms of the CeCILL.
7  *  This source file is licensed as described in the file COPYING, which
8  *  you should have received as part of this distribution.  The terms
9  *  are also available at
10  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11  *
12  */
13
14 #include <iostream>
15
16 #include "DecompositionUtils.hxx"
17 #include "PolylineDecomposer.hxx"
18 #include "Triangulator.hxx"
19 #include "ColorComputer.hxx"
20
21 extern "C"
22 {
23 #include <math.h>
24 #include <string.h>
25
26 #include "getGraphicObjectProperty.h"
27 #include "graphicObjectProperties.h"
28 }
29
30 int PolylineDecomposer::getDataSize(char* id)
31 {
32     int nPoints = 0;
33     int *piNPoints = &nPoints;
34     int polylineStyle = 0;
35     int* piPolylineStyle = &polylineStyle;
36     int closed = 0;
37     int* piClosed = &closed;
38
39     getGraphicObjectProperty(id, __GO_POLYLINE_STYLE__, jni_int, (void**) &piPolylineStyle);
40     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_ELEMENTS__, jni_int, (void**) &piNPoints);
41     getGraphicObjectProperty(id, __GO_CLOSED__, jni_bool, (void**) &piClosed);
42
43     /* If 0 points, 0 elements */
44     if (nPoints == 0)
45     {
46         return 0;
47     }
48
49     /* Segments */
50     if (polylineStyle == 1)
51     {
52         return nPoints;
53     }
54     /* Staircase */
55     else if (polylineStyle == 2)
56     {
57         if (closed)
58         {
59             return 2*nPoints;
60         }
61         else
62         {
63             return (2*nPoints)-1;
64         }
65     }
66     /* Vertical segments plus segments */
67     else if (polylineStyle == 3)
68     {
69         return 2*nPoints;
70     }
71     /* Segments with arrow heads */
72     else if (polylineStyle == 4)
73     {
74         int nArrowVertices;
75         /* The numbers of arrow head vertices and indices are exactly the same */
76         nArrowVertices = PolylineDecomposer::getArrowTriangleIndicesSize(nPoints, closed);
77
78         return nPoints + nArrowVertices;
79     }
80     /* Filled patch  */
81     else if (polylineStyle == 5)
82     {
83         return nPoints;
84     }
85     /* Vertical bars plus segments */
86     else if (polylineStyle == 6)
87     {
88         return 5*nPoints;
89     }
90     /* Horizontal bars plus segments */
91     else if (polylineStyle == 7)
92     {
93         return 5*nPoints;
94     }
95     /* To be done: remaining styles */
96     else
97     {
98         return 0;
99     }
100
101 }
102
103 void PolylineDecomposer::fillVertices(char* id, float* buffer, int bufferLength, int elementsSize, int coordinateMask, double* scale, double* translation, int logMask)
104 {
105     double* t = NULL;
106     double* xshift = NULL;
107     double* yshift = NULL;
108     double* zshift = NULL;
109
110     int polylineStyle = 0;
111     int* piPolylineStyle = &polylineStyle;
112
113     int nPoints = 0;
114     int *piNPoints = &nPoints;
115
116     getGraphicObjectProperty(id, __GO_DATA_MODEL_COORDINATES__, jni_double_vector, (void**) &t);
117     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_ELEMENTS__, jni_int, (void**) &piNPoints);
118
119     getGraphicObjectProperty(id, __GO_DATA_MODEL_X_COORDINATES_SHIFT__, jni_double_vector, (void**) &xshift);
120     getGraphicObjectProperty(id, __GO_DATA_MODEL_Y_COORDINATES_SHIFT__, jni_double_vector, (void**) &yshift);
121     getGraphicObjectProperty(id, __GO_DATA_MODEL_Z_COORDINATES_SHIFT__, jni_double_vector, (void**) &zshift);
122
123     getGraphicObjectProperty(id, __GO_POLYLINE_STYLE__, jni_int, (void**) &piPolylineStyle);
124
125     if (polylineStyle == 1)
126     {
127         fillSegmentsDecompositionVertices(id, buffer, bufferLength, elementsSize, coordinateMask, scale, translation, logMask, t, nPoints, xshift, yshift, zshift);
128     }
129     else if (polylineStyle == 2)
130     {
131         fillStairDecompositionVertices(id, buffer, bufferLength, elementsSize, coordinateMask, scale, translation, logMask, t, nPoints, xshift, yshift, zshift);
132     }
133     else if (polylineStyle == 3)
134     {
135         fillVerticalLinesDecompositionVertices(id, buffer, bufferLength, elementsSize, coordinateMask, scale, translation, logMask, t, nPoints, xshift, yshift, zshift);
136     }
137     else if (polylineStyle == 4)
138     {
139         fillSegmentsDecompositionVertices(id, buffer, bufferLength, elementsSize, coordinateMask, scale, translation, logMask, t, nPoints, xshift, yshift, zshift);
140     }
141     else if (polylineStyle == 5)
142     {
143         fillSegmentsDecompositionVertices(id, buffer, bufferLength, elementsSize, coordinateMask, scale, translation, logMask, t, nPoints, xshift, yshift, zshift);
144     }
145     else if (polylineStyle == 6)
146     {
147         fillVerticalBarsDecompositionVertices(id, buffer, bufferLength, elementsSize, coordinateMask, scale, translation, logMask, t, nPoints, xshift, yshift, zshift);
148     }
149     else if (polylineStyle == 7)
150     {
151         fillHorizontalBarsDecompositionVertices(id, buffer, bufferLength, elementsSize, coordinateMask, scale, translation, logMask, t, nPoints, xshift, yshift, zshift);
152     }
153
154 }
155
156 void PolylineDecomposer::fillSegmentsDecompositionVertices(char* id, float* buffer, int bufferLength, int elementsSize, int coordinateMask, double* scale, double* translation,
157                                                            int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift)
158 {
159
160     int componentIndices[3];
161
162     // TODO Optimize ? (test if s = 1 and t = 0, coordinateMask = 0 ...)
163     for (int i = 0; i < nPoints; i++)
164     {
165         /* Offset of a polyline vertex */
166         int v0 = elementsSize*i;
167
168         componentIndices[0] = i;
169         componentIndices[1] = i;
170         componentIndices[2] = i;
171
172         getAndWriteVertexToBuffer(buffer, v0, coordinates, componentIndices, nPoints, elementsSize,
173                                   xshift, yshift, zshift, coordinateMask, scale, translation, logMask);
174     }
175
176 }
177
178 void PolylineDecomposer::getAndWriteVertexToBuffer(float* buffer, int offset, double* coordinates, int* vertexIndices, int nPoints, int elementsSize,
179                                                    double* xshift, double* yshift, double* zshift, int coordinateMask, double* scale, double* translation, int logMask)
180 {
181     double coordinate = 0.;
182
183     if (coordinateMask & 0x01)
184     {
185         coordinate = coordinates[vertexIndices[0]];
186
187         if (xshift != NULL)
188         {
189             coordinate += xshift[vertexIndices[0]];
190         }
191
192         if (logMask & 0x01)
193         {
194             coordinate = DecompositionUtils::getLog10Value(coordinate);
195         }
196
197         buffer[offset +0] = (float)(coordinate * scale[0] + translation[0]);
198     }
199
200     if (coordinateMask & 0x02)
201     {
202         coordinate = coordinates[vertexIndices[1] + nPoints];
203
204         if (yshift != NULL)
205         {
206             coordinate += yshift[vertexIndices[1]];
207         }
208
209         if (logMask & 0x02)
210         {
211             coordinate = DecompositionUtils::getLog10Value(coordinate);
212         }
213
214         buffer[offset +1] = (float)(coordinate * scale[1] + translation[1]);
215     }
216
217     if (coordinateMask & 0x04)
218     {
219         coordinate = coordinates[vertexIndices[2] + 2*nPoints];
220
221         if (zshift != NULL)
222         {
223             coordinate += zshift[vertexIndices[2]];
224         }
225
226         if (logMask & 0x04)
227         {
228             coordinate = DecompositionUtils::getLog10Value(coordinate);
229         }
230
231         buffer[offset +2] = (float)(coordinate * scale[2] + translation[2]);
232     }
233
234     if((elementsSize == 4) && (coordinateMask & 0x08))
235     {
236         buffer[offset +3] = 1.0;
237     }
238
239 }
240
241 void PolylineDecomposer::fillStairDecompositionVertices(char* id, float* buffer, int bufferLength, int elementsSize, int coordinateMask, double* scale, double* translation,
242                                                         int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift)
243 {
244     int closed = 0;
245     int* piClosed = &closed;
246
247     /* Offsets of the left and right vertices (respectively) */
248     int v0 = 0;
249     int v1 = 0;
250
251     int componentIndices[3];
252
253     if (nPoints == 0)
254     {
255         return;
256     }
257
258     getGraphicObjectProperty(id, __GO_CLOSED__, jni_bool, (void**) &piClosed);
259
260     for (int i = 0; i < nPoints-1; i++)
261     {
262         v0 = elementsSize*2*i;
263         v1 = elementsSize*(2*i+1);
264
265         componentIndices[0] = i;
266         componentIndices[1] = i;
267         componentIndices[2] = i;
268
269         getAndWriteVertexToBuffer(buffer, v0, coordinates, componentIndices, nPoints, elementsSize, xshift, yshift, zshift, coordinateMask, scale, translation, logMask);
270
271         componentIndices[0] = i+1;
272         componentIndices[1] = i;
273         componentIndices[2] = i;
274
275         /* To be optimized: the y and z components are fetched and transformed twice */
276         getAndWriteVertexToBuffer(buffer, v1, coordinates, componentIndices, nPoints, elementsSize, xshift, yshift, zshift, coordinateMask, scale, translation, logMask);
277     }
278
279     /* Last point */
280     v0 = elementsSize*2*(nPoints-1);
281
282     componentIndices[0] = nPoints-1;
283     componentIndices[1] = nPoints-1;
284     componentIndices[2] = nPoints-1;
285
286     getAndWriteVertexToBuffer(buffer, v0, coordinates, componentIndices, nPoints, elementsSize, xshift, yshift, zshift, coordinateMask, scale, translation, logMask);
287
288     /*
289      * One additional vertex if closed
290      * Its x-coordinate is equal to the one of the polyline's first point
291      * whereas its y and z coordinates are equal to those of the last point.
292      */
293     if (closed)
294     {
295         v0 = elementsSize*(2*nPoints-1);
296
297         componentIndices[0] = 0;
298         componentIndices[1] = nPoints-1;
299         componentIndices[2] = nPoints-1;
300
301         getAndWriteVertexToBuffer(buffer, v0, coordinates, componentIndices, nPoints, elementsSize, xshift, yshift, zshift, coordinateMask, scale, translation, logMask);
302     }
303
304 }
305
306 void PolylineDecomposer::fillVerticalLinesDecompositionVertices(char* id, float* buffer, int bufferLength, int elementsSize, int coordinateMask, double* scale, double* translation,
307                                                                 int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift)
308 {
309     for (int i = 0; i < nPoints; i++)
310     {
311         /* Offsets of the lower and upper vertices (respectively) */
312         int v0 = 0;
313         int v1 = 0;
314
315         /* Coordinates of the lower and upper vertices (respectively) */
316         double coord0 = 0.;
317         double coord1 = 0.;
318
319         v0 = elementsSize*2*i;
320         v1 = elementsSize*(2*i+1);
321
322         /* Lower and upper endpoints x coordinates */
323         if (coordinateMask & 0x01)
324         {
325             coord0 = coordinates[i];
326             coord1 = coordinates[i];
327
328             if (xshift != NULL)
329             {
330                 coord0 += xshift[i];
331                 coord1 += xshift[i];
332             }
333
334             if (logMask & 0x01)
335             {
336                 coord0 = DecompositionUtils::getLog10Value(coord0);
337                 coord1 = DecompositionUtils::getLog10Value(coord1);
338             }
339
340             buffer[v0 +0] = (float)(coord0 * scale[0] + translation[0]);
341             buffer[v1 +0] = (float)(coord1 * scale[0] + translation[0]);
342         }
343
344         /* Lower and upper endpoints y coordinates */
345         if (coordinateMask & 0x02)
346         {
347             coord0 = 0.0;
348             coord1 = coordinates[i + nPoints];
349
350             if (yshift != NULL)
351             {
352                 /*
353                  * Only the upper vertex's y coordinate is shifted,
354                  * the lower vertex's one remains unchanged.
355                  */
356                 coord1 += yshift[i];
357             }
358
359             if (logMask & 0x02)
360             {
361                 /* The lower endpoint's y coordinate is unchanged (it amounts to log10(1), which is 0) */
362                 coord1 = DecompositionUtils::getLog10Value(coord1);
363             }
364
365             buffer[v0 +1] = (float)(coord0 * scale[1] + translation[1]);
366             buffer[v1 +1] = (float)(coord1 * scale[1] + translation[1]);
367         }
368
369         /* Lower and upper endpoints z coordinates */
370         if (coordinateMask & 0x04)
371         {
372             coord0 = coordinates[2*nPoints+i];
373             coord1 = coordinates[2*nPoints+i];
374
375             if (zshift != NULL)
376             {
377                 coord0 += zshift[i];
378                 coord1 += zshift[i];
379             }
380
381             if (logMask & 0x04)
382             {
383                 coord0 = DecompositionUtils::getLog10Value(coord0);
384                 coord1 = DecompositionUtils::getLog10Value(coord1);
385             }
386
387             buffer[v0 +2] = (float)(coord0 * scale[2] + translation[2]);
388             buffer[v1 +2] = (float)(coord1 * scale[2] + translation[2]);
389         }
390
391         if((elementsSize == 4) && (coordinateMask & 0x08))
392         {
393             buffer[v0 +3] = 1.0;
394             buffer[v1 +3] = 1.0;
395         }
396
397     }
398
399 }
400
401 void PolylineDecomposer::writeBarVerticesToBuffer(float* buffer, int* offsets, int componentOffset, double* coordinates, double shift, int shiftUsed,
402                                                   double scale, double translation, int logUsed)
403 {
404     if (shiftUsed)
405     {
406         coordinates[0] += shift;
407         coordinates[1] += shift;
408         coordinates[2] += shift;
409         coordinates[3] += shift;
410
411         coordinates[4] += shift;
412     }
413
414     if (logUsed)
415     {
416         coordinates[0] = DecompositionUtils::getLog10Value(coordinates[0]);
417         coordinates[1] = DecompositionUtils::getLog10Value(coordinates[1]);
418         coordinates[2] = DecompositionUtils::getLog10Value(coordinates[2]);
419         coordinates[3] = DecompositionUtils::getLog10Value(coordinates[3]);
420
421         coordinates[4] = DecompositionUtils::getLog10Value(coordinates[4]);
422     }
423
424     buffer[offsets[0] +componentOffset] = (float)(coordinates[0] * scale + translation);
425     buffer[offsets[1] +componentOffset] = (float)(coordinates[1] * scale + translation);
426     buffer[offsets[2] +componentOffset] = (float)(coordinates[2] * scale + translation);
427     buffer[offsets[3] +componentOffset] = (float)(coordinates[3] * scale + translation);
428
429     buffer[offsets[4] +componentOffset] = (float)(coordinates[4] * scale + translation);
430 }
431
432 void PolylineDecomposer::fillVerticalBarsDecompositionVertices(char* id, float* buffer, int bufferLength, int elementsSize, int coordinateMask, double* scale, double* translation,
433                                                                int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift)
434 {
435     double barWidth = 0.0;
436     double* pdBarWidth = &barWidth;
437
438     int shiftUsed[3];
439     int *piShiftUsed = NULL;
440
441     /*
442      * Offsets of the lower-left, lower-right, upper-right and upper-left bar vertices (respectively)
443      * and of the polyline vertex proper
444      */
445     int offsets[5];
446
447     /*
448      * {x,y or z}-component values of a bar's 4 vertices (same ordering as the offsets)
449      * and of the polyline vertex proper.
450      */
451     double coords[5];
452
453     double shift = 0.;
454
455
456     getGraphicObjectProperty(id, __GO_BAR_WIDTH__, jni_double, (void**) &pdBarWidth);
457
458     piShiftUsed = &shiftUsed[0];
459     getGraphicObjectProperty(id, __GO_DATA_MODEL_X_COORDINATES_SHIFT_SET__, jni_double_vector, (void**) &piShiftUsed);
460     piShiftUsed = &shiftUsed[1];
461     getGraphicObjectProperty(id, __GO_DATA_MODEL_Y_COORDINATES_SHIFT_SET__, jni_double_vector, (void**) &piShiftUsed);
462     piShiftUsed = &shiftUsed[2];
463     getGraphicObjectProperty(id, __GO_DATA_MODEL_Z_COORDINATES_SHIFT_SET__, jni_double_vector, (void**) &piShiftUsed);
464
465
466     for (int i = 0; i < nPoints; i++)
467     {
468         offsets[0] = elementsSize*4*i;
469         offsets[1] = elementsSize*(4*i+1);
470         offsets[2] = elementsSize*(4*i+2);
471         offsets[3] = elementsSize*(4*i+3);
472
473         offsets[4] = elementsSize*(4*nPoints+i);
474
475         if (coordinateMask & 0x01)
476         {
477             coords[0] = coordinates[i] - 0.5*barWidth;
478             coords[1] = coordinates[i] + 0.5*barWidth;
479             coords[2] = coordinates[i] + 0.5*barWidth;
480             coords[3] = coordinates[i] - 0.5*barWidth;
481
482             coords[4] = coordinates[i];
483
484             if (shiftUsed[0])
485             {
486                 shift = xshift[i];
487             }
488
489             writeBarVerticesToBuffer(buffer, offsets, 0, coords, shift, shiftUsed[0], scale[0], translation[0], logMask & 0x01);
490         }
491
492         if (coordinateMask & 0x02)
493         {
494             coords[0] = 0.0;
495             coords[1] = 0.0;
496             coords[2] = coordinates[i + nPoints];
497             coords[3] = coordinates[i + nPoints];
498
499             coords[4] = coordinates[i + nPoints];
500
501             if (shiftUsed[1])
502             {
503                 shift = yshift[i];
504             }
505
506             if (logMask & 0x02)
507             {
508                 /*
509                  * The two lower endpoints' y coordinates must be set to 1
510                  * since writeBarVerticesToBuffer applies the logarithmic transformation.
511                  */
512                 coords[0] = 1.0;
513                 coords[1] = 1.0;
514             }
515
516             writeBarVerticesToBuffer(buffer, offsets, 1, coords, shift, shiftUsed[1], scale[1], translation[1], logMask & 0x02);
517         }
518
519         if (coordinateMask & 0x04)
520         {
521             coords[0] = coordinates[i + 2 * nPoints];
522             coords[1] = coordinates[i + 2 * nPoints];
523             coords[2] = coordinates[i + 2 * nPoints];
524             coords[3] = coordinates[i + 2 * nPoints];
525
526             coords[4] = coordinates[i + 2* nPoints];
527
528             if (shiftUsed[2])
529             {
530                 shift = zshift[i];
531             }
532
533             writeBarVerticesToBuffer(buffer, offsets, 2, coords, shift, shiftUsed[2], scale[2], translation[2], logMask & 0x04);
534         }
535
536         if((elementsSize == 4) && (coordinateMask & 0x08))
537         {
538             buffer[offsets[0] +3] = 1.0;
539             buffer[offsets[1] +3] = 1.0;
540             buffer[offsets[2] +3] = 1.0;
541             buffer[offsets[3] +3] = 1.0;
542
543             buffer[offsets[4] +3] = 1.0;
544         }
545
546     }
547
548 }
549
550 /*
551  * To do: -refactor with fillVerticalBarsDecompositionVertices as these two functions are very similar, possibly by implementing
552  a PolylineBarDecomposer class.
553 */
554 void PolylineDecomposer::fillHorizontalBarsDecompositionVertices(char* id, float* buffer, int bufferLength, int elementsSize, int coordinateMask, double* scale, double* translation,
555                                                                  int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift)
556 {
557     double barWidth = 0.0;
558     double* pdBarWidth = &barWidth;
559
560     int shiftUsed[3];
561     int *piShiftUsed = NULL;
562
563     /*
564      * Offsets of the lower-left, lower-right, upper-right and upper-left bar vertices (respectively)
565      * and of the polyline vertex proper
566      */
567     int offsets[5];
568
569     /*
570      * {x,y or z}-component values of a bar's 4 vertices (same ordering as the offsets)
571      * and of the polyline vertex proper.
572      */
573     double coords[5];
574
575     double shift = 0.;
576
577
578     getGraphicObjectProperty(id, __GO_BAR_WIDTH__, jni_double, (void**) &pdBarWidth);
579
580     piShiftUsed = &shiftUsed[0];
581     getGraphicObjectProperty(id, __GO_DATA_MODEL_X_COORDINATES_SHIFT_SET__, jni_double_vector, (void**) &piShiftUsed);
582     piShiftUsed = &shiftUsed[1];
583     getGraphicObjectProperty(id, __GO_DATA_MODEL_Y_COORDINATES_SHIFT_SET__, jni_double_vector, (void**) &piShiftUsed);
584     piShiftUsed = &shiftUsed[2];
585     getGraphicObjectProperty(id, __GO_DATA_MODEL_Z_COORDINATES_SHIFT_SET__, jni_double_vector, (void**) &piShiftUsed);
586
587     for (int i = 0; i < nPoints; i++)
588     {
589         offsets[0] = elementsSize*4*i;
590         offsets[1] = elementsSize*(4*i+1);
591         offsets[2] = elementsSize*(4*i+2);
592         offsets[3] = elementsSize*(4*i+3);
593
594         offsets[4] = elementsSize*(4*nPoints+i);
595
596         /* The actual x coordinates correspond to the polyline's y coordinates. */
597         if (coordinateMask & 0x01)
598         {
599             coords[0] = 0.0;
600             coords[1] = 0.0;
601             coords[2] = coordinates[i + nPoints];
602             coords[3] = coordinates[i + nPoints];
603
604             coords[4] = coordinates[i];
605
606             if (shiftUsed[1])
607             {
608                 shift = yshift[i];
609             }
610
611             writeBarVerticesToBuffer(buffer, offsets, 0, coords, shift, shiftUsed[1], scale[0], translation[0], logMask & 0x01);
612         }
613
614         /* The actual y coordinates correspond to the polyline's x coordinates. */
615         if (coordinateMask & 0x02)
616         {
617             coords[0] = coordinates[i] - 0.5*barWidth;
618             coords[1] = coordinates[i] + 0.5*barWidth;
619             coords[2] = coordinates[i] + 0.5*barWidth;
620             coords[3] = coordinates[i] - 0.5*barWidth;
621
622             coords[4] = coordinates[i + nPoints];
623
624             if (shiftUsed[0])
625             {
626                 shift = xshift[i];
627             }
628
629             if (logMask & 0x02)
630             {
631                 /*
632                  * The two lower endpoints' y coordinates must be set to 1
633                  * since writeBarVerticesToBuffer applies the logarithmic transformation.
634                  */
635                 coords[0] = 1.0;
636                 coords[1] = 1.0;
637             }
638
639             writeBarVerticesToBuffer(buffer, offsets, 1, coords, shift, shiftUsed[0], scale[1], translation[1], logMask & 0x02);
640         }
641
642         if (coordinateMask & 0x04)
643         {
644             coords[0] = coordinates[i + 2 * nPoints];
645             coords[1] = coordinates[i + 2 * nPoints];
646             coords[2] = coordinates[i + 2 * nPoints];
647             coords[3] = coordinates[i + 2 * nPoints];
648
649             coords[4] = coordinates[i + 2* nPoints];
650
651             if (shiftUsed[2])
652             {
653                 shift = zshift[i];
654             }
655
656             writeBarVerticesToBuffer(buffer, offsets, 2, coords, shift, shiftUsed[2], scale[2], translation[2], logMask & 0x04);
657         }
658
659         if((elementsSize == 4) && (coordinateMask & 0x08))
660         {
661             buffer[offsets[0] +3] = 1.0;
662             buffer[offsets[1] +3] = 1.0;
663             buffer[offsets[2] +3] = 1.0;
664             buffer[offsets[3] +3] = 1.0;
665
666             buffer[offsets[4] +3] = 1.0;
667         }
668
669     }
670
671 }
672
673 /*
674  * To do:
675  *  -implement for the other relevant polyline style values.
676  *  -fix the no colors written problem (related to polyline C build functions, see below).
677  */
678 void PolylineDecomposer::fillColors(char* id, float* buffer, int bufferLength, int elementsSize)
679 {
680     char* parent = NULL;
681     char* parentFigure = NULL;
682
683     int interpColorMode = 0;
684     int* piInterpColorMode = &interpColorMode;
685     int polylineStyle = 0;
686     int* piPolylineStyle = &polylineStyle;
687     int nPoints = 0;
688     int *piNPoints = &nPoints;
689     int colormapSize = 0;
690     int* piColormapSize = &colormapSize;
691     int bufferOffset = 0;
692     int* interpColorVector = NULL;
693
694     double* colormap = NULL;
695
696     getGraphicObjectProperty(id, __GO_INTERP_COLOR_MODE__, jni_bool, (void**) &piInterpColorMode);
697
698     if (interpColorMode == 0)
699     {
700         return;
701     }
702
703     getGraphicObjectProperty(id, __GO_POLYLINE_STYLE__, jni_int, (void**) &piPolylineStyle);
704
705     if (polylineStyle  != 1)
706     {
707         return;
708     }
709
710     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_ELEMENTS__, jni_int, (void**) &piNPoints);
711     getGraphicObjectProperty(id, __GO_PARENT__, jni_string, (void**) &parent);
712
713     /* Temporary: to avoid getting a null parent_figure property when the object is built */
714     if (strcmp(parent, "") == 0)
715     {
716         return;
717     }
718
719     getGraphicObjectProperty(id, __GO_PARENT_FIGURE__, jni_string, (void**) &parentFigure);
720
721     /*
722      * In some cases, the polyline's parent figure may be unitialized, when this point is reached from the
723      * filled polygons build C functions (xfpolys, with several polygons and a color vector for each one).
724      * This check prevents from crashing when getting the colormap. However, it results in incorrectly
725      * black-filled polygons, as no colors are written.
726      * As the sequentially built polygons are inserted within a Compound object, the latter object may be
727      * still unattached to a Figure as its Polyline children are rendered. This occurs about once in 5 to 10,
728      * hence possibly caused by a race condition.
729      * To be fixed.
730      */
731     if (strcmp(parentFigure, "") == 0)
732     {
733         return;
734     }
735
736     /*
737      * The interpolated color vector is a 3- or 4-element vector.
738      * However, if nPoints is greater than 4, we choose to output
739      * 4 colors (this behaviour is kept for compatibility, see fillTriangleIndices).
740      */
741     if (nPoints < 3)
742     {
743         return;
744     }
745
746     getGraphicObjectProperty(id, __GO_INTERP_COLOR_VECTOR__, jni_int_vector, (void**) &interpColorVector);
747     getGraphicObjectProperty(parentFigure, __GO_COLORMAP__, jni_double_vector, (void**) &colormap);
748     getGraphicObjectProperty(parentFigure, __GO_COLORMAP_SIZE__, jni_int, (void**) &piColormapSize);
749
750     if (nPoints > 4)
751     {
752         nPoints = 4;
753     }
754
755     for (int i = 0; i < nPoints; i++)
756     {
757         ColorComputer::getDirectColor((double) interpColorVector[i] - 1.0, colormap, colormapSize, &buffer[bufferOffset]);
758
759         if (elementsSize == 4)
760         {
761             buffer[bufferOffset+3] = 1.0;
762         }
763
764         bufferOffset += elementsSize;
765     }
766
767     releaseGraphicObjectProperty(__GO_COLORMAP__, colormap, jni_double_vector, colormapSize);
768     releaseGraphicObjectProperty(__GO_INTERP_COLOR_VECTOR__, interpColorVector, jni_int_vector, 0);
769 }
770
771 void PolylineDecomposer::fillTextureCoordinates(char* id, float* buffer, int bufferLength)
772 {
773     char* parent = NULL;
774     char* parentFigure = NULL;
775
776     int interpColorMode = 0;
777     int* piInterpColorMode = &interpColorMode;
778     int polylineStyle = 0;
779     int* piPolylineStyle = &polylineStyle;
780     int nPoints = 0;
781     int *piNPoints = &nPoints;
782     int colormapSize = 0;
783     int* piColormapSize = &colormapSize;
784     int bufferOffset = 0;
785     int* interpColorVector = NULL;
786
787     double* colormap = NULL;
788
789     getGraphicObjectProperty(id, __GO_INTERP_COLOR_MODE__, jni_bool, (void**) &piInterpColorMode);
790
791     if (interpColorMode == 0)
792     {
793         return;
794     }
795
796     getGraphicObjectProperty(id, __GO_POLYLINE_STYLE__, jni_int, (void**) &piPolylineStyle);
797
798     if (polylineStyle  != 1)
799     {
800         return;
801     }
802
803     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_ELEMENTS__, jni_int, (void**) &piNPoints);
804     getGraphicObjectProperty(id, __GO_PARENT__, jni_string, (void**) &parent);
805
806     /* Temporary: to avoid getting a null parent_figure property when the object is built */
807     if (strcmp(parent, "") == 0)
808     {
809         return;
810     }
811
812     getGraphicObjectProperty(id, __GO_PARENT_FIGURE__, jni_string, (void**) &parentFigure);
813
814     /*
815      * In some cases, the polyline's parent figure may be unitialized, when this point is reached from the
816      * filled polygons build C functions (xfpolys, with several polygons and a color vector for each one).
817      * This check prevents from crashing when getting the colormap. However, it results in incorrectly
818      * black-filled polygons, as no colors are written.
819      * As the sequentially built polygons are inserted within a Compound object, the latter object may be
820      * still unattached to a Figure as its Polyline children are rendered. This occurs about once in 5 to 10,
821      * hence possibly caused by a race condition.
822      * To be fixed.
823      */
824     if (strcmp(parentFigure, "") == 0)
825     {
826         return;
827     }
828
829     /*
830      * The interpolated color vector is a 3- or 4-element vector.
831      * However, if nPoints is greater than 4, we choose to output
832      * 4 colors (this behaviour is kept for compatibility, see fillTriangleIndices).
833      */
834     if (nPoints < 3)
835     {
836         return;
837     }
838
839     getGraphicObjectProperty(id, __GO_INTERP_COLOR_VECTOR__, jni_int_vector, (void**) &interpColorVector);
840     getGraphicObjectProperty(parentFigure, __GO_COLORMAP__, jni_double_vector, (void**) &colormap);
841     getGraphicObjectProperty(parentFigure, __GO_COLORMAP_SIZE__, jni_int, (void**) &piColormapSize);
842
843     if (nPoints > 4)
844     {
845         nPoints = 4;
846     }
847
848     for (int i = 0; i < nPoints; i++)
849     {
850         double index = (ColorComputer::getDirectIndex((double) interpColorVector[i] - 1.0, colormapSize) + 2.0 + COLOR_TEXTURE_OFFSET) / (double) (colormapSize + 2);
851
852         buffer[bufferOffset] = (float)index;
853         buffer[bufferOffset+1] = 0.0;
854         buffer[bufferOffset+2] = 0.0;
855         buffer[bufferOffset+3] = 1.0;
856
857         bufferOffset += 4;
858     }
859
860     releaseGraphicObjectProperty(__GO_COLORMAP__, colormap, jni_double_vector, colormapSize);
861     releaseGraphicObjectProperty(__GO_INTERP_COLOR_VECTOR__, interpColorVector, jni_int_vector, 0);
862 }
863
864 /*
865  * To do: see fillIndices
866  * -take into account polyline_style.
867  */
868 int PolylineDecomposer::getIndicesSize(char* id)
869 {
870     int nPoints = 0;
871     int *piNPoints = &nPoints;
872     int polylineStyle = 0;
873     int* piPolylineStyle = &polylineStyle;
874     int closed = 0;
875     int* piClosed = &closed;
876
877     int nIndices = 0;
878
879     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_ELEMENTS__, jni_int, (void**) &piNPoints);
880     getGraphicObjectProperty(id, __GO_POLYLINE_STYLE__, jni_int, (void**) &piPolylineStyle);
881     getGraphicObjectProperty(id, __GO_CLOSED__, jni_bool, (void**) &piClosed);
882
883     /* No facets if 0 points */
884     if (nPoints == 0)
885     {
886         return 0;
887     }
888
889     /* Segments */
890     if (polylineStyle == 1)
891     {
892         if (nPoints < 3)
893         {
894             return 0;
895         }
896
897         /* Maximum number of triangles output by the triangulator */
898         nIndices = 3*(nPoints-2);
899     }
900     /* Arrowed segments */
901     else if (polylineStyle == 4)
902     {
903         nIndices = PolylineDecomposer::getArrowTriangleIndicesSize(nPoints, closed);
904     }
905     /* Filled patch  */
906     else if (polylineStyle == 5)
907     {
908         if (nPoints < 3)
909         {
910             return 0;
911         }
912
913         /* Maximum number of triangles output by the triangulator */
914         nIndices = 3*(nPoints-2);
915     }
916     /* Vertical bars plus segments */
917     else if (polylineStyle == 6)
918     {
919         nIndices = PolylineDecomposer::getBarsDecompositionTriangleIndicesSize(nPoints);
920     }
921     /* Horizontal bars plus segments */
922     else if (polylineStyle == 7)
923     {
924         nIndices = PolylineDecomposer::getBarsDecompositionTriangleIndicesSize(nPoints);
925     }
926
927     return nIndices;
928 }
929
930 int PolylineDecomposer::getArrowTriangleIndicesSize(int nPoints, int closed)
931 {
932     int nIndices = 0;
933
934     if (nPoints < 2)
935     {
936         nIndices = 0;
937     }
938     else
939     {
940         nIndices = 3*(nPoints-1);
941
942         if (closed)
943         {
944             nIndices += 3;
945         }
946     }
947
948     return nIndices;
949 }
950
951 int PolylineDecomposer::getBarsDecompositionTriangleIndicesSize(int nPoints)
952 {
953     return 2*3*nPoints;
954 }
955
956 /*
957  * To do:
958  * -take into account the polyline style property (note: vertical bars -style 6- are filled
959  *  whatever fill_mode's value), by implementing the relevant functions (see fillTriangleIndices),
960  *  as the curve must be filled if fill_mode set to on, whatever its polyline style value.
961  */
962 int PolylineDecomposer::fillIndices(char* id, int* buffer, int bufferLength, int logMask)
963 {
964     double* coordinates = NULL;
965     double* xshift = NULL;
966     double* yshift = NULL;
967     double* zshift = NULL;
968
969     int nPoints = 0;
970     int* piNPoints = &nPoints;
971     int polylineStyle = 0;
972     int* piPolylineStyle = &polylineStyle;
973     int fillMode = 0;
974     int* piFillMode = &fillMode;
975
976     getGraphicObjectProperty(id, __GO_DATA_MODEL_COORDINATES__, jni_double_vector, (void**) &coordinates);
977     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_ELEMENTS__, jni_int, (void**) &piNPoints);
978     getGraphicObjectProperty(id, __GO_POLYLINE_STYLE__, jni_int, (void**) &piPolylineStyle);
979     getGraphicObjectProperty(id, __GO_DATA_MODEL_X_COORDINATES_SHIFT__, jni_double_vector, (void**) &xshift);
980     getGraphicObjectProperty(id, __GO_DATA_MODEL_Y_COORDINATES_SHIFT__, jni_double_vector, (void**) &yshift);
981     getGraphicObjectProperty(id, __GO_DATA_MODEL_Z_COORDINATES_SHIFT__, jni_double_vector, (void**) &zshift);
982
983     getGraphicObjectProperty(id, __GO_FILL_MODE__, jni_bool, (void**) &piFillMode);
984
985     /* 0 triangles if 0 points */
986     if (nPoints == 0)
987     {
988         return 0;
989     }
990
991     if (polylineStyle == 1)
992     {
993         return fillTriangleIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, fillMode, polylineStyle);
994     }
995     else if (polylineStyle == 4)
996     {
997         return fillArrowTriangleIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift);
998     }
999     else if (polylineStyle == 5)
1000     {
1001         /* Set fill mode to on, since patches are always filled whatever fill mode's value */
1002         return fillTriangleIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, 1, polylineStyle);
1003     }
1004     else if (polylineStyle == 6)
1005     {
1006         return fillBarsDecompositionTriangleIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift);
1007     }
1008     else if (polylineStyle == 7)
1009     {
1010         return fillBarsDecompositionTriangleIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift);
1011     }
1012
1013     return 0;
1014 }
1015
1016 int PolylineDecomposer::fillTriangleIndices(char* id, int* buffer, int bufferLength,
1017                                             int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift, int fillMode, int polylineStyle)
1018 {
1019     double coords[4][3];
1020
1021     int interpColorMode = 0;
1022     int* piInterpColorMode = &interpColorMode;
1023     int triangulate = 0;
1024
1025     int isValid = 0;
1026     int tmpValid = 0;
1027     int nIndices = 0;
1028
1029     /* At least 3 points needed */
1030     if (nPoints < 3)
1031     {
1032         return 0;
1033     }
1034
1035     if (fillMode == 0)
1036     {
1037         return 0;
1038     }
1039
1040     getGraphicObjectProperty(id, __GO_INTERP_COLOR_MODE__, jni_bool, (void**) &piInterpColorMode);
1041
1042     /*
1043      * Do not triangulate if the interpolated color mode is set to 'on' and the polyline style is filled patch (5).
1044      * The quadrilateral facet decomposition function is used instead, if nPoints == 4,
1045      * for compatibility reasons, although triangulation could be used.
1046      */
1047     if (interpColorMode && polylineStyle != 5)
1048     {
1049         triangulate = 0;
1050     }
1051     else if (nPoints > 3)
1052     {
1053         /* Perform triangulation only if more than 3 points */
1054         triangulate = 1;
1055     }
1056
1057     if (triangulate)
1058     {
1059         Triangulator triangulator;
1060         int numTriangles;
1061         int* indices;
1062
1063         isValid = 1;
1064
1065         for (int i = 0; i < nPoints; i++)
1066         {
1067             getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, i, &coords[0][0], &coords[0][1], &coords[0][2]);
1068
1069             tmpValid = DecompositionUtils::isValid(coords[0][0], coords[0][1], coords[0][2]);
1070
1071             if (logMask)
1072             {
1073                 tmpValid &= DecompositionUtils::isLogValid(coords[0][0], coords[0][1], coords[0][2], logMask);
1074
1075                 if (logMask & 0x01)
1076                 {
1077                     coords[0][0] = DecompositionUtils::getLog10Value(coords[0][0]);
1078                 }
1079
1080                 if (logMask & 0x02)
1081                 {
1082                     coords[0][1] = DecompositionUtils::getLog10Value(coords[0][1]);
1083                 }
1084
1085                 if (logMask & 0x04)
1086                 {
1087                     coords[0][2] = DecompositionUtils::getLog10Value(coords[0][2]);
1088                 }
1089             }
1090
1091             isValid &= tmpValid;
1092
1093             if (!isValid)
1094             {
1095                 break;
1096             }
1097
1098             triangulator.addPoint(coords[0][0], coords[0][1], coords[0][2]);
1099         }
1100
1101         if (!isValid)
1102         {
1103             return 0;
1104         }
1105
1106         /* Triangulate */
1107         triangulator.initialize();
1108         triangulator.triangulate();
1109
1110         numTriangles = triangulator.getNumberTriangles();
1111         indices = triangulator.getIndices();
1112
1113         for (int i = 0; i < numTriangles; i++)
1114         {
1115             buffer[3*i] = indices[3*i];
1116             buffer[3*i+1] = indices[3*i+1];
1117             buffer[3*i+2] = indices[3*i+2];
1118             nIndices += 3;
1119         }
1120
1121         triangulator.clear();
1122
1123         return nIndices;
1124     }
1125     else
1126     {
1127         /* Do not triangulate: either the interpolation color mode is set to on or it is not and there are only 3 points. */
1128
1129         /* 3 points: only one triangle output */
1130         if (nPoints == 3)
1131         {
1132             getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 0, &coords[0][0], &coords[0][1], &coords[0][2]);
1133             getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 1, &coords[1][0], &coords[1][1], &coords[1][2]);
1134             getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 2, &coords[2][0], &coords[2][1], &coords[2][2]);
1135
1136             tmpValid = DecompositionUtils::isValid(coords[0][0], coords[0][1], coords[0][2]);
1137             tmpValid &= DecompositionUtils::isValid(coords[1][0], coords[1][1], coords[1][2]);
1138             tmpValid &= DecompositionUtils::isValid(coords[2][0], coords[2][1], coords[2][2]);
1139
1140             isValid = tmpValid;
1141
1142             if (logMask)
1143             {
1144                 tmpValid = DecompositionUtils::isLogValid(coords[0][0], coords[0][1], coords[0][2], logMask);
1145                 tmpValid &= DecompositionUtils::isLogValid(coords[1][0], coords[1][1], coords[1][2], logMask);
1146                 tmpValid &= DecompositionUtils::isLogValid(coords[2][0], coords[2][1], coords[2][2], logMask);
1147                 isValid &= tmpValid;
1148             }
1149
1150             if (isValid)
1151             {
1152                 buffer[0] = 0;
1153                 buffer[1] = 1;
1154                 buffer[2] = 2;
1155
1156                 nIndices += 3;
1157             }
1158         }
1159         else if (nPoints >= 4)
1160         {
1161             /*
1162              * 4 points: the quadrilateral facet decomposition algorithm is used.
1163              * If the Polyline has more than 4 points, we still output two triangles
1164              * corresponding to the first 4 points. This behaviour is kept for compatibility.
1165              * Possible correction: do not output indices if there are more than 4 points and
1166              * the interpolation color mode is set to on.
1167              */
1168             int facetVertexIndices[4] = {0, 1, 2, 3};
1169
1170             getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 0, &coords[0][0], &coords[0][1], &coords[0][2]);
1171             getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 1, &coords[1][0], &coords[1][1], &coords[1][2]);
1172             getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 2, &coords[2][0], &coords[2][1], &coords[2][2]);
1173             getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 3, &coords[3][0], &coords[3][1], &coords[3][2]);
1174
1175             tmpValid = DecompositionUtils::isValid(coords[0][0], coords[0][1], coords[0][2]);
1176             tmpValid &= DecompositionUtils::isValid(coords[1][0], coords[1][1], coords[1][2]);
1177             tmpValid &= DecompositionUtils::isValid(coords[2][0], coords[2][1], coords[2][2]);
1178             tmpValid &= DecompositionUtils::isValid(coords[3][0], coords[3][1], coords[3][2]);
1179
1180             isValid = tmpValid;
1181
1182             if (logMask)
1183             {
1184                 tmpValid = DecompositionUtils::isLogValid(coords[0][0], coords[0][1], coords[0][2], logMask);
1185                 tmpValid &= DecompositionUtils::isLogValid(coords[1][0], coords[1][1], coords[1][2], logMask);
1186                 tmpValid &= DecompositionUtils::isLogValid(coords[2][0], coords[2][1], coords[2][2], logMask);
1187                 tmpValid &= DecompositionUtils::isLogValid(coords[3][0], coords[3][1], coords[3][2], logMask);
1188                 isValid &= tmpValid;
1189             }
1190
1191             if (isValid)
1192             {
1193                 DecompositionUtils::getDecomposedQuadTriangleIndices(coords, facetVertexIndices, buffer);
1194                 nIndices += 6;
1195             }
1196         }
1197
1198     }
1199
1200     return nIndices;
1201 }
1202
1203 int PolylineDecomposer::fillArrowTriangleIndices(char* id, int* buffer, int bufferLength,
1204                                                  int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift)
1205 {
1206     int closed = 0;
1207     int* piClosed = &closed;
1208
1209     int currentValid = 0;
1210     int nextValid = 0;
1211
1212     int firstArrowVertex = 0;
1213     int nArrows = 0;
1214
1215     int offset = 0;
1216     int numberValidIndices = 0;
1217
1218     /* At least 2 points needed to form segments */
1219     if (nPoints < 2)
1220     {
1221         return 0;
1222     }
1223
1224     getGraphicObjectProperty(id, __GO_CLOSED__, jni_bool, (void**) &piClosed);
1225
1226     /* If closed, an additional segment is present */
1227     if (closed)
1228     {
1229         nArrows = nPoints;
1230     }
1231     else
1232     {
1233         nArrows = nPoints-1;
1234     }
1235
1236     /*
1237      * Arrow head vertices are stored consecutively after all the line vertices.
1238      * Hence the offset to the first arrow vertex.
1239      */
1240     firstArrowVertex = nPoints;
1241
1242     for (int i = 0; i < nArrows; i++)
1243     {
1244         /* Indices of the tip, left and right vertices */
1245         int n = 3 * i;
1246         buffer[n] = firstArrowVertex + n;
1247         buffer[n + 1] = buffer[n] + 1;
1248         buffer[n + 2] = buffer[n] + 2;
1249     }
1250
1251     return 3 * nArrows;
1252 }
1253
1254 /*
1255  * Only bars are filled at the present moment, the curve is not.
1256  * See fillTriangleIndices for more information.
1257  */
1258 int PolylineDecomposer::fillBarsDecompositionTriangleIndices(char* id, int* buffer, int bufferLength,
1259                                                              int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift)
1260 {
1261     double barWidth = 0.0;
1262     double* pdBarWidth = &barWidth;
1263     double coordsi[3];
1264
1265     int triangleIndices[6];
1266     int offset = 0;
1267     int numberValidIndices = 0;
1268
1269     if (nPoints == 0)
1270     {
1271         return 0;
1272     }
1273
1274     getGraphicObjectProperty(id, __GO_BAR_WIDTH__, jni_double, (void**) &pdBarWidth);
1275
1276     /* 0 indices if the bar width is invalid, as it is the same for all bars. */
1277     if (!DecompositionUtils::isValid(barWidth))
1278     {
1279         return 0;
1280     }
1281
1282     /*
1283      * Gets the indices corresponding to a rectangle decomposed into 2 triangles.
1284      * All the bars are decomposed the same way.
1285      */
1286     DecompositionUtils::getDecomposedRectangleTriangleIndices(triangleIndices);
1287
1288     /* Bars */
1289     for (int i = 0; i < nPoints; i++)
1290     {
1291         getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, i, &coordsi[0], &coordsi[1], &coordsi[2]);
1292
1293         if (DecompositionUtils::isValid(coordsi[0], coordsi[1], coordsi[2]))
1294         {
1295             if (logMask && !DecompositionUtils::isLogValid(coordsi[0], coordsi[1], coordsi[2], logMask))
1296             {
1297                 continue;
1298             }
1299
1300             buffer[6*offset] = 4*i + triangleIndices[0];
1301             buffer[6*offset+1] = 4*i + triangleIndices[1];
1302             buffer[6*offset+2] = 4*i + triangleIndices[2];
1303             buffer[6*offset+3] = 4*i + triangleIndices[3];
1304             buffer[6*offset+4] = 4*i + triangleIndices[4];
1305             buffer[6*offset+5] = 4*i + triangleIndices[5];
1306
1307             numberValidIndices += 6;
1308             offset++;
1309         }
1310
1311     }
1312
1313     return numberValidIndices;
1314 }
1315
1316 int PolylineDecomposer::getWireIndicesSize(char* id)
1317 {
1318     int nPoints = 0;
1319     int *piNPoints = &nPoints;
1320     int polylineStyle = 0;
1321     int* piPolylineStyle = &polylineStyle;
1322
1323     int lineMode = 0;
1324     int* piLineMode = &lineMode;
1325
1326     int closed = 0;
1327     int* piClosed = &closed;
1328
1329     getGraphicObjectProperty(id, __GO_POLYLINE_STYLE__, jni_int, (void**) &piPolylineStyle);
1330     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_ELEMENTS__, jni_int, (void**) &piNPoints);
1331     getGraphicObjectProperty(id, __GO_LINE_MODE__, jni_bool, (void**) &piLineMode);
1332     getGraphicObjectProperty(id, __GO_CLOSED__, jni_bool, (void**) &piClosed);
1333
1334     /* No segments if 0 points */
1335     if (nPoints == 0)
1336     {
1337         return 0;
1338     }
1339
1340     /* Segments */
1341     if (polylineStyle == 1)
1342     {
1343         return getSegmentsDecompositionSegmentIndicesSize(nPoints, lineMode, closed);
1344     }
1345     /* Staircase */
1346     else if (polylineStyle == 2)
1347     {
1348         return getStairDecompositionSegmentIndicesSize(nPoints, lineMode, closed);
1349     }
1350     /* Vertical segments plus segments */
1351     else if (polylineStyle == 3)
1352     {
1353         return getVerticalLinesDecompositionSegmentIndicesSize(nPoints, lineMode);
1354     }
1355     /* Segments with arrow heads */
1356     else if (polylineStyle == 4)
1357     {
1358         return getSegmentsDecompositionSegmentIndicesSize(nPoints, lineMode, closed);
1359     }
1360     /* Filled patch  */
1361     else if (polylineStyle == 5)
1362     {
1363         return getSegmentsDecompositionSegmentIndicesSize(nPoints, lineMode, closed);
1364     }
1365     /* Vertical bars plus segments */
1366     else if (polylineStyle == 6)
1367     {
1368         return getBarsDecompositionSegmentIndicesSize(nPoints, lineMode);
1369     }
1370     /* Horizontal bars plus segments */
1371     else if (polylineStyle == 7)
1372     {
1373         return getBarsDecompositionSegmentIndicesSize(nPoints, lineMode);
1374     }
1375     else
1376     {
1377         return 0;
1378     }
1379
1380 }
1381
1382 int PolylineDecomposer::getSegmentsDecompositionSegmentIndicesSize(int nPoints, int lineMode, int closed)
1383 {
1384     if (nPoints < 2)
1385     {
1386         return 0;
1387     }
1388
1389     if (lineMode)
1390     {
1391         if (closed)
1392         {
1393             return nPoints + 1;
1394         }
1395         else
1396         {
1397             return nPoints;
1398         }
1399     }
1400     else
1401     {
1402         return 0;
1403     }
1404 }
1405
1406 int PolylineDecomposer::getStairDecompositionSegmentIndicesSize(int nPoints, int lineMode, int closed)
1407 {
1408     if (nPoints < 2)
1409     {
1410         return 0;
1411     }
1412
1413     if (lineMode)
1414     {
1415         if (closed)
1416         {
1417             return 2 * nPoints + 1;
1418         }
1419         else
1420         {
1421             return 2 * nPoints - 1;
1422         }
1423     }
1424     else
1425     {
1426         return 0;
1427     }
1428 }
1429
1430 int PolylineDecomposer::getVerticalLinesDecompositionSegmentIndicesSize(int nPoints, int lineMode)
1431 {
1432     if (nPoints == 0)
1433     {
1434         return 0;
1435     }
1436
1437     if (lineMode)
1438     {
1439         return 2*(nPoints) + 2*(nPoints-1);
1440     }
1441     else
1442     {
1443         return 2*(nPoints);
1444     }
1445 }
1446
1447 int PolylineDecomposer::getBarsDecompositionSegmentIndicesSize(int nPoints, int lineMode)
1448 {
1449     if (nPoints == 0)
1450     {
1451         return 0;
1452     }
1453
1454     if (lineMode)
1455     {
1456         return 2*4*(nPoints) + 2*(nPoints-1);
1457     }
1458     else
1459     {
1460         return 2*4*(nPoints);
1461     }
1462 }
1463
1464 int PolylineDecomposer::fillWireIndices(char* id, int* buffer, int bufferLength, int logMask)
1465 {
1466     double* coordinates = NULL;
1467     double* xshift = NULL;
1468     double* yshift = NULL;
1469     double* zshift = NULL;
1470
1471     int polylineStyle = 0;
1472     int* piPolylineStyle = &polylineStyle;
1473     int nPoints = 0;
1474     int* piNPoints = &nPoints;
1475     int closed = 0;
1476     int* piClosed = &closed;
1477     int lineMode = 0;
1478     int* piLineMode = &lineMode;
1479
1480     getGraphicObjectProperty(id, __GO_POLYLINE_STYLE__, jni_int, (void**) &piPolylineStyle);
1481
1482     getGraphicObjectProperty(id, __GO_DATA_MODEL_COORDINATES__, jni_double_vector, (void**) &coordinates);
1483     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_ELEMENTS__, jni_int, (void**) &piNPoints);
1484     getGraphicObjectProperty(id, __GO_DATA_MODEL_X_COORDINATES_SHIFT__, jni_double_vector, (void**) &xshift);
1485     getGraphicObjectProperty(id, __GO_DATA_MODEL_Y_COORDINATES_SHIFT__, jni_double_vector, (void**) &yshift);
1486     getGraphicObjectProperty(id, __GO_DATA_MODEL_Z_COORDINATES_SHIFT__, jni_double_vector, (void**) &zshift);
1487
1488     getGraphicObjectProperty(id, __GO_LINE_MODE__, jni_bool, (void**) &piLineMode);
1489     getGraphicObjectProperty(id, __GO_CLOSED__, jni_bool, (void**) &piClosed);
1490
1491     if (polylineStyle == 1)
1492     {
1493         return fillSegmentsDecompositionSegmentIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, lineMode, closed);
1494     }
1495     else if (polylineStyle == 2)
1496     {
1497         return fillStairDecompositionSegmentIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, lineMode, closed);
1498     }
1499     else if (polylineStyle == 3)
1500     {
1501         return fillVerticalLinesDecompositionSegmentIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, lineMode);
1502     }
1503     else if (polylineStyle == 4)
1504     {
1505         return fillSegmentsDecompositionSegmentIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, lineMode, closed);
1506     }
1507     else if (polylineStyle == 5)
1508     {
1509         return fillSegmentsDecompositionSegmentIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, lineMode, closed);
1510     }
1511     else if (polylineStyle == 6)
1512     {
1513         return fillBarsDecompositionSegmentIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, lineMode);
1514     }
1515     else if (polylineStyle == 7)
1516     {
1517         return fillBarsDecompositionSegmentIndices(id, buffer, bufferLength, logMask, coordinates, nPoints, xshift, yshift, zshift, lineMode);
1518     }
1519
1520     return 0;
1521 }
1522
1523 int PolylineDecomposer::fillSegmentsDecompositionSegmentIndices(char* id, int* buffer, int bufferLength,
1524                                                                 int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift, int lineMode, int closed)
1525 {
1526     /* If less than 2 points, no segments */
1527     if (nPoints < 2)
1528     {
1529         return 0;
1530     }
1531
1532     if (lineMode == 0)
1533     {
1534         return 0;
1535     }
1536
1537     for (int i = 0; i < nPoints; i++)
1538     {
1539         buffer[i] = i;
1540     }
1541
1542     if (closed)
1543     {
1544         buffer[nPoints] = 0;
1545     }
1546
1547     return closed ? (nPoints + 1) : nPoints;
1548 }
1549
1550 int PolylineDecomposer::fillStairDecompositionSegmentIndices(char* id, int* buffer, int bufferLength,
1551                                                              int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift, int lineMode, int closed)
1552 {
1553     int currentValid = 0;
1554     int middleVertexValid = 0;
1555     int nextValid = 0;
1556
1557     int offset = 0;
1558     int numberValidIndices = 0;
1559
1560     /* If less than 2 points, no segments */
1561     if (nPoints < 2)
1562     {
1563         return 0;
1564     }
1565
1566     if (lineMode == 0)
1567     {
1568         return 0;
1569     }
1570
1571     for (int i = 0; i < 2 * nPoints - 1; i++)
1572     {
1573         buffer[i] = i;
1574     }
1575
1576     if (closed)
1577     {
1578         buffer[2 * nPoints - 1] = 2 * nPoints - 1;
1579         buffer[2 * nPoints] = 0;
1580     }
1581
1582     return closed ? (2 * nPoints + 1) : (2 * nPoints - 1);
1583 }
1584
1585 int PolylineDecomposer::fillVerticalLinesDecompositionSegmentIndices(char* id, int* buffer, int bufferLength,
1586                                                                      int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift, int lineMode)
1587 {
1588     double coordsi[3];
1589
1590     int offset = 0;
1591     int numberValidIndices = 0;
1592
1593     if (nPoints == 0)
1594     {
1595         return 0;
1596     }
1597
1598     /* Vertical lines */
1599     for (int i = 0; i < nPoints; i++)
1600     {
1601         getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, i, &coordsi[0], &coordsi[1], &coordsi[2]);
1602
1603         if (DecompositionUtils::isValid(coordsi[0], coordsi[1], coordsi[2]))
1604         {
1605             if (logMask && !DecompositionUtils::isLogValid(coordsi[0], coordsi[1], coordsi[2], logMask))
1606             {
1607                 continue;
1608             }
1609
1610             buffer[2*offset] = 2*i;
1611             buffer[2*offset+1] = 2*i+1;
1612
1613             numberValidIndices += 2;
1614             offset++;
1615         }
1616
1617     }
1618
1619     if (lineMode)
1620     {
1621         int currentValid;
1622         int nextValid;
1623
1624         getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 0, &coordsi[0], &coordsi[1], &coordsi[2]);
1625
1626         currentValid = DecompositionUtils::isValid(coordsi[0], coordsi[1], coordsi[2]);
1627
1628         if (logMask)
1629         {
1630             currentValid &= DecompositionUtils::isLogValid(coordsi[0], coordsi[1], coordsi[2], logMask);
1631         }
1632
1633         for (int i = 0; i < nPoints-1; i++)
1634         {
1635             getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, i+1, &coordsi[0], &coordsi[1], &coordsi[2]);
1636
1637             nextValid = DecompositionUtils::isValid(coordsi[0], coordsi[1], coordsi[2]);
1638
1639             if (logMask)
1640             {
1641                 nextValid &= DecompositionUtils::isLogValid(coordsi[0], coordsi[1], coordsi[2], logMask);
1642             }
1643
1644             if (currentValid && nextValid)
1645             {
1646                 buffer[2*offset] = 2*i+1;
1647                 buffer[2*offset+1] = 2*(i+1)+1;
1648
1649                 numberValidIndices += 2;
1650                 offset++;
1651             }
1652
1653             currentValid = nextValid;
1654         }
1655     }
1656
1657     return numberValidIndices;
1658 }
1659
1660
1661 int PolylineDecomposer::fillBarsDecompositionSegmentIndices(char* id, int* buffer, int bufferLength,
1662                                                             int logMask, double* coordinates, int nPoints, double* xshift, double* yshift, double* zshift, int lineMode)
1663 {
1664     double barWidth = 0.0;
1665     double* pdBarWidth = &barWidth;
1666     double coordsi[3];
1667
1668     int barWidthValid = 0;
1669     int offset = 0;
1670     int numberValidIndices = 0;
1671
1672     if (nPoints == 0)
1673     {
1674         return 0;
1675     }
1676
1677     getGraphicObjectProperty(id, __GO_BAR_WIDTH__, jni_double, (void**) &pdBarWidth);
1678
1679     barWidthValid = DecompositionUtils::isValid(barWidth);
1680
1681     /* 0 bar segment indices if the bar width is invalid, as it is the same for all bars. */
1682     if (barWidthValid)
1683     {
1684         /* Bars */
1685         for (int i = 0; i < nPoints; i++)
1686         {
1687             getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, i, &coordsi[0], &coordsi[1], &coordsi[2]);
1688
1689             if (DecompositionUtils::isValid(coordsi[0], coordsi[1], coordsi[2]))
1690             {
1691                 if (logMask && !DecompositionUtils::isLogValid(coordsi[0], coordsi[1], coordsi[2], logMask))
1692                 {
1693                     continue;
1694                 }
1695
1696                 buffer[8*offset] = 4*i;
1697                 buffer[8*offset+1] = 4*i+1;
1698                 buffer[8*offset+2] = 4*i+1;
1699                 buffer[8*offset+3] = 4*i+2;
1700                 buffer[8*offset+4] = 4*i+2;
1701                 buffer[8*offset+5] = 4*i+3;
1702                 buffer[8*offset+6] = 4*i+3;
1703                 buffer[8*offset+7] = 4*i;
1704
1705                 numberValidIndices += 8;
1706                 offset++;
1707             }
1708
1709         }
1710
1711     }
1712
1713     /* Lines */
1714     if (lineMode)
1715     {
1716         int loffset = 0;
1717
1718         int currentValid;
1719         int nextValid;
1720
1721         getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, 0, &coordsi[0], &coordsi[1], &coordsi[2]);
1722
1723         currentValid = DecompositionUtils::isValid(coordsi[0], coordsi[1], coordsi[2]);
1724
1725         if (logMask)
1726         {
1727             currentValid &= DecompositionUtils::isLogValid(coordsi[0], coordsi[1], coordsi[2], logMask);
1728         }
1729
1730         for (int i = 0; i < nPoints-1; i++)
1731         {
1732             getShiftedPolylinePoint(coordinates, xshift, yshift, zshift, nPoints, i+1, &coordsi[0], &coordsi[1], &coordsi[2]);
1733
1734             nextValid = DecompositionUtils::isValid(coordsi[0], coordsi[1], coordsi[2]);
1735
1736             if (logMask)
1737             {
1738                 nextValid &= DecompositionUtils::isLogValid(coordsi[0], coordsi[1], coordsi[2], logMask);
1739             }
1740
1741             if (currentValid && nextValid)
1742             {
1743                 buffer[8*offset+2*loffset] = 4*nPoints +i;
1744                 buffer[8*offset+2*loffset+1] = 4*nPoints +i+1;
1745
1746                 numberValidIndices += 2;
1747                 loffset++;
1748             }
1749
1750             currentValid = nextValid;
1751         }
1752     }
1753
1754     return numberValidIndices;
1755 }
1756
1757 void PolylineDecomposer::getShiftedPolylinePoint(double* coordinates, double* xshift, double* yshift, double* zshift, int nPoints, int index,
1758                                                  double* x, double* y, double* z)
1759 {
1760     *x = coordinates[index];
1761
1762     if (xshift != NULL)
1763     {
1764         *x += xshift[index];
1765     }
1766
1767     *y = coordinates[index + nPoints];
1768
1769     if (yshift != NULL)
1770     {
1771         *y += yshift[index];
1772     }
1773
1774     *z = coordinates[index + 2*nPoints];
1775
1776     if (zshift != NULL)
1777     {
1778         *z += zshift[index];
1779     }
1780
1781 }
1782