Bug 12232 fixed: fix several memleaks in various filler
[scilab.git] / scilab / modules / graphic_objects / src / cpp / TriangleMeshFecDataDecomposer.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2011 - DIGITEO - Manuel Juliachs
4  *
5  *  This file must be used under the terms of the CeCILL.
6  *  This source file is licensed as described in the file COPYING, which
7  *  you should have received as part of this distribution.  The terms
8  *  are also available at
9  *  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
10  *
11  */
12
13 #include "ColorComputer.hxx"
14 #include "DecompositionUtils.hxx"
15 #include "TriangleMeshFecDataDecomposer.hxx"
16
17 extern "C"
18 {
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include "getGraphicObjectProperty.h"
23 #include "graphicObjectProperties.h"
24 }
25
26 int TriangleMeshFecDataDecomposer::getDataSize(char* id)
27 {
28     int numVertices = 0;
29     int* piNumVertices = &numVertices;
30
31     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_VERTICES__, jni_int, (void**) &piNumVertices);
32
33     return numVertices;
34 }
35
36 void TriangleMeshFecDataDecomposer::fillVertices(char* id, float* buffer, int bufferLength, int elementsSize, int coordinateMask, double* scale, double* translation, int logMask)
37 {
38     double* coordinates = NULL;
39
40     int numVertices = 0;
41     int* piNumVertices = &numVertices;
42
43     getGraphicObjectProperty(id, __GO_DATA_MODEL_COORDINATES__, jni_double_vector, (void**) &coordinates);
44     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_VERTICES__, jni_int, (void**) &piNumVertices);
45
46     for (int i = 0; i < numVertices; i++)
47     {
48         if (coordinateMask & 0x1)
49         {
50             double xi = coordinates[3 * i];
51             if (logMask & 0x1)
52             {
53                 xi = DecompositionUtils::getLog10Value(xi);
54             }
55             buffer[elementsSize * i] = (float)(xi * scale[0] + translation[0]);
56         }
57
58         if (coordinateMask & 0x2)
59         {
60             double yi = coordinates[3 * i + 1];
61             if (logMask & 0x2)
62             {
63                 yi = DecompositionUtils::getLog10Value(yi);
64             }
65             buffer[elementsSize * i + 1] = (float)(yi * scale[1] + translation[1]);
66         }
67
68         if (coordinateMask & 0x4)
69         {
70             double zi = coordinates[3 * i + 2];
71             if (logMask & 0x4)
72             {
73                 zi = DecompositionUtils::getLog10Value(zi);
74             }
75             buffer[elementsSize * i + 2] = (float)(zi * scale[2] + translation[2]);
76         }
77
78         if (elementsSize == 4 && (coordinateMask & 0x8))
79         {
80             buffer[elementsSize * i + 3] = 1.0;
81         }
82     }
83
84 }
85
86 void TriangleMeshFecDataDecomposer::fillTextureCoordinates(char* id, float* buffer, int bufferLength)
87 {
88     char* parentFigure = NULL;
89     int colormapSize = 0;
90     int* piColormapSize = &colormapSize;
91     int* colorRange = NULL;
92
93     double colorsNumber = 0.;
94     double scale = 0.;
95     double t = 0.;
96
97     double* values = NULL;
98     double* zBounds = NULL;
99
100     double minValue = 0.;
101     double maxValue = 0.;
102
103     int numVertices = 0;
104     int* piNumVertices = &numVertices;
105
106     int bufferOffset = 0;
107
108     getGraphicObjectProperty(id, __GO_PARENT_FIGURE__, jni_string, (void**) &parentFigure);
109     /* Temporary: to avoid getting a null parent_figure property when the object is built */
110     if (strcmp(parentFigure, "") == 0)
111     {
112         return;
113     }
114     getGraphicObjectProperty(id, __GO_COLOR_RANGE__, jni_int_vector, (void**) &colorRange);
115     getGraphicObjectProperty(parentFigure, __GO_COLORMAP_SIZE__, jni_int, (void**) &piColormapSize);
116
117     if (colorRange[0] != 0 || colorRange[1] != 0)
118     {
119         colorsNumber = (double) (1 + colorRange[1] - colorRange[0]);
120     }
121     else
122     {
123         colorsNumber = (double) colormapSize;
124     }
125
126     releaseGraphicObjectProperty(__GO_COLOR_RANGE__, colorRange, jni_int_vector, 0);
127
128     /** To take into account the presence of exterior colors:
129      *  - We add 2 to the number of colors.
130      *  - We skip the first color.
131      */
132     t = 3. / (2. * (colorsNumber + 2.));
133     scale = (colorsNumber - 1.) / (colorsNumber + 2);
134
135     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_VERTICES__, jni_int, (void**) &piNumVertices);
136     getGraphicObjectProperty(id, __GO_DATA_MODEL_VALUES__, jni_double_vector, (void**) &values);
137     getGraphicObjectProperty(id, __GO_Z_BOUNDS__, jni_double_vector, (void**) &zBounds);
138
139     /* Z-bounds are not taken into account if either of them is invalid */
140     if ((zBounds[0] != 0.0 || zBounds[1] != 0.0) && (DecompositionUtils::isValid(zBounds[0]) && DecompositionUtils::isValid(zBounds[1])) && (zBounds[0] != zBounds[1]))
141     {
142         minValue = zBounds[0];
143         maxValue = zBounds[1];
144     }
145     else
146     {
147         computeMinMaxValues(values, numVertices, &minValue, &maxValue);
148     }
149
150     releaseGraphicObjectProperty(__GO_Z_BOUNDS__, zBounds, jni_double_vector, 0);
151
152     if (maxValue == minValue)
153     {
154         for (int i = 0; i < numVertices; i++)
155         {
156             buffer[bufferOffset++] = (float)minValue;
157             buffer[bufferOffset++] = 0;
158             buffer[bufferOffset++] = 0;
159             buffer[bufferOffset++] = 1;
160         }
161     }
162     else
163     {
164         for (int i = 0; i < numVertices; i++)
165         {
166             buffer[bufferOffset++] = (float)(t + scale * (values[i] - minValue) / (maxValue - minValue));
167             buffer[bufferOffset++] = 0;
168             buffer[bufferOffset++] = 0;
169             buffer[bufferOffset++] = 1;
170         }
171     }
172 }
173
174 void TriangleMeshFecDataDecomposer::fillColors(char* id, float* buffer, int bufferLength, int elementsSize)
175 {
176     char* parent = NULL;
177     char* parentFigure = NULL;
178
179     double* values = NULL;
180     double* zBounds = NULL;
181     double* colormap = NULL;
182
183     double minValue = 0.;
184     double maxValue = 0.;
185     double valueRange = 0.;
186
187     float minColor[3];
188     float maxColor[3];
189
190     int colormapSize = 0;
191     int* piColormapSize = &colormapSize;
192
193     int numVertices = 0;
194     int* piNumVertices = &numVertices;
195
196     int minColorIndex = 0;
197     int maxColorIndex = 0;
198
199     int* colorRange = NULL;
200     int useOutsideColors = 0;
201     int bufferOffset = 0;
202
203     getGraphicObjectProperty(id, __GO_PARENT__, jni_string, (void**) &parent);
204
205     /* Temporary: to avoid getting a null parent_figure property when the object is built */
206     if (strcmp(parent, "") == 0)
207     {
208         return;
209     }
210
211     getGraphicObjectProperty(id, __GO_PARENT_FIGURE__, jni_string, (void**) &parentFigure);
212
213     getGraphicObjectProperty(parentFigure, __GO_COLORMAP__, jni_double_vector, (void**) &colormap);
214     getGraphicObjectProperty(parentFigure, __GO_COLORMAP_SIZE__, jni_int, (void**) &piColormapSize);
215
216     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_VERTICES__, jni_int, (void**) &piNumVertices);
217
218     getGraphicObjectProperty(id, __GO_DATA_MODEL_VALUES__, jni_double_vector, (void**) &values);
219
220     getGraphicObjectProperty(id, __GO_Z_BOUNDS__, jni_double_vector, (void**) &zBounds);
221     getGraphicObjectProperty(id, __GO_COLOR_RANGE__, jni_int_vector, (void**) &colorRange);
222
223     if (colorRange[0] != 0 || colorRange[1] != 0)
224     {
225         /* To do: use a scilab index to colormap index conversion function */
226         minColorIndex = colorRange[0] - 1;
227         maxColorIndex = colorRange[1] - 1;
228
229         if (minColorIndex < 0)
230         {
231             minColorIndex = 0;
232         }
233         if (maxColorIndex < 0)
234         {
235             maxColorIndex = 0;
236         }
237
238         if (maxColorIndex > colormapSize-1)
239         {
240             maxColorIndex = colormapSize - 1;
241         }
242         if (minColorIndex > colormapSize-1)
243         {
244             minColorIndex = colormapSize - 1;
245         }
246
247     }
248     else
249     {
250         minColorIndex = 0;
251         maxColorIndex = colormapSize-1;
252     }
253
254     releaseGraphicObjectProperty(__GO_COLOR_RANGE__, colorRange, jni_int_vector, 0);
255
256     computeMinMaxValues(values, numVertices, &minValue, &maxValue);
257
258     /* Z-bounds are not taken into account if either of them is invalid */
259     if ((zBounds[0] != 0.0 || zBounds[1] != 0.0) && (DecompositionUtils::isValid(zBounds[0]) && DecompositionUtils::isValid(zBounds[1])) && (zBounds[0] != zBounds[1]))
260     {
261         int* outsideColors;
262
263         minValue = zBounds[0];
264         maxValue = zBounds[1];
265
266         getGraphicObjectProperty(id, __GO_OUTSIDE_COLOR__, jni_int_vector, (void**) &outsideColors);
267
268         if (outsideColors[0] != 0 || outsideColors[1] != 0)
269         {
270             useOutsideColors = 1;
271
272             ColorComputer::getDirectColor((double) outsideColors[0] - 1.0, colormap, colormapSize, minColor);
273             ColorComputer::getDirectColor((double) outsideColors[1] - 1.0, colormap, colormapSize, maxColor);
274         }
275     }
276
277     releaseGraphicObjectProperty(__GO_Z_BOUNDS__, zBounds, jni_double_vector, 0);
278
279     /* To be verified (when reverse z bounds are specified) */
280     if (DecompositionUtils::getAbsoluteValue(maxValue - minValue) < DecompositionUtils::getMinDoubleValue())
281     {
282         valueRange = 1.0;
283     }
284     else
285     {
286         valueRange = maxValue - minValue;
287     }
288
289     for (int i = 0; i < numVertices; i++)
290     {
291         bufferOffset = elementsSize*i;
292
293         if (useOutsideColors == 1)
294         {
295             if (values[i] < minValue)
296             {
297                 buffer[bufferOffset] = minColor[0];
298                 buffer[bufferOffset+1] = minColor[1];
299                 buffer[bufferOffset+2] = minColor[2];
300             }
301             else if (values[i] > maxValue)
302             {
303                 buffer[bufferOffset] = maxColor[0];
304                 buffer[bufferOffset+1] = maxColor[1];
305                 buffer[bufferOffset+2] = maxColor[2];
306             }
307             else
308             {
309                 /* To do: replace 0.5 by a macro-definition */
310                 ColorComputer::getColor(values[i], minValue, valueRange, 0.5, colormap, minColorIndex, maxColorIndex, colormapSize, &buffer[bufferOffset]);
311             }
312         }
313         else
314         {
315             /* To do: replace 0.5 by a macro-definition */
316             ColorComputer::getColor(values[i], minValue, valueRange, 0.5, colormap, minColorIndex, maxColorIndex, colormapSize, &buffer[bufferOffset]);
317         }
318
319         if (elementsSize == 4)
320         {
321             buffer[bufferOffset+3] = 1.0;
322         }
323     }
324
325     releaseGraphicObjectProperty(__GO_COLORMAP__, colormap, jni_double_vector, colormapSize);
326 }
327
328 void TriangleMeshFecDataDecomposer::computeMinMaxValues(double* values, int numValues, double* valueMin, double* valueMax)
329 {
330     double maxDouble = DecompositionUtils::getMaxDoubleValue();
331     double tmpValueMin = maxDouble;
332     double tmpValueMax = -maxDouble;
333     double value = 0.;
334
335     for (int i = 0; i < numValues; i++)
336     {
337         value = values[i];
338
339         if (value < tmpValueMin)
340         {
341             tmpValueMin = value;
342         }
343
344         if (value > tmpValueMax)
345         {
346             tmpValueMax = value;
347         }
348     }
349
350     *valueMin = tmpValueMin;
351     *valueMax = tmpValueMax;
352 }
353
354 int TriangleMeshFecDataDecomposer::getIndicesSize(char* id)
355 {
356     int numIndices = 0;
357     int* piNumIndices = &numIndices;
358
359     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_INDICES__, jni_int, (void**) &piNumIndices);
360
361     return 3*numIndices;
362 }
363
364 int TriangleMeshFecDataDecomposer::fillIndices(char* id, int* buffer, int bufferLength, int logMask)
365 {
366     double* coordinates = NULL;
367     double* values = NULL;
368
369     int numIndices = 0;
370     int* piNumIndices = &numIndices;
371     int numVertices = 0;
372     int* piNumVertices = &numVertices;
373
374     int* triangleIndices = NULL;
375
376     int v0 = 0;
377     int v1 = 0;
378     int v2 = 0;
379     int bufferOffset = 0;
380
381     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_INDICES__, jni_int, (void**) &piNumIndices);
382     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_VERTICES__, jni_int, (void**) &piNumVertices);
383
384     getGraphicObjectProperty(id, __GO_DATA_MODEL_COORDINATES__, jni_double_vector, (void**) &coordinates);
385     getGraphicObjectProperty(id, __GO_DATA_MODEL_VALUES__, jni_double_vector, (void**) &values);
386
387     /* 0 facets */
388     if (numIndices == 0 || numVertices < 3)
389     {
390         return 0;
391     }
392
393     getGraphicObjectProperty(id, __GO_DATA_MODEL_INDICES__, jni_int_vector, (void**) &triangleIndices);
394
395     for (int i = 0; i < numIndices; i++)
396     {
397         v0 = triangleIndices[3*i];
398         v1 = triangleIndices[3*i+1];
399         v2 = triangleIndices[3*i+2];
400
401         if (areFaceIndicesValid(numVertices, v0, v1, v2) &&
402             areFaceVerticesValid(coordinates, v0, v1, v2, logMask) &&
403             areFaceValuesValid(values, v0, v1, v2))
404         {
405             buffer[bufferOffset] = v0;
406             buffer[bufferOffset+1] = v1;
407             buffer[bufferOffset+2] = v2;
408
409             bufferOffset += 3;
410         }
411
412     }
413
414     return bufferOffset;
415 }
416
417 int TriangleMeshFecDataDecomposer::areFaceVerticesValid(double* coordinates, int v0, int v1, int v2, int logMask)
418 {
419     double vertex0[3];
420     double vertex1[3];
421     double vertex2[3];
422
423     getVertexCoordinates(coordinates, v0, vertex0);
424     getVertexCoordinates(coordinates, v1, vertex1);
425     getVertexCoordinates(coordinates, v2, vertex2);
426
427     if (DecompositionUtils::isValid(vertex0[0], vertex0[1], vertex0[2]) &&
428         DecompositionUtils::isLogValid(vertex0[0], vertex0[1], vertex0[2], logMask) &&
429         DecompositionUtils::isValid(vertex1[0], vertex1[1], vertex1[2]) &&
430         DecompositionUtils::isLogValid(vertex1[0], vertex1[1], vertex1[2], logMask) &&
431         DecompositionUtils::isValid(vertex2[0], vertex2[1], vertex2[2]) &&
432         DecompositionUtils::isLogValid(vertex2[0], vertex2[1], vertex2[2], logMask))
433     {
434         return 1;
435     }
436
437     return 0;
438 }
439
440 int TriangleMeshFecDataDecomposer::areFaceValuesValid(double* values, int v0, int v1, int v2)
441 {
442     if (DecompositionUtils::isValid(values[v0], values[v1], values[v2]))
443     {
444         return 1;
445     }
446
447     return 0;
448 }
449
450 int TriangleMeshFecDataDecomposer::areFaceIndicesValid(int numVertices, int v0, int v1, int v2)
451 {
452     if (v0 < 0 || v0 >= numVertices || v1 < 0 || v1 >= numVertices || v2 < 0 || v2 >= numVertices)
453     {
454         return 0;
455     }
456
457     return 1;
458 }
459
460 void TriangleMeshFecDataDecomposer::getVertexCoordinates(double* coordinates, int index, double* vertexCoordinates)
461 {
462     vertexCoordinates[0] = coordinates[3*index];
463     vertexCoordinates[1] = coordinates[3*index+1];
464     vertexCoordinates[2] = coordinates[3*index+2];
465 }
466
467 int TriangleMeshFecDataDecomposer::getWireIndicesSize(char* id)
468 {
469     int numTriangles = 0;
470     int* piNumTriangles = &numTriangles;
471
472     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_INDICES__, jni_int, (void**) &piNumTriangles);
473
474     return 6*numTriangles;
475 }
476
477 /*
478  * To do: ouput shared edges once instead of twice (once per adjacent face).
479  */
480 int TriangleMeshFecDataDecomposer::fillWireIndices(char* id, int* buffer, int bufferLength, int logMask)
481 {
482     double* coordinates = NULL;
483     double* values = NULL;
484
485     int numVertices = 0;
486     int* piNumVertices = &numVertices;
487     int numIndices = 0;
488     int* piNumIndices = &numIndices;
489     int* triangleIndices = NULL;
490
491     int v0 = 0;
492     int v1 = 0;
493     int v2 = 0;
494     int bufferOffset = 0;
495
496     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_INDICES__, jni_int, (void**) &piNumIndices);
497
498     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_VERTICES__, jni_int, (void**) &piNumVertices);
499     getGraphicObjectProperty(id, __GO_DATA_MODEL_COORDINATES__, jni_double_vector, (void**) &coordinates);
500     getGraphicObjectProperty(id, __GO_DATA_MODEL_VALUES__, jni_double_vector, (void**) &values);
501
502     /* 0 segments */
503     if (numIndices == 0 || numVertices < 3)
504     {
505         return 0;
506     }
507
508     getGraphicObjectProperty(id, __GO_DATA_MODEL_INDICES__, jni_int_vector, (void**) &triangleIndices);
509
510     for (int i = 0; i < numIndices; i++)
511     {
512         v0 = triangleIndices[3*i];
513         v1 = triangleIndices[3*i+1];
514         v2 = triangleIndices[3*i+2];
515
516         if (areFaceIndicesValid(numVertices, v0, v1, v2) &&
517             areFaceVerticesValid(coordinates, v0, v1, v2, logMask) &&
518             areFaceValuesValid(values, v0, v1, v2))
519         {
520             buffer[bufferOffset] = v0;
521             buffer[bufferOffset+1] = v1;
522             buffer[bufferOffset+2] = v1;
523             buffer[bufferOffset+3] = v2;
524             buffer[bufferOffset+4] = v2;
525             buffer[bufferOffset+5] = v0;
526
527             bufferOffset += 6;
528         }
529
530     }
531
532     return bufferOffset;
533 }
534