2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2012 - Scilab Enterprises - Clement DAVID
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
15 #define M_PI 3.14159265358979323846
19 #include "dynlib_scicos_blocks.h"
23 #include "elementary_functions.h"
25 #include "setGraphicObjectProperty.h"
26 #include "getGraphicObjectProperty.h"
27 #include "graphicObjectProperties.h"
28 #include "createGraphicObject.h"
30 #include "CurrentFigure.h"
32 #include "scicos_block4.h"
35 #include "localization.h"
37 #include "strdup_windows.h"
40 #include "FigureList.h"
41 #include "BuildObjects.h"
42 #include "AxesModel.h"
44 /*****************************************************************************
45 * Internal container structure
46 ****************************************************************************/
61 char const* cachedFigureUID;
63 char **cachedArcsUIDs;
68 * Get (and allocate on demand) the internal data used on this scope
69 * \param block the block
70 * \return the scope data
72 static sco_data *getScoData(scicos_block * block);
75 * Release any internal data
77 * \param block the block
79 static void freeScoData(scicos_block * block);
82 * Append the data to the current data
84 * \param block the block
88 static void appendData(scicos_block * block, double *x, double *y);
91 * Push the block data to the polyline
93 * \param block the block
94 * \param row the selected row
97 static BOOL pushData(scicos_block * block, int row);
99 /*****************************************************************************
101 ****************************************************************************/
104 * Get (and allocate on demand) the figure associated with the block
105 * \param block the block
106 * \return a valid figure UID or NULL on error
108 static char const* getFigure(scicos_block * block);
111 * Get (and allocate on demand) the axe associated with the input
113 * \param pFigureUID the parent figure UID
114 * \param block the block
115 * \param input the current input index (0-indexed)
116 * \return a valid axe UID or NULL on error
118 static char *getAxe(char const* pFigureUID, scicos_block * block);
121 * Get (and allocate on demand) the arc associated with the row
123 * \param pAxeUID the parent axe UID
124 * \param block the block
125 * \param row the current row index (0-indexed)
126 * \return a valid polyline UID or NULL on error
128 static char *getArc(char *pAxeUID, scicos_block * block, int row);
133 * \param block the block
135 static BOOL setBounds(scicos_block * block);
137 /*****************************************************************************
138 * Simulation function
139 ****************************************************************************/
141 /** \fn void bouncexy(scicos_block * block,int flag)
142 \brief the computational function
143 \param block A pointer to a scicos_block
144 \param flag An int which indicates the state of the block (init, update, ending)
146 SCICOS_BLOCKS_IMPEXP void bouncexy(scicos_block * block, scicos_flag flag)
148 char const* pFigureUID;
159 sco = getScoData(block);
164 pFigureUID = getFigure(block);
165 if (pFigureUID == NULL)
173 pFigureUID = getFigure(block);
174 if (pFigureUID == NULL)
181 appendData(block, (double *)block->inptr[0], (double *)block->inptr[1]);
182 for (j = 0; j < block->insz[0]; j++)
184 result = pushData(block, j);
187 Coserror("%s: unable to push some data.", "bouncexy");
202 /*-------------------------------------------------------------------------*/
204 /*****************************************************************************
206 * Container management
208 ****************************************************************************/
210 static sco_data *getScoData(scicos_block * block)
212 sco_data *sco = (sco_data *) * (block->work);
221 sco = (sco_data *) MALLOC(sizeof(sco_data));
223 goto error_handler_sco;
225 sco->internal.ballsSize = (double *)CALLOC(block->insz[0], sizeof(double));
226 if (sco->internal.ballsSize == NULL)
227 goto error_handler_ballsSize;
228 for (i = 0; i < block->insz[0]; i++)
230 sco->internal.ballsSize[i] = block->z[6 * i + 2];
233 sco->internal.data = (double **)CALLOC(block->insz[0], sizeof(double *));
234 if (sco->internal.data == NULL)
235 goto error_handler_data;
237 for (i = 0; i < block->insz[0]; i++)
239 sco->internal.data[i] = (double *)CALLOC(3, sizeof(double));
240 if (sco->internal.data[i] == NULL)
241 goto error_handler_data_i;
244 sco->scope.cachedFigureUID = NULL;
245 sco->scope.cachedAxeUID = NULL;
247 sco->scope.cachedArcsUIDs = (char **)CALLOC(block->insz[0], sizeof(char *));
249 *(block->work) = sco;
255 * Error management (out of normal flow)
258 error_handler_data_i:
259 for (j = 0; j < i; j++)
261 FREE(sco->internal.data[i]);
263 FREE(sco->internal.data);
265 FREE(sco->internal.ballsSize);
266 error_handler_ballsSize:
274 static void freeScoData(scicos_block * block)
276 sco_data *sco = (sco_data *) * (block->work);
281 for (i = 0; i < block->insz[0]; i++)
283 FREE(sco->internal.data[i]);
286 FREE(sco->internal.data);
287 FREE(sco->internal.ballsSize);
289 for (i = 0; i < block->insz[0]; i++)
291 FREE(sco->scope.cachedArcsUIDs[i]);
292 sco->scope.cachedArcsUIDs[i] = NULL;
294 FREE(sco->scope.cachedAxeUID);
295 sco->scope.cachedAxeUID = NULL;
301 static void appendData(scicos_block * block, double *x, double *y)
304 double *upperLeftPoint;
306 sco_data *sco = (sco_data *) * (block->work);
313 for (i = 0; i < block->insz[0]; i++)
315 upperLeftPoint = sco->internal.data[i];
316 ballSize = sco->internal.ballsSize[i];
318 upperLeftPoint[0] = x[i] - (ballSize / 2); // x
319 upperLeftPoint[1] = y[i] + (ballSize / 2); // y
320 upperLeftPoint[2] = 0; // z
325 static BOOL pushData(scicos_block * block, int row)
327 char const* pFigureUID;
331 double *upperLeftPoint;
334 pFigureUID = getFigure(block);
335 pAxeUID = getAxe(pFigureUID, block);
336 pArcUID = getArc(pAxeUID, block, row);
338 sco = getScoData(block);
342 upperLeftPoint = sco->internal.data[row];
343 return setGraphicObjectProperty(pArcUID, __GO_UPPER_LEFT_POINT__, upperLeftPoint, jni_double_vector, 3);
346 /*****************************************************************************
350 ****************************************************************************/
352 /*****************************************************************************
356 ****************************************************************************/
358 static char const* getFigure(scicos_block * block)
361 char const* pFigureUID = NULL;
366 sco_data *sco = (sco_data *) * (block->work);
368 // fast path for an existing object
369 if (sco->scope.cachedFigureUID != NULL)
371 return sco->scope.cachedFigureUID;
374 figNum = block->ipar[0];
376 // with a negative id, use the block number indexed from a constant.
379 figNum = 20000 + get_block_number();
382 pFigureUID = getFigureFromIndex(figNum);
384 if (pFigureUID == NULL)
386 pFigureUID = createNewFigureWithAxes();
387 setGraphicObjectProperty(pFigureUID, __GO_ID__, &figNum, jni_int, 1);
389 // the stored uid is a reference to the figure map, not to the current figure
390 pFigureUID = getFigureFromIndex(figNum);
391 sco->scope.cachedFigureUID = pFigureUID;
393 // allocate the axes through the getter
394 pAxe = getAxe(pFigureUID, block);
397 * Setup according to block settings
399 setGraphicObjectProperty(pAxe, __GO_BOX_TYPE__, &i__1, jni_int, 1);
400 setGraphicObjectProperty(pAxe, __GO_ISOVIEW__, &b_true, jni_bool, 1);
405 if (sco->scope.cachedFigureUID == NULL)
407 sco->scope.cachedFigureUID = pFigureUID;
412 static char *getAxe(char const* pFigureUID, scicos_block * block)
417 sco_data *sco = (sco_data *) * (block->work);
419 // fast path for an existing object
420 if (sco->scope.cachedAxeUID != NULL)
422 return sco->scope.cachedAxeUID;
425 pAxe = findChildWithKindAt(pFigureUID, __GO_AXES__, 0);
428 * Allocate if necessary
432 cloneAxesModel(pFigureUID);
433 pAxe = findChildWithKindAt(pFigureUID, __GO_AXES__, 0);
437 * Setup on first access
441 // allocate the polylines through the getter
442 for (i = 0; i < block->insz[0]; i++)
444 getArc(pAxe, block, i);
449 * then cache with local storage
451 if (pAxe != NULL && sco->scope.cachedAxeUID == NULL)
453 sco->scope.cachedAxeUID = strdup(pAxe);
454 releaseGraphicObjectProperty(__GO_PARENT__, pAxe, jni_string, 1);
456 return sco->scope.cachedAxeUID;
459 static char *getArc(char *pAxeUID, scicos_block * block, int row)
461 static double d__0 = 0.0;
462 static double d__2PI = 2 * M_PI;
463 static BOOL b__true = TRUE;
468 sco_data *sco = (sco_data *) * (block->work);
470 // fast path for an existing object
471 if (sco->scope.cachedArcsUIDs != NULL && sco->scope.cachedArcsUIDs[row] != NULL)
473 return sco->scope.cachedArcsUIDs[row];
476 pArc = findChildWithKindAt(pAxeUID, __GO_ARC__, row);
479 * Allocate if necessary
483 pArc = createGraphicObject(__GO_ARC__);
487 createDataObject(pArc, __GO_ARC__);
488 setGraphicObjectRelationship(pAxeUID, pArc);
493 * Setup on first access
497 setGraphicObjectProperty(pArc, __GO_START_ANGLE__, &d__0, jni_double, 1);
498 setGraphicObjectProperty(pArc, __GO_END_ANGLE__, &d__2PI, jni_double, 1);
500 color = block->ipar[2 + row];
501 setGraphicObjectProperty(pArc, __GO_BACKGROUND__, &color, jni_int, 1);
503 setGraphicObjectProperty(pArc, __GO_WIDTH__, &sco->internal.ballsSize[row], jni_double, 1);
504 setGraphicObjectProperty(pArc, __GO_HEIGHT__, &sco->internal.ballsSize[row], jni_double, 1);
506 setGraphicObjectProperty(pArc, __GO_FILL_MODE__, &b__true, jni_bool, 1);
509 int iClipState = 1; //on
510 setGraphicObjectProperty(pArc, __GO_CLIP_STATE__, &iClipState, jni_int, 1);
515 * then cache with local storage
517 if (pArc != NULL && sco->scope.cachedArcsUIDs != NULL && sco->scope.cachedArcsUIDs[row] == NULL)
519 sco->scope.cachedArcsUIDs[row] = strdup(pArc);
520 releaseGraphicObjectProperty(__GO_PARENT__, pArc, jni_string, 1);
522 return sco->scope.cachedArcsUIDs[row];
525 static BOOL setBounds(scicos_block * block)
527 char const* pFigureUID;
530 double dataBounds[6];
532 dataBounds[0] = block->rpar[0]; // xMin
533 dataBounds[1] = block->rpar[1]; // xMax
534 dataBounds[2] = block->rpar[2]; // yMin
535 dataBounds[3] = block->rpar[3]; // yMax
536 dataBounds[4] = -1.0; // zMin
537 dataBounds[5] = 1.0; // zMax
539 pFigureUID = getFigure(block);
540 pAxeUID = getAxe(pFigureUID, block);
542 return setGraphicObjectProperty(pAxeUID, __GO_DATA_BOUNDS__, dataBounds, jni_double_vector, 6);