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.1-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;
60 int* 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 int getFigure(scicos_block * block);
109 * Get (and allocate on demand) the axe associated with the input
111 * \param iFigureUID 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 int getAxe(int iFigureUID, scicos_block * block);
119 * Get (and allocate on demand) the polyline associated with the row
121 * \param iAxeUID 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 int getPolyline(int iAxeUID, 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 cscopxy3d(scicos_block * block, scicos_flag flag)
157 sco = getScoData(block);
162 iFigureUID = getFigure(block);
171 iFigureUID = getFigure(block);
179 appendData(block, block->inptr[0], block->inptr[1], block->inptr[2]);
180 for (j = 0; j < block->insz[0]; j++)
182 result = pushData(block, j);
185 Coserror("%s: unable to push some data.", "cscopxy3d");
200 /*-------------------------------------------------------------------------*/
202 /*****************************************************************************
204 * Container management
206 ****************************************************************************/
208 static sco_data *getScoData(scicos_block * block)
210 sco_data *sco = (sco_data *) * (block->work);
219 sco = (sco_data *) MALLOC(sizeof(sco_data));
222 goto error_handler_sco;
225 sco->internal.numberOfPoints = 0;
226 sco->internal.maxNumberOfPoints = block->ipar[2];
228 sco->internal.coordinates = (double **)CALLOC(block->nin, sizeof(double *));
229 if (sco->internal.coordinates == NULL)
231 goto error_handler_coordinates;
234 for (i = 0; i < block->insz[0]; i++)
236 sco->internal.coordinates[i] = (double *)CALLOC(3 * block->ipar[2], sizeof(double));
238 if (sco->internal.coordinates[i] == NULL)
240 goto error_handler_coordinates_i;
244 sco->scope.cachedFigureUID = 0;
245 sco->scope.cachedAxeUID = 0;
247 sco->scope.cachedPolylinesUIDs = (int*)CALLOC(block->insz[0], sizeof(int));
249 *(block->work) = sco;
255 * Error management (out of normal flow)
258 error_handler_coordinates_i:
259 for (j = 0; j < i; j++)
261 FREE(sco->internal.coordinates[i]);
263 FREE(sco->internal.coordinates);
264 error_handler_coordinates:
272 static void freeScoData(scicos_block * block)
274 sco_data *sco = (sco_data *) * (block->work);
279 for (i = 0; i < block->insz[0]; i++)
281 FREE(sco->internal.coordinates[i]);
284 FREE(sco->internal.coordinates);
285 FREE(sco->scope.cachedPolylinesUIDs);
287 *(block->work) = NULL;
291 static sco_data *reallocScoData(scicos_block * block, int numberOfPoints)
293 sco_data *sco = (sco_data *) * (block->work);
298 int previousNumberOfPoints = sco->internal.maxNumberOfPoints;
299 int newPoints = numberOfPoints - previousNumberOfPoints;
301 for (i = 0; i < block->insz[0]; i++)
303 ptr = (double *)REALLOC(sco->internal.coordinates[i], 3 * numberOfPoints * sizeof(double));
309 // memcpy existing Z-axis values (use memmove to handle memory overlapping)
310 memmove(ptr + 2 * numberOfPoints, ptr + 2 * previousNumberOfPoints, previousNumberOfPoints * sizeof(double));
312 // memcpy existing Y-axis values (use memmove to handle memory overlapping)
313 memmove(ptr + numberOfPoints, ptr + previousNumberOfPoints, previousNumberOfPoints * sizeof(double));
315 // then set the last points to the last values for Z-axis, Y-axis and X-axis values
316 for (setLen = newPoints - 1; setLen >= 0; setLen--)
318 ptr[2 * numberOfPoints + previousNumberOfPoints + setLen] = ptr[2 * numberOfPoints + previousNumberOfPoints - 1];
320 for (setLen = newPoints - 1; setLen >= 0; setLen--)
322 ptr[numberOfPoints + previousNumberOfPoints + setLen] = ptr[numberOfPoints + previousNumberOfPoints - 1];
324 for (setLen = newPoints - 1; setLen >= 0; setLen--)
326 ptr[previousNumberOfPoints + setLen] = ptr[previousNumberOfPoints - 1];
329 sco->internal.coordinates[i] = ptr;
332 sco->internal.maxNumberOfPoints = numberOfPoints;
342 static void appendData(scicos_block * block, double *x, double *y, double *z)
346 sco_data *sco = (sco_data *) * (block->work);
347 int maxNumberOfPoints = sco->internal.maxNumberOfPoints;
348 int numberOfPoints = sco->internal.numberOfPoints;
351 * Handle the case where the scope has more points than maxNumberOfPoints
353 if (sco != NULL && numberOfPoints >= maxNumberOfPoints)
355 // on a full scope, re-alloc
356 maxNumberOfPoints = maxNumberOfPoints + block->ipar[2];
357 sco = reallocScoData(block, maxNumberOfPoints);
367 for (i = 0; i < block->insz[0]; i++)
370 for (setLen = maxNumberOfPoints - numberOfPoints - 1; setLen >= 0; setLen--)
372 sco->internal.coordinates[i][numberOfPoints + setLen] = x[i];
375 for (setLen = maxNumberOfPoints - numberOfPoints - 1; setLen >= 0; setLen--)
377 sco->internal.coordinates[i][maxNumberOfPoints + numberOfPoints + setLen] = y[i];
380 for (setLen = maxNumberOfPoints - numberOfPoints - 1; setLen >= 0; setLen--)
382 sco->internal.coordinates[i][2 * maxNumberOfPoints + numberOfPoints + setLen] = z[i];
386 sco->internal.numberOfPoints++;
390 static BOOL pushData(scicos_block * block, int row)
399 iFigureUID = getFigure(block);
400 iAxeUID = getAxe(iFigureUID, block);
401 iPolylineUID = getPolyline(iAxeUID, block, row);
403 sco = getScoData(block);
409 // select the right row
410 coordinates = sco->internal.coordinates[row];
412 return setGraphicObjectProperty(iPolylineUID, __GO_DATA_MODEL_COORDINATES__, coordinates, jni_double_vector, sco->internal.maxNumberOfPoints);
415 /*****************************************************************************
419 ****************************************************************************/
422 * Set properties on the figure.
424 * \param iFigureUID the figure uid
425 * \param block the current block
427 static void setFigureSettings(int iFigureUID, scicos_block * block)
432 int *ipar = block->ipar;
433 int nipar = block->nipar;
435 win_pos[0] = ipar[nipar - 5];
436 win_pos[1] = ipar[nipar - 4];
437 win_dim[0] = ipar[nipar - 3];
438 win_dim[1] = ipar[nipar - 2];
440 if (win_pos[0] > 0 && win_pos[1] > 0)
442 setGraphicObjectProperty(iFigureUID, __GO_POSITION__, &win_pos, jni_int_vector, 2);
445 if (win_dim[0] > 0 && win_dim[1] > 0)
447 setGraphicObjectProperty(iFigureUID, __GO_SIZE__, &win_dim, jni_int_vector, 2);
451 /*****************************************************************************
455 ****************************************************************************/
457 static int getFigure(scicos_block * block)
460 int iFigureUID = NULL;
463 sco_data *sco = (sco_data *) * (block->work);
465 // assert the sco is not NULL
471 // fast path for an existing object
472 if (sco->scope.cachedFigureUID)
474 return sco->scope.cachedFigureUID;
477 figNum = block->ipar[0];
479 // with a negative id, use the block number indexed from a constant.
482 figNum = 20000 + get_block_number();
485 iFigureUID = getFigureFromIndex(figNum);
489 iFigureUID = createNewFigureWithAxes();
490 setGraphicObjectProperty(iFigureUID, __GO_ID__, &figNum, jni_int, 1);
492 // the stored uid is a reference to the figure map, not to the current figure
493 iFigureUID = getFigureFromIndex(figNum);
494 sco->scope.cachedFigureUID = iFigureUID;
496 // set configured parameters
497 setFigureSettings(iFigureUID, block);
499 // allocate the axes through the getter
500 iAxe = getAxe(iFigureUID, block);
503 * Setup according to block settings
505 setLabel(iAxe, __GO_X_AXIS_LABEL__, "x");
506 setLabel(iAxe, __GO_Y_AXIS_LABEL__, "y");
507 setLabel(iAxe, __GO_Z_AXIS_LABEL__, "z");
509 setGraphicObjectProperty(iAxe, __GO_X_AXIS_VISIBLE__, &i__1, jni_bool, 1);
510 setGraphicObjectProperty(iAxe, __GO_Y_AXIS_VISIBLE__, &i__1, jni_bool, 1);
511 setGraphicObjectProperty(iAxe, __GO_Z_AXIS_VISIBLE__, &i__1, jni_bool, 1);
513 setPolylinesBounds(block);
516 if (sco->scope.cachedFigureUID == 0)
518 sco->scope.cachedFigureUID = iFigureUID;
523 static int getAxe(int iFigureUID, scicos_block * block)
527 sco_data *sco = (sco_data *) * (block->work);
529 // assert the sco is not NULL
535 // fast path for an existing object
536 if (sco->scope.cachedAxeUID)
538 return sco->scope.cachedAxeUID;
541 iAxe = findChildWithKindAt(iFigureUID, __GO_AXES__, 0);
544 * Allocate if necessary
548 cloneAxesModel(iFigureUID);
549 iAxe = findChildWithKindAt(iFigureUID, __GO_AXES__, 0);
553 * Setup on first access
557 // allocate the polylines through the getter
558 for (i = 0; i < block->insz[0]; i++)
560 getPolyline(iAxe, block, i);
569 * then cache with local storage
571 sco->scope.cachedAxeUID = iAxe;
572 return sco->scope.cachedAxeUID;
575 static int getPolyline(int iAxeUID, scicos_block * block, int row)
582 double lineThickness;
584 sco_data *sco = (sco_data *) * (block->work);
586 // assert the sco is not NULL
587 if (sco == NULL || sco->scope.cachedPolylinesUIDs == NULL)
592 // fast path for an existing object
593 if (sco->scope.cachedPolylinesUIDs[row])
595 return sco->scope.cachedPolylinesUIDs[row];
598 iPolyline = findChildWithKindAt(iAxeUID, __GO_POLYLINE__, row);
601 * Allocate if necessary
605 iPolyline = createGraphicObject(__GO_POLYLINE__);
609 createDataObject(iPolyline, __GO_POLYLINE__);
610 setGraphicObjectRelationship(iAxeUID, iPolyline);
619 * Setup on first access
623 * Default setup of the nGons property
627 setGraphicObjectProperty(iPolyline, __GO_DATA_MODEL_NUM_GONS__, &nGons, jni_int, 1);
630 color = block->ipar[3 + row];
631 markSize = block->ipar[3 + block->ipar[1] + row];
632 lineThickness = (double)markSize;
635 setGraphicObjectProperty(iPolyline, __GO_LINE_MODE__, &b__true, jni_bool, 1);
637 setGraphicObjectProperty(iPolyline, __GO_LINE_COLOR__, &color, jni_int, 1);
638 setGraphicObjectProperty(iPolyline, __GO_LINE_THICKNESS__, &lineThickness, jni_double, 1);
643 setGraphicObjectProperty(iPolyline, __GO_MARK_MODE__, &b__true, jni_bool, 1);
645 setGraphicObjectProperty(iPolyline, __GO_MARK_STYLE__, &color, jni_int, 1);
646 setGraphicObjectProperty(iPolyline, __GO_MARK_SIZE__, &markSize, jni_int, 1);
650 int iClipState = 1; //on
651 setGraphicObjectProperty(iPolyline, __GO_CLIP_STATE__, &iClipState, jni_int, 1);
655 * then cache with local storage
657 sco->scope.cachedPolylinesUIDs[row] = iPolyline;
658 return sco->scope.cachedPolylinesUIDs[row];
661 static BOOL setPolylinesBounds(scicos_block * block)
667 double dataBounds[6];
668 double rotationAngle[2];
670 dataBounds[0] = block->rpar[0]; // xMin
671 dataBounds[1] = block->rpar[1]; // xMax
672 dataBounds[2] = block->rpar[2]; // yMin
673 dataBounds[3] = block->rpar[3]; // yMax
674 dataBounds[4] = block->rpar[4]; // zMin
675 dataBounds[5] = block->rpar[5]; // zMax
677 rotationAngle[0] = block->rpar[6]; // alpha
678 rotationAngle[1] = block->rpar[7]; // theta
680 iFigureUID = getFigure(block);
681 iAxeUID = getAxe(iFigureUID, block);
683 result = setGraphicObjectProperty(iAxeUID, __GO_DATA_BOUNDS__, dataBounds, jni_double_vector, 6);
684 result &= setGraphicObjectProperty(iAxeUID, __GO_ROTATION_ANGLES__, rotationAngle, jni_double_vector, 2);