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