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