6ca4eaa8ddb39dfbd56a7843a46f0541cef43991
[scilab.git] / scilab / modules / graphic_objects / src / cpp / NgonGridMatplotDataDecomposer.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 "ColorComputer.hxx"
14 #include "DecompositionUtils.hxx"
15 #include "NgonGridDataDecomposer.hxx"
16 #include "NgonGridMatplotDataDecomposer.hxx"
17
18 extern "C"
19 {
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include "getGraphicObjectProperty.h"
24 #include "graphicObjectProperties.h"
25 }
26
27 NgonGridMatplotDataDecomposer* NgonGridMatplotDataDecomposer::decomposer = NULL;
28
29 void NgonGridMatplotDataDecomposer::fillVertices(char* id, float* buffer, int bufferLength, int elementsSize, int coordinateMask, double* scale, double* translation, int logMask)
30 {
31     double* matplotScale = NULL;
32     double* matplotTranslate = NULL;
33     double zShift = 0.;
34     double* pdZShift = &zShift;
35
36     double xTrans[2];
37     double yTrans[2];
38
39     int numX = 0;
40     int* piNumX = &numX;
41     int numY = 0;
42     int* piNumY = &numY;
43
44     NgonGridMatplotDataDecomposer* decomposer = get();
45
46     getGraphicObjectProperty(id, __GO_MATPLOT_SCALE__, jni_double_vector, (void**) &matplotScale);
47     getGraphicObjectProperty(id, __GO_MATPLOT_TRANSLATE__, jni_double_vector, (void**) &matplotTranslate);
48
49     getGraphicObjectProperty(id, __GO_DATA_MODEL_Z_COORDINATES_SHIFT__, jni_double, (void**) &pdZShift);
50
51     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_X__, jni_int, (void**) &piNumX);
52     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_Y__, jni_int, (void**) &piNumY);
53
54     /* The position of the lower-left corner and the distance between two adjacent vertices i and i+1 (respectively) along the x-axis */
55     xTrans[0] = matplotTranslate[0];
56     xTrans[1] = matplotScale[0];
57
58     /* The position of the lower-left corner and the distance between two adjacent vertices j and j+1 (respectively) along the y-axis */
59     yTrans[0] = matplotTranslate[1];
60     yTrans[1] = matplotScale[1];
61
62     /*
63      * We pass the scale and translate values (for both the x and y axes) as the x and y coordinate arrays,
64      * because Matplot vertex coordinates are directly computed from these values.
65      */
66     decomposer->fillGridVertices(buffer, bufferLength, elementsSize, coordinateMask, scale, translation, logMask, (double*) xTrans, (double*) yTrans, &zShift, numX, numY);
67 }
68
69 /* To do: refactor with its parent class' same method */
70 void NgonGridMatplotDataDecomposer::fillGridVertices(float* buffer, int bufferLength, int elementsSize, int coordinateMask, double* scale, double* translation, int logMask,
71     double* x, double* y, double* z, int numX, int numY)
72 {
73     double xi = 0.;
74     double yj = 0.;
75     double zij = 0.;
76     double yjp1 = 0.;
77     double xip1 = 0.;
78
79     int bufferOffset = 0;
80
81 #if PER_VERTEX_VALUES
82     for (int j = 0; j < numY; j++)
83     {
84         yj = (double) j * y[1] + y[0];
85
86         if (coordinateMask  & 0x2)
87         {
88             if (logMask & 0x2)
89             {
90                 yj = DecompositionUtils::getLog10Value(yj);
91             }
92         }
93
94         for (int i = 0; i < numX; i++)
95         {
96             xi = (double) i * x[1] + x[0];
97             bufferOffset = elementsSize*(numX*j + i);
98
99             if (coordinateMask & 0x1)
100             {
101                 if (logMask & 0x1)
102                 {
103                     xi = DecompositionUtils::getLog10Value(xi);
104                 }
105
106                 buffer[bufferOffset] = xi * scale[0] + translation[0];
107             }
108
109             if (coordinateMask  & 0x2)
110             {
111                 buffer[bufferOffset +1] = yj * scale[1] + translation[1];
112             }
113
114             if (coordinateMask & 0x4)
115             {
116                 zij = getZCoordinate(z, numX, numY, i, j, logMask & 0x4);
117
118                 buffer[bufferOffset +2] = zij * scale[2] + translation[2];
119             }
120
121             if (elementsSize == 4 && (coordinateMask & 0x8))
122             {
123                 buffer[bufferOffset +3] = 1.0;
124             }
125         }
126     }
127 #else
128     bufferOffset = 0;
129
130     for (int j = 0; j < numY-1; j++)
131     {
132         double ycoords[4];
133         int yindices[4];
134
135         yj = (double) j * y[1] + y[0];
136         yjp1 = (double) (j+1) * y[1] + y[0];
137
138         if (coordinateMask  & 0x2)
139         {
140             if (logMask & 0x2)
141             {
142                 yj = DecompositionUtils::getLog10Value(yj);
143                 yjp1 = DecompositionUtils::getLog10Value(yjp1);
144             }
145         }
146
147         ycoords[0] = yj;
148         ycoords[1] = yj;
149         ycoords[2] = yjp1;
150         ycoords[3] = yjp1;
151
152         yindices[0] = j;
153         yindices[1] = j;
154         yindices[2] = j+1;
155         yindices[3] = j+1;
156
157         for (int i = 0; i < numX-1; i++)
158         {
159             double xcoords[4];
160             int xindices[4];
161
162             xi = (double) i * x[1] + x[0];
163             xip1 = (double) (i+1) * x[1] + x[0];
164
165             if (logMask & 0x1)
166             {
167                 xi = DecompositionUtils::getLog10Value(xi);
168                 xip1 = DecompositionUtils::getLog10Value(xip1);
169             }
170
171             xcoords[0] = xi;
172             xcoords[1] = xip1;
173             xcoords[2] = xi;
174             xcoords[3] = xip1;
175
176             xindices[0] = i;
177             xindices[1] = i+1;
178             xindices[2] = i;
179             xindices[3] = i+1;
180
181             for (int k = 0; k < 4; k++)
182             {
183                 if (coordinateMask & 0x1)
184                 {
185                     buffer[bufferOffset] = (float)(xcoords[k] * scale[0] + translation[0]);
186                 }
187
188                 if (coordinateMask  & 0x2)
189                 {
190                     buffer[bufferOffset +1] = (float)(ycoords[k] * scale[1] + translation[1]);
191                 }
192
193                 if (coordinateMask & 0x4)
194                 {
195                     zij = getZCoordinate(z, numX, numY, xindices[k], yindices[k], logMask & 0x4);
196                     buffer[bufferOffset +2] = (float)(zij * scale[2] + translation[2]);
197                 }
198
199                 if (elementsSize == 4 && (coordinateMask & 0x8))
200                 {
201                     buffer[bufferOffset +3] = 1.0;
202                 }
203
204                 bufferOffset += elementsSize;
205             }
206
207         }
208     }
209
210 #endif
211 }
212
213 /*
214  * To do:
215  * -clean-up: replace explicitely computed z indices by getPointIndex calls
216  * -remove the per-vertex color fill code
217  */
218 void NgonGridMatplotDataDecomposer::fillColors(char* id, float* buffer, int bufferLength, int elementsSize)
219 {
220     char* parent = NULL;
221     char* parentFigure = NULL;
222
223     double* z = NULL;
224     double* colormap = NULL;
225     double currentZ = 0.;
226
227     int numX = 0;
228     int* piNumX = &numX;
229     int numY = 0;
230     int* piNumY = &numY;
231     int colormapSize = 0;
232     int* piColormapSize = &colormapSize;
233
234     int bufferOffset = 0;
235
236     getGraphicObjectProperty(id, __GO_PARENT__, jni_string, (void**) &parent);
237
238     /* Temporary: to avoid getting a null parent_figure property when the object is built */
239     if (strcmp(parent, "") == 0)
240     {
241         return;
242     }
243
244     getGraphicObjectProperty(id, __GO_PARENT_FIGURE__, jni_string, (void**) &parentFigure);
245
246     getGraphicObjectProperty(parentFigure, __GO_COLORMAP__, jni_double_vector, (void**) &colormap);
247     getGraphicObjectProperty(parentFigure, __GO_COLORMAP_SIZE__, jni_int, (void**) &piColormapSize);
248
249     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_X__, jni_int, (void**) &piNumX);
250     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_Y__, jni_int, (void**) &piNumY);
251
252     getGraphicObjectProperty(id, __GO_DATA_MODEL_Z__, jni_double_vector, (void**) &z);
253
254     /* In order not to access invalid data when reading the last line's last element */
255     if (numX < 2)
256     {
257         return;
258     }
259
260 #if PER_VERTEX_VALUES
261     for (int j = 0; j < numY-1; j++)
262     {
263         for (int i = 0; i < numX-1; i++)
264         {
265             currentZ = z[i*(numY-1)+(numY-2-j)];
266
267             ColorComputer::getDirectColor((double) currentZ - 1.0, colormap, colormapSize, &buffer[bufferOffset]);
268
269             if (elementsSize == 4)
270             {
271                 buffer[bufferOffset+3] = 1.0;
272             }
273
274             bufferOffset += elementsSize;
275         }
276
277         /* Last element (same as the above loop's last) */
278         currentZ  = z[(numX-2)*(numY-1)+(numY-2-j)];
279
280         ColorComputer::getDirectColor((double) currentZ - 1.0, colormap, colormapSize, &buffer[bufferOffset]);
281
282         if (elementsSize == 4)
283         {
284             buffer[bufferOffset+3] = 1.0;
285         }
286
287         bufferOffset += elementsSize;
288     }
289
290     /* Last line */
291     for (int i = 0; i < numX-1; i++)
292     {
293         currentZ = z[(numY-1)*i+0];
294
295         ColorComputer::getDirectColor((double) currentZ - 1.0, colormap, colormapSize, &buffer[bufferOffset]);
296
297         bufferOffset += elementsSize;
298
299         if (elementsSize == 4)
300         {
301             buffer[bufferOffset+3] = 1.0;
302         }
303     }
304
305     /* Last element (same as the above loop's last) */
306     currentZ  = z[(numX-2)*(numY-1)+0];
307
308     ColorComputer::getDirectColor((double) currentZ - 1.0, colormap, colormapSize, &buffer[bufferOffset]);
309
310     if (elementsSize == 4)
311     {
312         buffer[bufferOffset+3] = 1.0;
313     }
314
315 #else
316
317     for (int j = 0; j < numY-1; j++)
318     {
319         for (int i = 0; i < numX-1; i++)
320         {
321             float facetColor[3];
322
323             currentZ = z[i*(numY-1)+(numY-2-j)];
324
325             ColorComputer::getDirectColor((double) currentZ - 1.0, colormap, colormapSize, facetColor);
326
327             writeFacetColorToBuffer(buffer, bufferOffset, facetColor, elementsSize);
328
329             bufferOffset += 4*elementsSize;
330         }
331     }
332
333 #endif
334 }
335
336 /*
337  * To do: merge with NgonGridDataDecomposer::fillIndices as these functions perform a lot of work in
338  * a redundant way.
339  */
340 int NgonGridMatplotDataDecomposer::fillIndices(char* id, int* buffer, int bufferLength, int logMask)
341 {
342     double* x = NULL;
343     double* y = NULL;
344     double* z = NULL;
345     double zShift = 0.0;
346     double* pdZShift = &zShift;
347
348     int numX = 0;
349     int* piNumX = &numX;
350     int numY = 0;
351     int* piNumY = &numY;
352
353     int numberIndices = 0;
354
355     NgonGridMatplotDataDecomposer* decomposer = get();
356
357     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_X__, jni_int, (void**) &piNumX);
358     getGraphicObjectProperty(id, __GO_DATA_MODEL_NUM_Y__, jni_int, (void**) &piNumY);
359
360     /* 0 indices if less than 2 points along either dimension */
361     if (numX < 2 || numY < 2)
362     {
363         return 0;
364     }
365
366     getGraphicObjectProperty(id, __GO_DATA_MODEL_X__, jni_double_vector, (void**) &x);
367     getGraphicObjectProperty(id, __GO_DATA_MODEL_Y__, jni_double_vector, (void**) &y);
368     getGraphicObjectProperty(id, __GO_DATA_MODEL_Z__, jni_double_vector, (void**) &z);
369
370     getGraphicObjectProperty(id, __GO_DATA_MODEL_Z_COORDINATES_SHIFT__, jni_double, (void**) &pdZShift);
371
372     /*
373      * The per-node value flag is set to 0 as for Matplot objects grid values are specified per-facet.
374      * However, it not used at all when determining facet validity and hence is only informative.
375      */
376     numberIndices = decomposer->fillTriangleIndices(buffer, bufferLength, logMask, x, y, &zShift, z, 0, numX, numY);
377
378     return numberIndices;
379 }
380
381 int NgonGridMatplotDataDecomposer::isFacetValid(double* z, double* values, int perNodeValues, int numX, int numY, int i, int j, int logUsed, int currentEdgeValid, int* nextEdgeValid)
382 {
383     double zij = 0.;
384     int facetValid = 0;
385
386     zij = getZCoordinate(z, numX, numY, i, j, logUsed);
387
388     facetValid = DecompositionUtils::isValid(zij);
389
390     if (logUsed)
391     {
392         facetValid &= DecompositionUtils::isLogValid(zij);
393     }
394
395     /* Transposed relative to Grayplot */
396     facetValid &= DecompositionUtils::isValid(values[getPointIndex(numY-1, numX-1, numY-2-j, i)]);
397
398     /* Edge validity is always 1 since it is not used at all to determine facet validity for Matplot decomposition */
399     *nextEdgeValid = 1;
400
401     return facetValid;
402 }
403
404 int NgonGridMatplotDataDecomposer::isFacetEdgeValid(double* z, double* values, int perNodeValues, int numX, int numY, int i, int j, int logUsed)
405 {
406     /* Always considered valid since not used at all to determine facet validity */
407     return 1;
408 }
409