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