50a95773aa90886bfc96d3d7c356d840f8ad680b
[scilab.git] / scilab / modules / graphic_objects / src / cpp / Plot3DDecomposer.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2011-2012 - 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 <cstring>
14
15 #include "ColorComputer.hxx"
16 #include "DecompositionUtils.hxx"
17 #include "Plot3DDecomposer.hxx"
18
19 extern "C"
20 {
21 #include "getGraphicObjectProperty.h"
22 #include "graphicObjectProperties.h"
23 }
24
25 Plot3DDecomposer* Plot3DDecomposer::decomposer = NULL;
26
27 void Plot3DDecomposer::fillVertices(char* id, float* buffer, int bufferLength, int elementsSize, int coordinateMask, double* scale, double* translation, int logMask)
28 {
29     double* x = NULL;
30     double* y = NULL;
31     double* z = NULL;
32
33     int numX = 0;
34     int* piNumX = &numX;
35     int numY = 0;
36     int* piNumY = &numY;
37
38     Plot3DDecomposer* decomposer = get();
39
40     getGraphicObjectProperty(id, __GO_DATA_MODEL_X__, jni_double_vector, (void**) &x);
41     getGraphicObjectProperty(id, __GO_DATA_MODEL_Y__, jni_double_vector, (void**) &y);
42     getGraphicObjectProperty(id, __GO_DATA_MODEL_Z__, jni_double_vector, (void**) &z);
43
44     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_X__, jni_int, (void**) &piNumX);
45     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_Y__, jni_int, (void**) &piNumY);
46
47     decomposer->fillGridVertices(buffer, bufferLength, elementsSize, coordinateMask, scale, translation, logMask, x, y, z, numX, numY);
48 }
49
50 double Plot3DDecomposer::getZCoordinate(double* z, int numX, int numY, int i, int j)
51 {
52     double zij = 0.;
53
54     zij = z[numX*j+i];
55
56     return zij;
57 }
58
59 double Plot3DDecomposer::getZCoordinate(double* z, int numX, int numY, int i, int j, int logUsed)
60 {
61     double zij = 0.;
62
63     zij = z[numX*j+i];
64
65     if (logUsed)
66     {
67         zij = DecompositionUtils::getLog10Value(zij);
68     }
69
70     return zij;
71 }
72
73 void Plot3DDecomposer::getFacetTriangles(double* x, double* y, double* z, int numX, int numY, int i, int j,
74     int* facetVertexIndices, int* triangleVertexIndices)
75 {
76     double vertices[4][3];
77
78     /* Gets the facet's vertices: (i,j), (i+1,j), (i+1,j+1), (i,j+1) */
79     getFacetCoordinates(x, y, z, numX, numY, i, j, vertices);
80
81     /* Decomposes the facet into two triangles and outputs their indices */
82     DecompositionUtils::getDecomposedQuadTriangleIndices(vertices, facetVertexIndices, triangleVertexIndices);
83 }
84
85 /*
86  * To do: compute and return color indices instead of directly looking
87  * up colors from the colormap.
88  */
89 void Plot3DDecomposer::fillColors(char* id, float* buffer, int bufferLength, int elementsSize)
90 {
91     char* parentFigure = NULL;
92     char* parent = NULL;
93
94     double* z = NULL;
95     double* colormap = NULL;
96
97
98     int numX = 0;
99     int* piNumX = &numX;
100     int numY = 0;
101     int* piNumY = &numY;
102     int colormapSize = 0;
103     int* piColormapSize = &colormapSize;
104
105     Plot3DDecomposer* decomposer = get();
106
107     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_X__, jni_int, (void**) &piNumX);
108     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_Y__, jni_int, (void**) &piNumY);
109
110     getGraphicObjectProperty(id, __GO_DATA_MODEL_Z__, jni_double_vector, (void**) &z);
111
112     getGraphicObjectProperty(id, __GO_PARENT__, jni_string, (void**) &parent);
113
114     /* Temporary: to avoid getting a null parent_figure property when the object is built */
115     if (strcmp(parent, "") == 0)
116     {
117         return;
118     }
119
120     getGraphicObjectProperty(id, __GO_PARENT_FIGURE__, jni_string, (void**) &parentFigure);
121
122     if (parentFigure == NULL)
123     {
124         return;
125     }
126
127     getGraphicObjectProperty(parentFigure, __GO_COLORMAP__, jni_double_vector, (void**) &colormap);
128     getGraphicObjectProperty(parentFigure, __GO_COLORMAP_SIZE__, jni_int, (void**) &piColormapSize);
129
130     decomposer->fillNormalizedZGridColors(buffer, bufferLength, elementsSize, colormap, colormapSize, z, numX, numY);
131 }
132
133 int Plot3DDecomposer::fillIndices(char* id, int* buffer, int bufferLength, int logMask)
134 {
135     double* x = NULL;
136     double* y = NULL;
137     double* z = NULL;
138
139     int numX = 0;
140     int* piNumX = &numX;
141     int numY = 0;
142     int* piNumY = &numY;
143
144     int numberIndices = 0;
145
146     Plot3DDecomposer* decomposer = get();
147
148     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_X__, jni_int, (void**) &piNumX);
149     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_Y__, jni_int, (void**) &piNumY);
150
151     /* 0 indices if 0 points */
152     if (numX == 0 || numY == 0)
153     {
154         return 0;
155     }
156
157     getGraphicObjectProperty(id, __GO_DATA_MODEL_X__, jni_double_vector, (void**) &x);
158     getGraphicObjectProperty(id, __GO_DATA_MODEL_Y__, jni_double_vector, (void**) &y);
159     getGraphicObjectProperty(id, __GO_DATA_MODEL_Z__, jni_double_vector, (void**) &z);
160
161     /* The per-node value flag is set to 1, as grid values amount to z coordinates and are not relevant anyway. */
162     numberIndices = decomposer->fillTriangleIndices(buffer, bufferLength, logMask, x, y, z, z, 1, numX, numY);
163
164     return numberIndices;
165 }
166
167 int Plot3DDecomposer::getWireIndicesSize(char* id)
168 {
169     int numX = 0;
170     int* piNumX = &numX;
171     int numY = 0;
172     int* piNumY = &numY;
173
174     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_X__, jni_int, (void**) &piNumX);
175     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_Y__, jni_int, (void**) &piNumY);
176
177     if (numX == 0 || numY == 0)
178     {
179         return 0;
180     }
181
182     return 2*2*(numX-1)*(numY-1) + 2*(numX-1) + 2*(numY-1);
183 }
184
185 /*
186  * To be optimized:
187  * -a lot of work performed redundantly with NgonGridDataDecomposer::fillIndices, ought to be merged
188  *  with it.
189  */
190 int Plot3DDecomposer::fillWireIndices(char* id, int* buffer, int bufferLength, int logMask)
191 {
192     double* x = NULL;
193     double* y = NULL;
194     double* z = NULL;
195
196     int numX = 0;
197     int* piNumX = &numX;
198     int numY = 0;
199     int* piNumY = &numY;
200
201     int previousRowValid = 0;
202     int currentRowValid = 0;
203     int nextRowValid = 0;
204
205     int previousColumnValid = 0;
206     int currentColumnValid = 0;
207     int nextColumnValid = 0;
208
209     int lowerLeftZValid = 0;
210     int lowerRightZValid = 0;
211     int upperLeftZValid = 0;
212     int upperRightZValid = 0;
213
214     int jm1HorizontalEdgeZValid = 0;
215     int im1VerticalEdgeZValid = 0;
216     int jHorizontalEdgeZValid = 0;
217     int iVerticalEdgeZValid = 0;
218     int jp1HorizontalEdgeZValid = 0;
219     int ip1VerticalEdgeZValid = 0;
220
221     int ij = 0;
222     int ip1j = 0;
223     int ijp1 = 0;
224     int ip1jp1 = 0;
225     int ijm1 = 0;
226     int ip1jm1 = 0;
227
228     int firstVertexIndex = 0;
229
230     int bufferOffset = 0;
231
232     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_X__, jni_int, (void**) &piNumX);
233     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_Y__, jni_int, (void**) &piNumY);
234
235     /* 0 indices if less than 2 points along either dimension */
236     if (numX < 2 || numY < 2)
237     {
238         return 0;
239     }
240
241     getGraphicObjectProperty(id, __GO_DATA_MODEL_X__, jni_double_vector, (void**) &x);
242     getGraphicObjectProperty(id, __GO_DATA_MODEL_Y__, jni_double_vector, (void**) &y);
243     getGraphicObjectProperty(id, __GO_DATA_MODEL_Z__, jni_double_vector, (void**) &z);
244
245     /* First row */
246     previousRowValid = 0;
247     currentRowValid = DecompositionUtils::isValid(y[0]);
248
249     if (logMask & 0x2)
250     {
251         currentRowValid &= DecompositionUtils::isLogValid(y[0]);
252     }
253
254     /* Set to 0 as it is not relevant for the first row iteration */
255     jm1HorizontalEdgeZValid = 0;
256
257     /* x-axis and y-axis indices (respectively) */
258     for (int j = 0; j < numY-1; j++)
259     {
260         nextRowValid = DecompositionUtils::isValid(y[j+1]);
261
262         if (logMask & 0x2)
263         {
264             nextRowValid &= DecompositionUtils::isLogValid(y[j+1]);
265         }
266
267         if (!currentRowValid)
268         {
269             previousRowValid = currentRowValid;
270             currentRowValid = nextRowValid;
271             continue;
272         }
273
274         previousColumnValid = 0;
275         currentColumnValid = DecompositionUtils::isValid(x[0]);
276
277         if (logMask & 0x1)
278         {
279             currentColumnValid &= DecompositionUtils::isLogValid(x[0]);
280         }
281
282         ij = getPointIndex(numX, numY, 0, j);
283         ijp1 = getPointIndex(numX, numY, 0, j+1);
284
285         lowerLeftZValid = DecompositionUtils::isValid(z[ij]);
286         upperLeftZValid = DecompositionUtils::isValid(z[ijp1]);
287
288         if (logMask & 0x4)
289         {
290             lowerLeftZValid &= DecompositionUtils::isLogValid(z[ij]);
291             upperLeftZValid &= DecompositionUtils::isLogValid(z[ijp1]);
292         }
293
294         iVerticalEdgeZValid = lowerLeftZValid && upperLeftZValid;
295
296         /* Set to 0 as not relevant for the first column iteration */
297         im1VerticalEdgeZValid = 0;
298
299         for (int i = 0; i < numX-1; i++)
300         {
301 #if !PER_VERTEX_VALUES
302             firstVertexIndex = getFirstVertexIndex(numX, numY, i, j);
303 #endif
304
305             ip1j = getPointIndex(numX, numY, i+1, j);
306             ip1jp1 = getPointIndex(numX, numY, i+1, j+1);
307
308             nextColumnValid = DecompositionUtils::isValid(x[i+1]);
309
310             if (logMask & 0x1)
311             {
312                 nextColumnValid &= DecompositionUtils::isLogValid(x[i+1]);
313             }
314
315             lowerRightZValid = DecompositionUtils::isValid(z[ip1j]);
316             upperRightZValid = DecompositionUtils::isValid(z[ip1jp1]);
317
318             if (logMask & 0x4)
319             {
320                 lowerRightZValid &= DecompositionUtils::isLogValid(z[ip1j]);
321                 upperRightZValid &= DecompositionUtils::isLogValid(z[ip1jp1]);
322             }
323
324             if (j > 0)
325             {
326                 ijm1 = getPointIndex(numX, numY, i, j-1);
327                 ip1jm1 = getPointIndex(numX, numY, i+1, j-1);
328
329                 jm1HorizontalEdgeZValid = DecompositionUtils::isValid(z[ijm1]) && DecompositionUtils::isValid(z[ip1jm1]);
330
331                 if (logMask & 0x4)
332                 {
333                     jm1HorizontalEdgeZValid &= (DecompositionUtils::isLogValid(z[ijm1]) && DecompositionUtils::isLogValid(z[ip1jm1]));
334                 }
335             }
336
337             jHorizontalEdgeZValid = lowerLeftZValid && lowerRightZValid;
338
339             jp1HorizontalEdgeZValid = upperLeftZValid && upperRightZValid;
340             ip1VerticalEdgeZValid = lowerRightZValid && upperRightZValid;
341
342             /*
343              * Two segments: between points (i,j) and (i+1,j)
344              * and points (i,j) and (i,j+1) .
345              */
346             if ((currentColumnValid && nextColumnValid) && jHorizontalEdgeZValid && ((previousRowValid && jm1HorizontalEdgeZValid) || (nextRowValid && jp1HorizontalEdgeZValid)))
347             {
348 #if PER_VERTEX_VALUES
349                 buffer[bufferOffset] = ij;
350                 buffer[bufferOffset+1] = ip1j;
351 #else
352                 buffer[bufferOffset] = firstVertexIndex;
353                 buffer[bufferOffset+1] = firstVertexIndex +1;
354 #endif
355
356                 bufferOffset += 2;
357             }
358
359             if (currentColumnValid && nextRowValid && iVerticalEdgeZValid && ((previousColumnValid && im1VerticalEdgeZValid) || (nextColumnValid && ip1VerticalEdgeZValid)))
360             {
361 #if PER_VERTEX_VALUES
362                 buffer[bufferOffset] = ij;
363                 buffer[bufferOffset+1] = ijp1;
364 #else
365                 buffer[bufferOffset] = firstVertexIndex;
366                 buffer[bufferOffset+1] = firstVertexIndex +2;
367 #endif
368
369                 bufferOffset += 2;
370             }
371
372             previousColumnValid = currentColumnValid;
373             currentColumnValid = nextColumnValid;
374             lowerLeftZValid = lowerRightZValid;
375             upperLeftZValid = upperRightZValid;
376
377             im1VerticalEdgeZValid = iVerticalEdgeZValid;
378             iVerticalEdgeZValid = ip1VerticalEdgeZValid;
379
380             ij = ip1j;
381             ijp1 = ip1jp1;
382         }
383
384         /* Rightmost vertical line */
385         if (currentColumnValid && nextRowValid && iVerticalEdgeZValid && (previousColumnValid && im1VerticalEdgeZValid))
386         {
387 #if PER_VERTEX_VALUES
388             buffer[bufferOffset] = ij;
389             buffer[bufferOffset+1] = ijp1;
390 #else
391             firstVertexIndex = getFirstVertexIndex(numX, numY, numX-2, j);
392
393             buffer[bufferOffset] = firstVertexIndex +1;
394             buffer[bufferOffset+1] = firstVertexIndex +3;
395 #endif
396
397             bufferOffset += 2;
398         }
399
400         previousRowValid = currentRowValid;
401         currentRowValid = nextRowValid;
402     }
403
404     /* Topmost horizontal lines */
405     currentRowValid = DecompositionUtils::isValid(y[numY-1]);
406
407     if (logMask & 0x2)
408     {
409         currentRowValid &= DecompositionUtils::isLogValid(y[numY-1]);
410     }
411
412     currentColumnValid = DecompositionUtils::isValid(x[0]);
413
414     if (logMask & 0x1)
415     {
416         currentColumnValid = DecompositionUtils::isValid(x[0]);
417     }
418
419     ij = getPointIndex(numX, numY, 0, numY-1);
420
421     lowerLeftZValid = DecompositionUtils::isValid(z[ij]);
422
423     if (logMask & 0x4)
424     {
425         lowerLeftZValid &= DecompositionUtils::isValid(z[ij]);
426     }
427
428     ij = getPointIndex(numX, numY, 0, numY-1);
429
430     for (int i = 0; i < numX-1; i++)
431     {
432         nextColumnValid = DecompositionUtils::isValid(x[i+1]);
433
434         if (logMask & 0x1)
435         {
436             nextColumnValid &= DecompositionUtils::isLogValid(x[i+1]);
437         }
438
439         ip1j = getPointIndex(numX, numY, i+1, numY-1);
440
441         lowerRightZValid = DecompositionUtils::isValid(z[ip1j]);
442
443         if (logMask & 0x4)
444         {
445             lowerRightZValid &= DecompositionUtils::isLogValid(z[ip1j]);
446         }
447
448         ijm1 = getPointIndex(numX, numY, i, numY-2);
449         ip1jm1 = getPointIndex(numX, numY, i+1, numY-2);
450
451         jm1HorizontalEdgeZValid = DecompositionUtils::isValid(z[ijm1]) && DecompositionUtils::isValid(z[ip1jm1]);
452
453         if (logMask & 0x4)
454         {
455             jm1HorizontalEdgeZValid &= (DecompositionUtils::isLogValid(z[ijm1]) && DecompositionUtils::isLogValid(z[ip1jm1]));
456         }
457
458         jHorizontalEdgeZValid = lowerLeftZValid && lowerRightZValid;
459
460         if (currentRowValid && (currentColumnValid && nextColumnValid) && jHorizontalEdgeZValid && (previousRowValid && jm1HorizontalEdgeZValid))
461         {
462 #if PER_VERTEX_VALUES
463             buffer[bufferOffset] = ij;
464             buffer[bufferOffset+1] = ip1j;
465 #else
466             firstVertexIndex = getFirstVertexIndex(numX, numY, i, numY-2);
467
468             buffer[bufferOffset] = firstVertexIndex +2;
469             buffer[bufferOffset+1] = firstVertexIndex +3;
470 #endif
471
472             bufferOffset += 2;
473         }
474
475         currentColumnValid = nextColumnValid;
476         lowerLeftZValid = lowerRightZValid;
477
478         ij = ip1j;
479     }
480
481     return bufferOffset;
482 }
483