2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2011 - 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 #include "dynlib_scicos_blocks.h"
19 #include "elementary_functions.h"
21 #include "getGraphicObjectProperty.h"
22 #include "setGraphicObjectProperty.h"
23 #include "graphicObjectProperties.h"
24 #include "createGraphicObject.h"
26 #include "CurrentFigure.h"
28 #include "scicos_block4.h"
31 #include "localization.h"
33 #include "strdup_windows.h"
36 #include "FigureList.h"
37 #include "BuildObjects.h"
38 #include "AxesModel.h"
40 /*****************************************************************************
41 * Internal container structure
42 ****************************************************************************/
52 int maxNumberOfPoints;
58 char const* cachedFigureUID;
60 char **cachedPolylinesUIDs;
65 * Get (and allocate on demand) the internal data used on this scope
66 * \param block the block
67 * \return the scope data
69 static sco_data *getScoData(scicos_block * block);
72 * Release any internal data
74 * \param block the block
76 static void freeScoData(scicos_block * block);
79 * Append the data to the current data
81 * \param block the block
86 static void appendData(scicos_block * block, double *x, double *y, double *z);
89 * Push the block data to the polyline
91 * \param block the block
92 * \param row the selected row
95 static BOOL pushData(scicos_block * block, int row);
97 /*****************************************************************************
99 ****************************************************************************/
102 * Get (and allocate on demand) the figure associated with the block
103 * \param block the block
104 * \return a valid figure UID or NULL on error
106 static char const* getFigure(scicos_block * block);
109 * Get (and allocate on demand) the axe associated with the input
111 * \param pFigureUID the parent figure UID
112 * \param block the block
113 * \param input the current input index (0-indexed)
114 * \return a valid axe UID or NULL on error
116 static char *getAxe(char const* pFigureUID, scicos_block * block);
119 * Get (and allocate on demand) the polyline associated with the row
121 * \param pAxeUID the parent axe UID
122 * \param block the block
123 * \param row the current row index (0-indexed)
124 * \return a valid polyline UID or NULL on error
126 static char *getPolyline(char *pAxeUID, scicos_block * block, int row);
129 * Set the polylines bounds
131 * \param block the block
133 static BOOL setPolylinesBounds(scicos_block * block);
135 /*****************************************************************************
136 * Simulation function
137 ****************************************************************************/
139 /** \fn void cmscope(scicos_block * block,int flag)
140 \brief the computational function
141 \param block A pointer to a scicos_block
142 \param flag An int which indicates the state of the block (init, update, ending)
144 SCICOS_BLOCKS_IMPEXP void canimxy3d(scicos_block * block, scicos_flag flag)
146 char const* pFigureUID;
157 sco = getScoData(block);
163 pFigureUID = getFigure(block);
164 if (pFigureUID == NULL)
173 pFigureUID = getFigure(block);
174 if (pFigureUID == NULL)
181 appendData(block, block->inptr[0], block->inptr[1], block->inptr[2]);
182 for (j = 0; j < block->insz[0]; j++)
184 result = pushData(block, j);
187 Coserror("%s: unable to push some data.", "cscopxy3d");
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.numberOfPoints = 0;
226 sco->internal.maxNumberOfPoints = block->ipar[2];
228 sco->internal.data = (double ***)CALLOC(block->nin, sizeof(double **));
229 if (sco->internal.data == NULL)
230 goto error_handler_data;
232 for (i = 0; i < block->nin; i++)
234 sco->internal.data[i] = (double **)CALLOC(block->insz[i], sizeof(double *));
235 if (sco->internal.data[i] == NULL)
236 goto error_handler_data_i;
238 for (i = 0; i < block->nin; i++)
240 for (j = 0; j < block->insz[i]; j++)
242 sco->internal.data[i][j] = (double *)CALLOC(block->ipar[2], sizeof(double));
244 if (sco->internal.data[i][j] == NULL)
245 goto error_handler_data_ij;
249 sco->scope.cachedFigureUID = NULL;
250 sco->scope.cachedAxeUID = NULL;
252 sco->scope.cachedPolylinesUIDs = (char **)CALLOC(block->insz[0], sizeof(char **));
254 *(block->work) = sco;
260 * Error management (out of normal flow)
263 error_handler_data_ij:
264 for (k = 0; k < i; k++)
266 for (l = 0; l < j; l++)
268 FREE(sco->internal.data[k][l]);
272 error_handler_data_i:
273 for (j = 0; j < i; j++)
275 FREE(sco->internal.data[i]);
277 FREE(sco->internal.data);
286 static void freeScoData(scicos_block * block)
288 sco_data *sco = (sco_data *) * (block->work);
293 for (i = 0; i < block->nin; i++)
295 for (j = 0; j < block->insz[i]; j++)
297 FREE(sco->internal.data[i][j]);
299 FREE(sco->internal.data[i]);
302 FREE(sco->internal.data);
304 for (i = 0; i < block->insz[0]; i++)
306 FREE(sco->scope.cachedPolylinesUIDs[i]);
307 sco->scope.cachedPolylinesUIDs[i] = NULL;
309 FREE(sco->scope.cachedAxeUID);
310 sco->scope.cachedAxeUID = NULL;
316 static void appendData(scicos_block * block, double *x, double *y, double *z)
320 sco_data *sco = (sco_data *) * (block->work);
321 int maxNumberOfPoints = sco->internal.maxNumberOfPoints;
322 int numberOfPoints = sco->internal.numberOfPoints;
325 * Handle the case where the scope has more points than maxNumberOfPoints
327 if (sco != NULL && numberOfPoints >= maxNumberOfPoints)
329 unsigned int setLen = (unsigned int)maxNumberOfPoints - 1;
331 // on a full scope, push data
332 for (i = 0; i < block->insz[0]; i++)
334 memmove(sco->internal.data[0][i], &sco->internal.data[0][i][1], setLen * sizeof(double));
335 sco->internal.data[0][i][setLen] = x[i];
337 memmove(sco->internal.data[1][i], &sco->internal.data[1][i][1], setLen * sizeof(double));
338 sco->internal.data[1][i][setLen] = y[i];
340 memmove(sco->internal.data[2][i], &sco->internal.data[2][i][1], setLen * sizeof(double));
341 sco->internal.data[2][i][setLen] = z[i];
355 for (i = 0; i < block->insz[0]; i++)
357 for (setLen = maxNumberOfPoints - numberOfPoints - 1; setLen >= 0; setLen--)
359 sco->internal.data[0][i][numberOfPoints + setLen] = x[i];
360 sco->internal.data[1][i][numberOfPoints + setLen] = y[i];
361 sco->internal.data[2][i][numberOfPoints + setLen] = z[i];
365 sco->internal.numberOfPoints++;
369 static BOOL pushData(scicos_block * block, int row)
371 char const* pFigureUID;
382 pFigureUID = getFigure(block);
383 pAxeUID = getAxe(pFigureUID, block);
384 pPolylineUID = getPolyline(pAxeUID, block, row);
386 sco = getScoData(block);
390 // select the right input and row
391 x = sco->internal.data[0][row];
392 y = sco->internal.data[1][row];
393 z = sco->internal.data[2][row];
395 result &= setGraphicObjectProperty(pPolylineUID, __GO_DATA_MODEL_X__, x, jni_double_vector, sco->internal.maxNumberOfPoints);
396 result &= setGraphicObjectProperty(pPolylineUID, __GO_DATA_MODEL_Y__, y, jni_double_vector, sco->internal.maxNumberOfPoints);
397 result &= setGraphicObjectProperty(pPolylineUID, __GO_DATA_MODEL_Z__, z, jni_double_vector, sco->internal.maxNumberOfPoints);
402 /*****************************************************************************
406 ****************************************************************************/
409 * Set properties on the figure.
411 * \param pFigureUID the figure uid
412 * \param block the current block
414 static void setFigureSettings(char const* pFigureUID, scicos_block * block)
419 int *ipar = block->ipar;
420 int nipar = block->nipar;
422 win_pos[0] = ipar[nipar - 5];
423 win_pos[1] = ipar[nipar - 4];
424 win_dim[0] = ipar[nipar - 3];
425 win_dim[1] = ipar[nipar - 2];
427 if (win_pos[0] > 0 && win_pos[1] > 0)
429 setGraphicObjectProperty(pFigureUID, __GO_POSITION__, &win_pos, jni_int_vector, 2);
432 if (win_dim[0] > 0 && win_dim[1] > 0)
434 setGraphicObjectProperty(pFigureUID, __GO_SIZE__, &win_dim, jni_int_vector, 2);
438 /*****************************************************************************
442 ****************************************************************************/
444 static char const* getFigure(scicos_block * block)
447 char const* pFigureUID = NULL;
450 sco_data *sco = (sco_data *) * (block->work);
452 // fast path for an existing object
453 if (sco->scope.cachedFigureUID != NULL)
455 return sco->scope.cachedFigureUID;
458 figNum = block->ipar[0];
460 // with a negative id, use the block number indexed from a constant.
463 figNum = 20000 + get_block_number();
466 pFigureUID = getFigureFromIndex(figNum);
468 if (pFigureUID == NULL)
470 pFigureUID = createNewFigureWithAxes();
471 setGraphicObjectProperty(pFigureUID, __GO_ID__, &figNum, jni_int, 1);
473 // the stored uid is a reference to the figure map, not to the current figure
474 pFigureUID = getFigureFromIndex(figNum);
475 sco->scope.cachedFigureUID = pFigureUID;
477 // set configured parameters
478 setFigureSettings(pFigureUID, block);
480 // allocate the axes through the getter
481 pAxe = getAxe(pFigureUID, block);
484 * Setup according to block settings
486 setLabel(pAxe, __GO_X_AXIS_LABEL__, "x");
487 setLabel(pAxe, __GO_Y_AXIS_LABEL__, "y");
488 setLabel(pAxe, __GO_Z_AXIS_LABEL__, "z");
490 setGraphicObjectProperty(pAxe, __GO_X_AXIS_VISIBLE__, &i__1, jni_bool, 1);
491 setGraphicObjectProperty(pAxe, __GO_Y_AXIS_VISIBLE__, &i__1, jni_bool, 1);
492 setGraphicObjectProperty(pAxe, __GO_Z_AXIS_VISIBLE__, &i__1, jni_bool, 1);
494 setPolylinesBounds(block);
497 if (sco->scope.cachedFigureUID == NULL)
499 sco->scope.cachedFigureUID = pFigureUID;
504 static char *getAxe(char const* pFigureUID, scicos_block * block)
508 sco_data *sco = (sco_data *) * (block->work);
510 // fast path for an existing object
511 if (sco->scope.cachedAxeUID != NULL)
513 return sco->scope.cachedAxeUID;
516 pAxe = findChildWithKindAt(pFigureUID, __GO_AXES__, 0);
519 * Allocate if necessary
523 cloneAxesModel(pFigureUID);
524 pAxe = findChildWithKindAt(pFigureUID, __GO_AXES__, 0);
528 * Setup on first access
532 // allocate the polylines through the getter
533 for (i = 0; i < block->insz[0]; i++)
535 getPolyline(pAxe, block, i);
540 * then cache with a local storage
542 if (pAxe != NULL && sco->scope.cachedAxeUID == NULL)
544 sco->scope.cachedAxeUID = strdup(pAxe);
545 releaseGraphicObjectProperty(__GO_PARENT__, pAxe, jni_string, 1);
547 return sco->scope.cachedAxeUID;
550 static char *getPolyline(char *pAxeUID, scicos_block * block, int row)
553 static double d__0 = 0.0;
554 static BOOL b__true = TRUE;
558 double lineThickness;
560 sco_data *sco = (sco_data *) * (block->work);
562 // fast path for an existing object
563 if (sco->scope.cachedPolylinesUIDs != NULL && sco->scope.cachedPolylinesUIDs[row] != NULL)
565 return sco->scope.cachedPolylinesUIDs[row];
568 pPolyline = findChildWithKindAt(pAxeUID, __GO_POLYLINE__, row);
571 * Allocate if necessary
573 if (pPolyline == NULL)
575 pPolyline = createGraphicObject(__GO_POLYLINE__);
577 if (pPolyline != NULL)
579 createDataObject(pPolyline, __GO_POLYLINE__);
580 setGraphicObjectRelationship(pAxeUID, pPolyline);
585 * Setup on first access
587 if (pPolyline != NULL)
590 * Default setup (will crash if removed)
593 int polylineSize[2] = { 1, block->ipar[2] };
594 setGraphicObjectProperty(pPolyline, __GO_DATA_MODEL_NUM_ELEMENTS_ARRAY__, polylineSize, jni_int_vector, 2);
597 setGraphicObjectProperty(pPolyline, __GO_DATA_MODEL_X__, &d__0, jni_double_vector, 1);
598 setGraphicObjectProperty(pPolyline, __GO_DATA_MODEL_Y__, &d__0, jni_double_vector, 1);
599 setGraphicObjectProperty(pPolyline, __GO_DATA_MODEL_Z__, &d__0, jni_double_vector, 1);
601 color = block->ipar[3 + row];
602 markSize = block->ipar[3 + block->ipar[1] + row];
603 lineThickness = (double)markSize;
606 setGraphicObjectProperty(pPolyline, __GO_LINE_MODE__, &b__true, jni_bool, 1);
608 setGraphicObjectProperty(pPolyline, __GO_LINE_COLOR__, &color, jni_int, 1);
609 setGraphicObjectProperty(pPolyline, __GO_LINE_THICKNESS__, &lineThickness, jni_double, 1);
614 setGraphicObjectProperty(pPolyline, __GO_MARK_MODE__, &b__true, jni_bool, 1);
616 setGraphicObjectProperty(pPolyline, __GO_MARK_STYLE__, &color, jni_int, 1);
617 setGraphicObjectProperty(pPolyline, __GO_MARK_SIZE__, &markSize, jni_int, 1);
621 int iClipState = 1; //on
622 setGraphicObjectProperty(pPolyline, __GO_CLIP_STATE__, &iClipState, jni_int, 1);
627 * then cache with a local storage
629 if (pPolyline != NULL && sco->scope.cachedPolylinesUIDs != NULL && sco->scope.cachedPolylinesUIDs[row] == NULL)
631 sco->scope.cachedPolylinesUIDs[row] = strdup(pPolyline);
632 releaseGraphicObjectProperty(__GO_PARENT__, pPolyline, jni_string, 1);
634 return sco->scope.cachedPolylinesUIDs[row];
637 static BOOL setPolylinesBounds(scicos_block * block)
639 char const* pFigureUID;
643 double dataBounds[6];
644 double rotationAngle[2];
646 dataBounds[0] = block->rpar[0]; // xMin
647 dataBounds[1] = block->rpar[1]; // xMax
648 dataBounds[2] = block->rpar[2]; // yMin
649 dataBounds[3] = block->rpar[3]; // yMax
650 dataBounds[4] = block->rpar[4]; // zMin
651 dataBounds[5] = block->rpar[5]; // zMax
653 rotationAngle[0] = block->rpar[6]; // alpha
654 rotationAngle[1] = block->rpar[7]; // theta
656 pFigureUID = getFigure(block);
657 pAxeUID = getAxe(pFigureUID, block);
659 result = setGraphicObjectProperty(pAxeUID, __GO_DATA_BOUNDS__, dataBounds, jni_double_vector, 6);
660 result &= setGraphicObjectProperty(pAxeUID, __GO_ROTATION_ANGLES__, rotationAngle, jni_double_vector, 2);