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