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
85 static void appendData(scicos_block * block, double *x, double *y);
88 * Push the block data to the polyline
90 * \param block the block
91 * \param row the selected row
94 static BOOL pushData(scicos_block * block, int row);
96 /*****************************************************************************
98 ****************************************************************************/
101 * Get (and allocate on demand) the figure associated with the block
102 * \param block the block
103 * \return a valid figure UID or NULL on error
105 static char const* getFigure(scicos_block * block);
108 * Get (and allocate on demand) the axe associated with the input
110 * \param pFigureUID the parent figure UID
111 * \param block the block
112 * \param input the current input index (0-indexed)
113 * \return a valid axe UID or NULL on error
115 static char *getAxe(char const* pFigureUID, scicos_block * block);
118 * Get (and allocate on demand) the polyline associated with the row
120 * \param pAxeUID the parent axe UID
121 * \param block the block
122 * \param row the current row index (0-indexed)
123 * \return a valid polyline UID or NULL on error
125 static char *getPolyline(char *pAxeUID, scicos_block * block, int row);
128 * Set the polylines buffer size
130 * \param block the block
131 * \param maxNumberOfPoints the size of the buffer
133 static BOOL setPolylinesBuffers(scicos_block * block, int maxNumberOfPoints);
136 * Set the polylines bounds
138 * \param block the block
140 static BOOL setPolylinesBounds(scicos_block * block);
142 /*****************************************************************************
143 * Simulation function
144 ****************************************************************************/
146 /** \fn void cmscope(scicos_block * block,int flag)
147 \brief the computational function
148 \param block A pointer to a scicos_block
149 \param flag An int which indicates the state of the block (init, update, ending)
151 SCICOS_BLOCKS_IMPEXP void cscopxy(scicos_block * block, scicos_flag flag)
153 char const* pFigureUID;
162 sco = getScoData(block);
167 pFigureUID = getFigure(block);
168 if (pFigureUID == NULL)
176 pFigureUID = getFigure(block);
177 if (pFigureUID == NULL)
184 appendData(block, block->inptr[0], block->inptr[1]);
185 for (j = 0; j < block->insz[0]; j++)
187 result = pushData(block, j);
190 Coserror("%s: unable to push some data.", "cscopxy");
205 /*-------------------------------------------------------------------------*/
207 /*****************************************************************************
209 * Container management
211 ****************************************************************************/
213 static sco_data *getScoData(scicos_block * block)
215 sco_data *sco = (sco_data *) * (block->work);
224 sco = (sco_data *) MALLOC(sizeof(sco_data));
226 goto error_handler_sco;
228 sco->internal.numberOfPoints = 0;
229 sco->internal.maxNumberOfPoints = block->ipar[2];
231 sco->internal.data = (double ***)CALLOC(block->nin, sizeof(double **));
232 if (sco->internal.data == NULL)
233 goto error_handler_data;
235 for (i = 0; i < block->nin; i++)
237 sco->internal.data[i] = (double **)CALLOC(block->insz[i], sizeof(double *));
238 if (sco->internal.data[i] == NULL)
239 goto error_handler_data_i;
241 for (i = 0; i < block->nin; i++)
243 for (j = 0; j < block->insz[i]; j++)
245 sco->internal.data[i][j] = (double *)CALLOC(block->ipar[2], sizeof(double));
247 if (sco->internal.data[i][j] == NULL)
248 goto error_handler_data_ij;
252 sco->scope.cachedFigureUID = NULL;
253 sco->scope.cachedAxeUID = NULL;
255 sco->scope.cachedPolylinesUIDs = (char **)CALLOC(block->insz[0], sizeof(char **));
257 *(block->work) = sco;
263 * Error management (out of normal flow)
266 error_handler_data_ij:
267 for (k = 0; k < i; k++)
269 for (l = 0; l < j; l++)
271 FREE(sco->internal.data[k][l]);
275 error_handler_data_i:
276 for (j = 0; j < i; j++)
278 FREE(sco->internal.data[i]);
280 FREE(sco->internal.data);
289 static void freeScoData(scicos_block * block)
291 sco_data *sco = (sco_data *) * (block->work);
296 for (i = 0; i < block->nin; i++)
298 for (j = 0; j < block->insz[i]; j++)
300 FREE(sco->internal.data[i][j]);
302 FREE(sco->internal.data[i]);
305 FREE(sco->internal.data);
307 for (i = 0; i < block->insz[0]; i++)
309 FREE(sco->scope.cachedPolylinesUIDs[i]);
311 FREE(sco->scope.cachedAxeUID);
314 *(block->work) = NULL;
318 static sco_data *reallocScoData(scicos_block * block, int numberOfPoints)
320 sco_data *sco = (sco_data *) * (block->work);
325 int previousNumberOfPoints = sco->internal.maxNumberOfPoints;
327 for (i = 0; i < block->nin; i++)
329 for (j = 0; j < block->insz[i]; j++)
331 ptr = (double *)REALLOC(sco->internal.data[i][j], numberOfPoints * sizeof(double));
335 for (setLen = numberOfPoints - previousNumberOfPoints - 1; setLen >= 0; setLen--)
337 ptr[previousNumberOfPoints + setLen] = ptr[previousNumberOfPoints - 1];
339 sco->internal.data[i][j] = ptr;
343 sco->internal.maxNumberOfPoints = numberOfPoints;
353 static void appendData(scicos_block * block, double *x, double *y)
357 sco_data *sco = (sco_data *) * (block->work);
358 int maxNumberOfPoints = sco->internal.maxNumberOfPoints;
359 int numberOfPoints = sco->internal.numberOfPoints;
362 * Handle the case where the scope has more points than maxNumberOfPoints
364 if (sco != NULL && numberOfPoints >= maxNumberOfPoints)
366 // on a full scope, re-alloc
367 maxNumberOfPoints = maxNumberOfPoints + block->ipar[2];
368 sco = reallocScoData(block, maxNumberOfPoints);
370 // reconfigure related graphic objects
371 if (setPolylinesBuffers(block, maxNumberOfPoints) == FALSE)
386 for (i = 0; i < block->insz[0]; i++)
388 for (setLen = maxNumberOfPoints - numberOfPoints - 1; setLen >= 0; setLen--)
390 sco->internal.data[0][i][numberOfPoints + setLen] = x[i];
391 sco->internal.data[1][i][numberOfPoints + setLen] = y[i];
395 sco->internal.numberOfPoints++;
399 static BOOL pushData(scicos_block * block, int row)
401 char const* pFigureUID;
411 pFigureUID = getFigure(block);
412 pAxeUID = getAxe(pFigureUID, block);
413 pPolylineUID = getPolyline(pAxeUID, block, row);
415 sco = getScoData(block);
419 // select the right input and row
420 x = sco->internal.data[0][row];
421 y = sco->internal.data[1][row];
423 result &= setGraphicObjectProperty(pPolylineUID, __GO_DATA_MODEL_X__, x, jni_double_vector, sco->internal.maxNumberOfPoints);
424 result &= setGraphicObjectProperty(pPolylineUID, __GO_DATA_MODEL_Y__, y, jni_double_vector, sco->internal.maxNumberOfPoints);
429 /*****************************************************************************
433 ****************************************************************************/
436 * Set properties on the figure.
438 * \param pFigureUID the figure uid
439 * \param block the current block
441 static void setFigureSettings(char const* pFigureUID, scicos_block * block)
446 int *ipar = block->ipar;
448 win_pos[0] = ipar[6];
449 win_pos[1] = ipar[7];
450 win_dim[0] = ipar[8];
451 win_dim[1] = ipar[9];
453 if (win_pos[0] > 0 && win_pos[1] > 0)
455 setGraphicObjectProperty(pFigureUID, __GO_POSITION__, &win_pos, jni_int_vector, 2);
458 if (win_dim[0] > 0 && win_dim[1] > 0)
460 setGraphicObjectProperty(pFigureUID, __GO_SIZE__, &win_dim, jni_int_vector, 2);
464 /*****************************************************************************
468 ****************************************************************************/
470 static char const* getFigure(scicos_block * block)
473 char const* pFigureUID = NULL;
476 sco_data *sco = (sco_data *) * (block->work);
478 // assert the sco is not NULL
484 // fast path for an existing object
485 if (sco->scope.cachedFigureUID != NULL)
487 return sco->scope.cachedFigureUID;
490 figNum = block->ipar[0];
492 // with a negative id, use the block number indexed from a constant.
495 figNum = 20000 + get_block_number();
498 pFigureUID = getFigureFromIndex(figNum);
500 if (pFigureUID == NULL)
502 pFigureUID = createNewFigureWithAxes();
503 setGraphicObjectProperty(pFigureUID, __GO_ID__, &figNum, jni_int, 1);
505 // the stored uid is a reference to the figure map, not to the current figure
506 pFigureUID = getFigureFromIndex(figNum);
507 sco->scope.cachedFigureUID = pFigureUID;
509 // set configured parameters
510 setFigureSettings(pFigureUID, block);
512 // allocate the axes through the getter
513 pAxe = getAxe(pFigureUID, block);
516 * Setup according to block settings
518 setLabel(pAxe, __GO_X_AXIS_LABEL__, "x");
519 setLabel(pAxe, __GO_Y_AXIS_LABEL__, "y");
521 setGraphicObjectProperty(pAxe, __GO_X_AXIS_VISIBLE__, &i__1, jni_bool, 1);
522 setGraphicObjectProperty(pAxe, __GO_Y_AXIS_VISIBLE__, &i__1, jni_bool, 1);
524 setPolylinesBounds(block);
527 if (sco->scope.cachedFigureUID == NULL)
529 sco->scope.cachedFigureUID = pFigureUID;
534 static char *getAxe(char const* pFigureUID, scicos_block * block)
538 sco_data *sco = (sco_data *) * (block->work);
540 // assert the sco is not NULL
546 // fast path for an existing object
547 if (sco->scope.cachedAxeUID != NULL)
549 return sco->scope.cachedAxeUID;
552 pAxe = findChildWithKindAt(pFigureUID, __GO_AXES__, 0);
555 * Allocate if necessary
559 cloneAxesModel(pFigureUID);
560 pAxe = findChildWithKindAt(pFigureUID, __GO_AXES__, 0);
564 * Setup on first access
568 // allocate the polylines through the getter
569 for (i = 0; i < block->insz[0]; i++)
571 getPolyline(pAxe, block, i);
576 * then cache with local storage
578 if (pAxe != NULL && sco->scope.cachedAxeUID == NULL)
580 sco->scope.cachedAxeUID = strdup(pAxe);
581 releaseGraphicObjectProperty(__GO_PARENT__, pAxe, jni_string, 1);
583 return sco->scope.cachedAxeUID;
586 static char *getPolyline(char *pAxeUID, scicos_block * block, int row)
594 double lineThickness;
596 sco_data *sco = (sco_data *) * (block->work);
598 // assert the sco is not NULL
604 // fast path for an existing object
605 if (sco->scope.cachedPolylinesUIDs != NULL && sco->scope.cachedPolylinesUIDs[row] != NULL)
607 return sco->scope.cachedPolylinesUIDs[row];
610 pPolyline = findChildWithKindAt(pAxeUID, __GO_POLYLINE__, row);
613 * Allocate if necessary
615 if (pPolyline == NULL)
617 pPolyline = createGraphicObject(__GO_POLYLINE__);
619 if (pPolyline != NULL)
621 createDataObject(pPolyline, __GO_POLYLINE__);
622 setGraphicObjectRelationship(pAxeUID, pPolyline);
628 * Setup on first access
630 if (pPolyline != NULL)
633 * Default setup (will crash if removed)
636 int polylineSize[2] = { 1, block->ipar[2] };
637 setGraphicObjectProperty(pPolyline, __GO_DATA_MODEL_NUM_ELEMENTS_ARRAY__, polylineSize, jni_int_vector, 2);
640 setGraphicObjectProperty(pPolyline, __GO_DATA_MODEL_X__, &d__0, jni_double_vector, 1);
641 setGraphicObjectProperty(pPolyline, __GO_DATA_MODEL_Y__, &d__0, jni_double_vector, 1);
643 color = block->ipar[3];
644 markSize = block->ipar[4];
645 lineThickness = (double)markSize;
648 setGraphicObjectProperty(pPolyline, __GO_LINE_MODE__, &b__true, jni_bool, 1);
650 setGraphicObjectProperty(pPolyline, __GO_LINE_COLOR__, &color, jni_int, 1);
651 setGraphicObjectProperty(pPolyline, __GO_LINE_THICKNESS__, &lineThickness, jni_double, 1);
656 setGraphicObjectProperty(pPolyline, __GO_MARK_MODE__, &b__true, jni_bool, 1);
658 setGraphicObjectProperty(pPolyline, __GO_MARK_STYLE__, &color, jni_int, 1);
659 setGraphicObjectProperty(pPolyline, __GO_MARK_SIZE__, &markSize, jni_int, 1);
663 int iClipState = 1; //on
664 setGraphicObjectProperty(pPolyline, __GO_CLIP_STATE__, &iClipState, jni_int, 1);
669 * then cache with local storage
671 if (pPolyline != NULL && sco->scope.cachedPolylinesUIDs != NULL && sco->scope.cachedPolylinesUIDs[row] == NULL)
673 sco->scope.cachedPolylinesUIDs[row] = strdup(pPolyline);
674 releaseGraphicObjectProperty(__GO_PARENT__, pPolyline, jni_string, 1);
676 return sco->scope.cachedPolylinesUIDs[row];
679 static BOOL setPolylinesBuffers(scicos_block * block, int maxNumberOfPoints)
683 char const* pFigureUID;
688 int polylineSize[2] = { 1, maxNumberOfPoints };
690 pFigureUID = getFigure(block);
691 pAxeUID = getAxe(pFigureUID, block);
693 for (i = 0; i < block->insz[0]; i++)
695 pPolylineUID = getPolyline(pAxeUID, block, i);
696 result &= setGraphicObjectProperty(pPolylineUID, __GO_DATA_MODEL_NUM_ELEMENTS_ARRAY__, polylineSize, jni_int_vector, 2);
702 static BOOL setPolylinesBounds(scicos_block * block)
704 char const* pFigureUID;
707 double dataBounds[6];
709 dataBounds[0] = block->rpar[0]; // xMin
710 dataBounds[1] = block->rpar[1]; // xMax
711 dataBounds[2] = block->rpar[2]; // yMin
712 dataBounds[3] = block->rpar[3]; // yMax
713 dataBounds[4] = -1.0; // zMin
714 dataBounds[5] = 1.0; // zMax
716 pFigureUID = getFigure(block);
717 pAxeUID = getAxe(pFigureUID, block);
719 return setGraphicObjectProperty(pAxeUID, __GO_DATA_BOUNDS__, dataBounds, jni_double_vector, 6);