2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2011 - Scilab Enterprises - Clement DAVID
5 * Copyright (C) 2012 - 2016 - Scilab Enterprises
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.
18 #include "dynlib_scicos_blocks.h"
21 #include "sci_malloc.h"
22 #include "elementary_functions.h"
24 #include "getGraphicObjectProperty.h"
25 #include "setGraphicObjectProperty.h"
26 #include "graphicObjectProperties.h"
27 #include "createGraphicObject.h"
29 #include "CurrentFigure.h"
31 #include "scicos_block4.h"
34 #include "localization.h"
35 #include "os_string.h"
37 #include "FigureList.h"
38 #include "BuildObjects.h"
39 #include "AxesModel.h"
41 /*****************************************************************************
42 * Internal container structure
43 ****************************************************************************/
53 int maxNumberOfPoints;
61 int* cachedPolylinesUIDs;
66 * Get (and allocate on demand) the internal data used on this scope
67 * \param block the block
68 * \return the scope data
70 static sco_data *getScoData(scicos_block * block);
73 * Release any internal data
75 * \param block the block
77 static void freeScoData(scicos_block * block);
80 * Append the data to the current data
82 * \param block the block
87 static void appendData(scicos_block * block, double *x, double *y, double *z);
90 * Push the block data to the polyline
92 * \param block the block
93 * \param row the selected row
96 static BOOL pushData(scicos_block * block, int row);
98 /*****************************************************************************
100 ****************************************************************************/
103 * Get (and allocate on demand) the figure associated with the block
104 * \param block the block
105 * \return a valid figure UID or NULL on error
107 static int getFigure(scicos_block * block);
110 * Get (and allocate on demand) the axe associated with the input
112 * \param iFigureUID the parent figure UID
113 * \param block the block
114 * \param input the current input index (0-indexed)
115 * \return a valid axe UID or NULL on error
117 static int getAxe(int iFigureUID, scicos_block * block);
120 * Get (and allocate on demand) the polyline associated with the row
122 * \param iAxeUID the parent axe UID
123 * \param block the block
124 * \param row the current row index (0-indexed)
125 * \return a valid polyline UID or NULL on error
127 static int getPolyline(int iAxeUID, scicos_block * block, int row);
130 * Set the polylines bounds
132 * \param block the block
133 * \param iAxeUID the axe id
135 static BOOL setPolylinesBounds(scicos_block * block, int iAxeUID);
137 /*****************************************************************************
138 * Simulation function
139 ****************************************************************************/
141 /** \fn void cmscope(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 cscopxy3d(scicos_block * block, scicos_flag flag)
159 sco = getScoData(block);
164 iFigureUID = getFigure(block);
173 iFigureUID = getFigure(block);
181 appendData(block, GetRealInPortPtrs(block, 1), GetRealInPortPtrs(block, 2), GetRealInPortPtrs(block, 3));
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));
224 goto error_handler_sco;
227 sco->internal.numberOfPoints = 0;
228 sco->internal.maxNumberOfPoints = block->ipar[2];
230 sco->internal.coordinates = (double **)CALLOC(block->nin, sizeof(double *));
231 if (sco->internal.coordinates == NULL)
233 goto error_handler_coordinates;
236 for (i = 0; i < block->insz[0]; i++)
238 sco->internal.coordinates[i] = (double *)CALLOC(3 * block->ipar[2], sizeof(double));
240 if (sco->internal.coordinates[i] == NULL)
242 goto error_handler_coordinates_i;
246 sco->scope.cachedFigureUID = 0;
247 sco->scope.cachedAxeUID = 0;
249 sco->scope.cachedPolylinesUIDs = (int*)CALLOC(block->insz[0], sizeof(int));
251 *(block->work) = sco;
257 * Error management (out of normal flow)
260 error_handler_coordinates_i:
261 for (j = 0; j < i; j++)
263 FREE(sco->internal.coordinates[i]);
265 FREE(sco->internal.coordinates);
266 error_handler_coordinates:
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.coordinates[i]);
286 FREE(sco->internal.coordinates);
287 FREE(sco->scope.cachedPolylinesUIDs);
289 *(block->work) = NULL;
293 static sco_data *reallocScoData(scicos_block * block, int numberOfPoints)
295 sco_data *sco = (sco_data *) * (block->work);
300 int previousNumberOfPoints = sco->internal.maxNumberOfPoints;
301 int newPoints = numberOfPoints - previousNumberOfPoints;
303 for (i = 0; i < block->insz[0]; i++)
305 ptr = (double *)REALLOC(sco->internal.coordinates[i], 3 * numberOfPoints * sizeof(double));
311 // memcpy existing Z-axis values (use memmove to handle memory overlapping)
312 memmove(ptr + 2 * numberOfPoints, ptr + 2 * previousNumberOfPoints, previousNumberOfPoints * sizeof(double));
314 // memcpy existing Y-axis values (use memmove to handle memory overlapping)
315 memmove(ptr + numberOfPoints, ptr + previousNumberOfPoints, previousNumberOfPoints * sizeof(double));
317 // then set the last points to the last values for Z-axis, Y-axis and X-axis values
318 for (setLen = newPoints - 1; setLen >= 0; setLen--)
320 ptr[2 * numberOfPoints + previousNumberOfPoints + setLen] = ptr[2 * numberOfPoints + previousNumberOfPoints - 1];
322 for (setLen = newPoints - 1; setLen >= 0; setLen--)
324 ptr[numberOfPoints + previousNumberOfPoints + setLen] = ptr[numberOfPoints + previousNumberOfPoints - 1];
326 for (setLen = newPoints - 1; setLen >= 0; setLen--)
328 ptr[previousNumberOfPoints + setLen] = ptr[previousNumberOfPoints - 1];
331 sco->internal.coordinates[i] = ptr;
334 sco->internal.maxNumberOfPoints = numberOfPoints;
344 static void appendData(scicos_block * block, double *x, double *y, double *z)
347 int maxNumberOfPoints;
350 sco_data *sco = (sco_data *) * (block->work);
355 maxNumberOfPoints = sco->internal.maxNumberOfPoints;
356 numberOfPoints = sco->internal.numberOfPoints;
359 * Handle the case where the scope has more points than maxNumberOfPoints
361 if (numberOfPoints >= maxNumberOfPoints)
363 // on a full scope, re-alloc
364 maxNumberOfPoints = maxNumberOfPoints + block->ipar[2];
365 sco = reallocScoData(block, maxNumberOfPoints);
375 for (i = 0; i < block->insz[0]; i++)
378 for (setLen = maxNumberOfPoints - numberOfPoints - 1; setLen >= 0; setLen--)
380 sco->internal.coordinates[i][numberOfPoints + setLen] = x[i];
383 for (setLen = maxNumberOfPoints - numberOfPoints - 1; setLen >= 0; setLen--)
385 sco->internal.coordinates[i][maxNumberOfPoints + numberOfPoints + setLen] = y[i];
388 for (setLen = maxNumberOfPoints - numberOfPoints - 1; setLen >= 0; setLen--)
390 sco->internal.coordinates[i][2 * maxNumberOfPoints + numberOfPoints + setLen] = z[i];
394 sco->internal.numberOfPoints++;
398 static BOOL pushData(scicos_block * block, int row)
407 iFigureUID = getFigure(block);
408 iAxeUID = getAxe(iFigureUID, block);
409 iPolylineUID = getPolyline(iAxeUID, block, row);
411 sco = getScoData(block);
417 // select the right row
418 coordinates = sco->internal.coordinates[row];
420 return setGraphicObjectProperty(iPolylineUID, __GO_DATA_MODEL_COORDINATES__, coordinates, jni_double_vector, sco->internal.maxNumberOfPoints);
423 /*****************************************************************************
427 ****************************************************************************/
430 * Set properties on the figure.
432 * \param iFigureUID the figure uid
433 * \param block the current block
435 static void setFigureSettings(int iFigureUID, scicos_block * block)
440 int *ipar = block->ipar;
441 int nipar = block->nipar;
443 win_pos[0] = ipar[nipar - 5];
444 win_pos[1] = ipar[nipar - 4];
445 win_dim[0] = ipar[nipar - 3];
446 win_dim[1] = ipar[nipar - 2];
448 if (win_pos[0] > 0 && win_pos[1] > 0)
450 setGraphicObjectProperty(iFigureUID, __GO_POSITION__, &win_pos, jni_int_vector, 2);
453 if (win_dim[0] > 0 && win_dim[1] > 0)
455 setGraphicObjectProperty(iFigureUID, __GO_SIZE__, &win_dim, jni_int_vector, 2);
459 /*****************************************************************************
463 ****************************************************************************/
465 static int getFigure(scicos_block * block)
471 sco_data *sco = (sco_data *) * (block->work);
473 // assert the sco is not NULL
479 // fast path for an existing object
480 if (sco->scope.cachedFigureUID)
482 return sco->scope.cachedFigureUID;
485 figNum = block->ipar[0];
487 // with a negative id, use the block number indexed from a constant.
490 figNum = 20000 + get_block_number();
493 iFigureUID = getFigureFromIndex(figNum);
497 iFigureUID = createNewFigureWithAxes();
498 setGraphicObjectProperty(iFigureUID, __GO_ID__, &figNum, jni_int, 1);
500 // the stored uid is a reference to the figure map, not to the current figure
501 iFigureUID = getFigureFromIndex(figNum);
502 sco->scope.cachedFigureUID = iFigureUID;
504 // set configured parameters
505 setFigureSettings(iFigureUID, block);
507 // allocate the axes through the getter
508 iAxe = getAxe(iFigureUID, block);
511 * Setup according to block settings
513 setLabel(iAxe, __GO_X_AXIS_LABEL__, "x");
514 setLabel(iAxe, __GO_Y_AXIS_LABEL__, "y");
515 setLabel(iAxe, __GO_Z_AXIS_LABEL__, "z");
517 setGraphicObjectProperty(iAxe, __GO_X_AXIS_VISIBLE__, &i__1, jni_bool, 1);
518 setGraphicObjectProperty(iAxe, __GO_Y_AXIS_VISIBLE__, &i__1, jni_bool, 1);
519 setGraphicObjectProperty(iAxe, __GO_Z_AXIS_VISIBLE__, &i__1, jni_bool, 1);
521 setPolylinesBounds(block, iAxe);
524 if (sco->scope.cachedFigureUID == 0)
526 sco->scope.cachedFigureUID = iFigureUID;
531 static int getAxe(int iFigureUID, scicos_block * block)
535 sco_data *sco = (sco_data *) * (block->work);
537 // assert the sco is not NULL
543 // fast path for an existing object
544 if (sco->scope.cachedAxeUID)
546 return sco->scope.cachedAxeUID;
549 iAxe = findChildWithKindAt(iFigureUID, __GO_AXES__, 0);
552 * Allocate if necessary
556 cloneAxesModel(iFigureUID);
557 iAxe = findChildWithKindAt(iFigureUID, __GO_AXES__, 0);
561 * Setup on first access
565 // allocate the polylines through the getter
566 for (i = 0; i < block->insz[0]; i++)
568 getPolyline(iAxe, block, i);
577 * then cache with local storage
579 sco->scope.cachedAxeUID = iAxe;
580 return sco->scope.cachedAxeUID;
583 static int getPolyline(int iAxeUID, scicos_block * block, int row)
590 double lineThickness;
592 sco_data *sco = (sco_data *) * (block->work);
594 // assert the sco is not NULL
595 if (sco == NULL || sco->scope.cachedPolylinesUIDs == NULL)
600 // fast path for an existing object
601 if (sco->scope.cachedPolylinesUIDs[row])
603 return sco->scope.cachedPolylinesUIDs[row];
606 iPolyline = findChildWithKindAt(iAxeUID, __GO_POLYLINE__, row);
609 * Allocate if necessary
613 iPolyline = createGraphicObject(__GO_POLYLINE__);
617 createDataObject(iPolyline, __GO_POLYLINE__);
618 setGraphicObjectRelationship(iAxeUID, iPolyline);
627 * Setup on first access
631 * Default setup of the nGons property
635 setGraphicObjectProperty(iPolyline, __GO_DATA_MODEL_NUM_GONS__, &nGons, jni_int, 1);
638 color = block->ipar[3 + row];
639 markSize = block->ipar[3 + block->ipar[1] + row];
640 lineThickness = (double)markSize;
643 setGraphicObjectProperty(iPolyline, __GO_LINE_MODE__, &b__true, jni_bool, 1);
645 setGraphicObjectProperty(iPolyline, __GO_LINE_COLOR__, &color, jni_int, 1);
646 setGraphicObjectProperty(iPolyline, __GO_LINE_THICKNESS__, &lineThickness, jni_double, 1);
651 setGraphicObjectProperty(iPolyline, __GO_MARK_MODE__, &b__true, jni_bool, 1);
653 setGraphicObjectProperty(iPolyline, __GO_MARK_STYLE__, &color, jni_int, 1);
654 setGraphicObjectProperty(iPolyline, __GO_MARK_SIZE__, &markSize, jni_int, 1);
658 int iClipState = 1; //on
659 setGraphicObjectProperty(iPolyline, __GO_CLIP_STATE__, &iClipState, jni_int, 1);
663 * then cache with local storage
665 sco->scope.cachedPolylinesUIDs[row] = iPolyline;
666 return sco->scope.cachedPolylinesUIDs[row];
669 static BOOL setPolylinesBounds(scicos_block * block, int iAxeUID)
672 double dataBounds[6];
673 double rotationAngle[2];
675 dataBounds[0] = block->rpar[0]; // xMin
676 dataBounds[1] = block->rpar[1]; // xMax
677 dataBounds[2] = block->rpar[2]; // yMin
678 dataBounds[3] = block->rpar[3]; // yMax
679 dataBounds[4] = block->rpar[4]; // zMin
680 dataBounds[5] = block->rpar[5]; // zMax
682 rotationAngle[0] = block->rpar[6]; // alpha
683 rotationAngle[1] = block->rpar[7]; // theta
685 result = setGraphicObjectProperty(iAxeUID, __GO_DATA_BOUNDS__, dataBounds, jni_double_vector, 6);
690 result = setGraphicObjectProperty(iAxeUID, __GO_ROTATION_ANGLES__, rotationAngle, jni_double_vector, 2);