22355b2c98ea3d3a93d201cf41065df1fe1cbebd
[scilab.git] / scilab / modules / scicos_blocks / src / c / cmatview.c
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2011 - Scilab Enterprises - Clement DAVID
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 <stdlib.h>
14 #include <math.h>
15 #include <string.h>
16
17 #include "dynlib_scicos_blocks.h"
18 #include "scoUtils.h"
19
20 #include "MALLOC.h"
21 #include "core_math.h"
22 #include "elementary_functions.h"
23
24 #include "getGraphicObjectProperty.h"
25 #include "setGraphicObjectProperty.h"
26 #include "graphicObjectProperties.h"
27 #include "createGraphicObject.h"
28
29 #include "CurrentFigure.h"
30
31 #include "scicos_block4.h"
32 #include "scicos.h"
33 #include "math.h"
34
35 #include "localization.h"
36 #ifdef _MSC_VER
37 #include "strdup_windows.h"
38 #endif
39
40 #include "FigureList.h"
41 #include "BuildObjects.h"
42 #include "AxesModel.h"
43
44 /*****************************************************************************
45  * Internal container structure
46  ****************************************************************************/
47
48 /**
49  * Container structure
50  */
51 typedef struct
52 {
53     struct
54     {
55         char const* cachedFigureUID;
56         char *cachedAxeUID;
57         char *cachedGrayplotUID;
58     } scope;
59 } sco_data;
60
61 /**
62  * Get (and allocate on demand) the internal data used on this scope
63  * \param block the block
64  * \return the scope data
65  */
66 static sco_data *getScoData(scicos_block * block);
67
68 /**
69  * Release any internal data
70  *
71  * \param block the block
72  */
73 static void freeScoData(scicos_block * block);
74
75 /**
76  * Push the block data to the polyline
77  *
78  * \param data the data to push
79  *
80  */
81 static BOOL pushData(scicos_block * block, double *data);
82
83 /*****************************************************************************
84  * Graphics utils
85  ****************************************************************************/
86
87 /**
88  * Get (and allocate on demand) the figure associated with the block
89  * \param block the block
90  * \return a valid figure UID or NULL on error
91  */
92 static char const* getFigure(scicos_block * block);
93
94 /**
95  * Get (and allocate on demand) the axe associated with the input
96  *
97  * \param pFigureUID the parent figure UID
98  * \param block the block
99  * \return a valid axe UID or NULL on error
100  */
101 static char *getAxe(char const* pFigureUID, scicos_block * block);
102
103 /**
104  * Get (and allocate on demand) the grayplot
105  *
106  * \param pAxeUID the parent axe UID
107  * \param block the block
108  * \return a valid grayplot UID or NULL on error
109  */
110 static char *getGrayplot(char *pAxeUID, scicos_block * block);
111
112 /**
113  * Set the grayplot and axes bounds
114  *
115  * \param block the block
116  * \param pAxeUID the axe
117  * \param pGrayplotUID the grayplot
118  */
119 static BOOL setBounds(scicos_block * block, char *pAxeUID, char *pGrayplotUID);
120
121 /**
122  * Set the grayplot default values
123  *
124  * \param block the block
125  * \param pGrayplotUID the grayplot
126  */
127 static BOOL setDefaultValues(scicos_block * block, char *pGrayplotUID);
128
129 /*****************************************************************************
130  * Simulation function
131  ****************************************************************************/
132
133 /** \fn void cmatview(scicos_block * block,int flag)
134     \brief the computational function
135     \param block A pointer to a scicos_block
136     \param flag An int which indicates the state of the block (init, update, ending)
137 */
138 SCICOS_BLOCKS_IMPEXP void cmatview(scicos_block * block, scicos_flag flag)
139 {
140     char const* pFigureUID;
141
142     double *u;
143     sco_data *sco;
144
145     BOOL result;
146
147     switch (flag)
148     {
149
150         case Initialization:
151             sco = getScoData(block);
152             if (sco == NULL)
153             {
154                 set_block_error(-5);
155                 break;
156             }
157             pFigureUID = getFigure(block);
158             if (pFigureUID == NULL)
159             {
160                 // allocation error
161                 set_block_error(-5);
162                 break;
163             }
164             break;
165
166         case StateUpdate:
167             pFigureUID = getFigure(block);
168             if (pFigureUID == NULL)
169             {
170                 // allocation error
171                 set_block_error(-5);
172                 break;
173             }
174
175             u = GetRealInPortPtrs(block, 1);
176
177             result = pushData(block, u);
178             if (result == FALSE)
179             {
180                 Coserror("%s: unable to push some data.", "cmatview");
181                 break;
182             }
183             break;
184
185         case Ending:
186             freeScoData(block);
187             break;
188
189         default:
190             break;
191     }
192 }
193
194 /*-------------------------------------------------------------------------*/
195
196 /*****************************************************************************
197  *
198  * Container management
199  *
200  ****************************************************************************/
201
202 static sco_data *getScoData(scicos_block * block)
203 {
204     sco_data *sco = (sco_data *) * (block->work);
205
206     if (sco == NULL)
207     {
208         /*
209          * Data allocation
210          */
211
212         sco = (sco_data *) MALLOC(sizeof(sco_data));
213         if (sco == NULL)
214             goto error_handler_sco;
215
216         sco->scope.cachedFigureUID = NULL;
217         sco->scope.cachedAxeUID = NULL;
218         sco->scope.cachedGrayplotUID = NULL;
219
220         *(block->work) = sco;
221     }
222
223     return sco;
224
225     /*
226      * Error management (out of normal flow)
227      */
228
229 error_handler_sco:
230     // allocation error
231     set_block_error(-5);
232     return NULL;
233 }
234
235 static void freeScoData(scicos_block * block)
236 {
237     sco_data *sco = (sco_data *) * (block->work);
238
239     if (sco != NULL)
240     {
241         FREE(sco->scope.cachedAxeUID);
242         FREE(sco->scope.cachedGrayplotUID);
243     }
244
245     FREE(sco);
246 }
247
248 static BOOL pushData(scicos_block * block, double *data)
249 {
250     char const* pFigureUID;
251     char *pAxeUID;
252     char *pGrayplotUID;
253
254     BOOL result;
255     int i;
256
257     int m, n;
258     double alpha, beta;
259     double *scaledData;
260
261     pFigureUID = getFigure(block);
262     pAxeUID = getAxe(pFigureUID, block);
263     pGrayplotUID = getGrayplot(pAxeUID, block);
264
265     m = GetInPortSize(block, 1, 1);
266     n = GetInPortSize(block, 1, 2);
267     if (m * n <= 0)
268     {
269         set_block_error(-5);
270         return FALSE;
271     }
272
273     /*
274      * Scale the data
275      */
276     alpha = block->rpar[0];
277     beta = block->rpar[1];
278
279     scaledData = (double *)MALLOC(m * n * sizeof(double));
280     if (scaledData == NULL)
281     {
282         return FALSE;
283     }
284
285     for (i = 0; i < m * n; i++)
286     {
287         scaledData[i] = floor(alpha * data[i] + beta);
288     }
289
290     result = setGraphicObjectProperty(pGrayplotUID, __GO_DATA_MODEL_Z__, scaledData, jni_double_vector, m * n);
291     FREE(scaledData);
292
293     return result;
294 }
295
296 /*****************************************************************************
297  *
298  * Graphic utils
299  *
300  ****************************************************************************/
301
302 /*****************************************************************************
303  *
304  * Graphic
305  *
306  ****************************************************************************/
307
308 static char const* getFigure(scicos_block * block)
309 {
310     signed int figNum;
311     char const* pFigureUID = NULL;
312     char *pAxe = NULL;
313     int i__1 = 1;
314     sco_data *sco = (sco_data *) * (block->work);
315
316     // fast path for an existing object
317     if (sco->scope.cachedFigureUID != NULL)
318     {
319         return sco->scope.cachedFigureUID;
320     }
321
322     figNum = block->ipar[0];
323
324     // with a negative id, use the block number indexed from a constant.
325     if (figNum < 0)
326     {
327         figNum = 20000 + get_block_number();
328     }
329
330     pFigureUID = getFigureFromIndex(figNum);
331     // create on demand
332     if (pFigureUID == NULL)
333     {
334         pFigureUID = createNewFigureWithAxes();
335         setGraphicObjectProperty(pFigureUID, __GO_ID__, &figNum, jni_int, 1);
336
337         // the stored uid is a reference to the figure map, not to the current figure
338         pFigureUID = getFigureFromIndex(figNum);
339         sco->scope.cachedFigureUID = pFigureUID;
340
341         setGraphicObjectProperty(pFigureUID, __GO_COLORMAP__, &block->rpar[2], jni_double_vector, block->ipar[2]);
342
343         // allocate the axes through the getter
344         pAxe = getAxe(pFigureUID, block);
345
346         /*
347          * Setup according to block settings
348          */
349         setLabel(pAxe, __GO_X_AXIS_LABEL__, "x");
350         setLabel(pAxe, __GO_Y_AXIS_LABEL__, "y");
351
352         setGraphicObjectProperty(pAxe, __GO_X_AXIS_VISIBLE__, &i__1, jni_bool, 1);
353         setGraphicObjectProperty(pAxe, __GO_Y_AXIS_VISIBLE__, &i__1, jni_bool, 1);
354     }
355
356     if (pFigureUID != NULL && sco->scope.cachedFigureUID == NULL)
357     {
358         sco->scope.cachedFigureUID = pFigureUID;
359     }
360     return pFigureUID;
361 }
362
363 static char *getAxe(char const* pFigureUID, scicos_block * block)
364 {
365     char *pAxe;
366     sco_data *sco = (sco_data *) * (block->work);
367
368     // fast path for an existing object
369     if (sco->scope.cachedAxeUID != NULL)
370     {
371         return sco->scope.cachedAxeUID;
372     }
373
374     pAxe = findChildWithKindAt(pFigureUID, __GO_AXES__, 0);
375
376     /*
377      * Allocate if necessary
378      */
379     if (pAxe == NULL)
380     {
381         cloneAxesModel(pFigureUID);
382         pAxe = findChildWithKindAt(pFigureUID, __GO_AXES__, 0);
383     }
384
385     /*
386      * Setup on first access
387      */
388     if (pAxe != NULL)
389     {
390         getGrayplot(pAxe, block);
391     }
392
393
394     /*
395      * then cache with local storage
396      */
397     if (pAxe != NULL && sco->scope.cachedAxeUID == NULL)
398     {
399         sco->scope.cachedAxeUID = strdup(pAxe);
400         releaseGraphicObjectProperty(__GO_PARENT__, pAxe, jni_string, 1);
401     }
402     return sco->scope.cachedAxeUID;
403 }
404
405 static char *getGrayplot(char *pAxeUID, scicos_block * block)
406 {
407     char *pGrayplot;
408     int i__0 = 0;
409
410     sco_data *sco = (sco_data *) * (block->work);
411
412     // fast path for an existing object
413     if (sco->scope.cachedGrayplotUID != NULL)
414     {
415         return sco->scope.cachedGrayplotUID;
416     }
417
418     pGrayplot = findChildWithKindAt(pAxeUID, __GO_GRAYPLOT__, 0);
419
420     /*
421      * Allocate if necessary
422      */
423     if (pGrayplot == NULL)
424     {
425         pGrayplot = createGraphicObject(__GO_GRAYPLOT__);
426
427         if (pGrayplot != NULL)
428         {
429             createDataObject(pGrayplot, __GO_GRAYPLOT__);
430             setGraphicObjectRelationship(pAxeUID, pGrayplot);
431         }
432     }
433
434     /*
435      * Setup on first access
436      */
437     if (pGrayplot != NULL)
438     {
439
440         setGraphicObjectProperty(pGrayplot, __GO_DATA_MAPPING__, &i__0, jni_int, 1);
441         setBounds(block, pAxeUID, pGrayplot);
442         setDefaultValues(block, pGrayplot);
443
444         {
445             int iClipState = 1; //on
446             setGraphicObjectProperty(pGrayplot, __GO_CLIP_STATE__, &iClipState, jni_int, 1);
447         }
448     }
449
450     /*
451      * then cache with a local storage
452      */
453     if (pGrayplot != NULL && sco->scope.cachedGrayplotUID == NULL)
454     {
455         sco->scope.cachedGrayplotUID = strdup(pGrayplot);
456         releaseGraphicObjectProperty(__GO_PARENT__, pGrayplot, jni_string, 1);
457     }
458     return sco->scope.cachedGrayplotUID;
459 }
460
461 static BOOL setBounds(scicos_block * block, char *pAxeUID, char *pGrayplotUID)
462 {
463     BOOL result;
464
465     int gridSize[4];
466     double dataBounds[6];
467
468     int m, n;
469
470     m = GetInPortSize(block, 1, 1);
471     n = GetInPortSize(block, 1, 2);
472
473     gridSize[0] = m;
474     gridSize[1] = 1;
475     gridSize[2] = n;
476     gridSize[3] = 1;
477
478     dataBounds[0] = 0;          // xMin
479     dataBounds[1] = (double)m;  // xMax
480     dataBounds[2] = 0;          // yMin
481     dataBounds[3] = (double)n;  // yMax
482     dataBounds[4] = -1.0;       // zMin
483     dataBounds[5] = 1.0;        // zMax
484
485     result = setGraphicObjectProperty(pGrayplotUID, __GO_DATA_MODEL_GRID_SIZE__, gridSize, jni_int_vector, 4);
486     result &= setGraphicObjectProperty(pAxeUID, __GO_DATA_BOUNDS__, dataBounds, jni_double_vector, 6);
487
488     return result;
489 }
490
491 static BOOL setDefaultValues(scicos_block * block, char *pGrayplotUID)
492 {
493     int m, n, len;
494     int i;
495     double *values;
496
497     BOOL result;
498
499     m = GetInPortSize(block, 1, 1);
500     n = GetInPortSize(block, 1, 2);
501
502     len = Max(m, n);
503
504     values = (double *)CALLOC(n * m, sizeof(double));
505     if (values == NULL)
506     {
507         return FALSE;
508     }
509
510     result = setGraphicObjectProperty(pGrayplotUID, __GO_DATA_MODEL_Z__, values, jni_double_vector, m * n);
511
512     for (i = 1; i <= len; i++)
513     {
514         values[i] = (double)i;
515     }
516     result &= setGraphicObjectProperty(pGrayplotUID, __GO_DATA_MODEL_X__, values, jni_double_vector, m);
517     result &= setGraphicObjectProperty(pGrayplotUID, __GO_DATA_MODEL_Y__, values, jni_double_vector, n);
518
519     FREE(values);
520     return result;
521 }