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