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