Fix code: UIDs are now integers and no more char*
[scilab.git] / scilab / modules / scicos_blocks / src / c / bouncexy.c
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2012 - Scilab Enterprises - Clement DAVID
4  *
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
10  *
11  */
12
13 #include <math.h>
14 #ifndef M_PI
15 #define M_PI           3.14159265358979323846
16 #endif
17 #include <string.h>
18
19 #include "dynlib_scicos_blocks.h"
20 #include "scoUtils.h"
21
22 #include "MALLOC.h"
23 #include "elementary_functions.h"
24
25 #include "setGraphicObjectProperty.h"
26 #include "getGraphicObjectProperty.h"
27 #include "graphicObjectProperties.h"
28 #include "createGraphicObject.h"
29
30 #include "CurrentFigure.h"
31
32 #include "scicos_block4.h"
33 #include "scicos.h"
34
35 #include "localization.h"
36 #ifdef _MSC_VER
37 #include "strdup_windows.h"
38 #endif
39
40 #include "FigureList.h"
41 #include "BuildObjects.h"
42 #include "AxesModel.h"
43
44 /*****************************************************************************
45  * Internal container structure
46  ****************************************************************************/
47
48 /**
49  * Container structure
50  */
51 typedef struct
52 {
53     struct
54     {
55         double *ballsSize;
56         double **data;
57     } internal;
58
59     struct
60     {
61         int cachedFigureUID;
62         int cachedAxeUID;
63         int* cachedArcsUIDs;
64     } scope;
65 } sco_data;
66
67 /**
68  * Get (and allocate on demand) the internal data used on this scope
69  * \param block the block
70  * \return the scope data
71  */
72 static sco_data *getScoData(scicos_block * block);
73
74 /**
75  * Release any internal data
76  *
77  * \param block the block
78  */
79 static void freeScoData(scicos_block * block);
80
81 /**
82  * Append the data to the current data
83  *
84  * \param block the block
85  * \param x x data
86  * \param y y data
87  */
88 static void appendData(scicos_block * block, double *x, double *y);
89
90 /**
91  * Push the block data to the polyline
92  *
93  * \param block the block
94  * \param row the selected row
95  *
96  */
97 static BOOL pushData(scicos_block * block, int row);
98
99 /*****************************************************************************
100  * Graphics utils
101  ****************************************************************************/
102
103 /**
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
107  */
108 static int getFigure(scicos_block * block);
109
110 /**
111  * Get (and allocate on demand) the axe associated with the input
112  *
113  * \param iFigureUID 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
117  */
118 static int getAxe(int iFigureUID, scicos_block * block);
119
120 /**
121  * Get (and allocate on demand) the arc associated with the row
122  *
123  * \param iAxeUID 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
127  */
128 static int getArc(int iAxeUID, scicos_block * block, int row);
129
130 /**
131  * Set the bounds
132  *
133  * \param block the block
134  */
135 static BOOL setBounds(scicos_block * block);
136
137 /*****************************************************************************
138  * Simulation function
139  ****************************************************************************/
140
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)
145 */
146 SCICOS_BLOCKS_IMPEXP void bouncexy(scicos_block * block, scicos_flag flag)
147 {
148     int iFigureUID;
149
150     sco_data *sco;
151
152     int j;
153     BOOL result;
154
155     switch (flag)
156     {
157
158         case Initialization:
159             sco = getScoData(block);
160             if (sco == NULL)
161             {
162                 set_block_error(-5);
163             }
164             iFigureUID = getFigure(block);
165             if (iFigureUID == 0)
166             {
167                 // allocation error
168                 set_block_error(-5);
169             }
170             break;
171
172         case StateUpdate:
173             iFigureUID = getFigure(block);
174             if (iFigureUID == 0)
175             {
176                 // allocation error
177                 set_block_error(-5);
178                 break;
179             }
180
181             appendData(block, (double *)block->inptr[0], (double *)block->inptr[1]);
182             for (j = 0; j < block->insz[0]; j++)
183             {
184                 result = pushData(block, j);
185                 if (result == FALSE)
186                 {
187                     Coserror("%s: unable to push some data.", "bouncexy");
188                     break;
189                 }
190             }
191             break;
192
193         case Ending:
194             freeScoData(block);
195             break;
196
197         default:
198             break;
199     }
200 }
201
202 /*-------------------------------------------------------------------------*/
203
204 /*****************************************************************************
205  *
206  * Container management
207  *
208  ****************************************************************************/
209
210 static sco_data *getScoData(scicos_block * block)
211 {
212     sco_data *sco = (sco_data *) * (block->work);
213     int i, j;
214
215     if (sco == NULL)
216     {
217         /*
218          * Data allocation
219          */
220
221         sco = (sco_data *) MALLOC(sizeof(sco_data));
222         if (sco == NULL)
223         {
224             goto error_handler_sco;
225         }
226
227         sco->internal.ballsSize = (double *)CALLOC(block->insz[0], sizeof(double));
228         if (sco->internal.ballsSize == NULL)
229         {
230             goto error_handler_ballsSize;
231         }
232         for (i = 0; i < block->insz[0]; i++)
233         {
234             sco->internal.ballsSize[i] = block->z[6 * i + 2];
235         }
236
237         sco->internal.data = (double **)CALLOC(block->insz[0], sizeof(double *));
238         if (sco->internal.data == NULL)
239         {
240             goto error_handler_data;
241         }
242
243         for (i = 0; i < block->insz[0]; i++)
244         {
245             sco->internal.data[i] = (double *)CALLOC(3, sizeof(double));
246             if (sco->internal.data[i] == NULL)
247             {
248                 goto error_handler_data_i;
249             }
250         }
251
252         sco->scope.cachedFigureUID = 0;
253         sco->scope.cachedAxeUID = 0;
254
255         sco->scope.cachedArcsUIDs = (int*)CALLOC(block->insz[0], sizeof(int));
256
257         *(block->work) = sco;
258     }
259
260     return sco;
261
262     /*
263      * Error management (out of normal flow)
264      */
265
266 error_handler_data_i:
267     for (j = 0; j < i; j++)
268     {
269         FREE(sco->internal.data[i]);
270     }
271     FREE(sco->internal.data);
272 error_handler_data:
273     FREE(sco->internal.ballsSize);
274 error_handler_ballsSize:
275     FREE(sco);
276 error_handler_sco:
277     // allocation error
278     set_block_error(-5);
279     return NULL;
280 }
281
282 static void freeScoData(scicos_block * block)
283 {
284     sco_data *sco = (sco_data *) * (block->work);
285     int i;
286
287     if (sco != NULL)
288     {
289         for (i = 0; i < block->insz[0]; i++)
290         {
291             FREE(sco->internal.data[i]);
292         }
293
294         FREE(sco->internal.data);
295         FREE(sco->internal.ballsSize);
296         FREE(sco->scope.cachedArcsUIDs);
297
298         FREE(sco);
299         *(block->work) = NULL;
300     }
301 }
302
303 static void appendData(scicos_block * block, double *x, double *y)
304 {
305     int i;
306     double *upperLeftPoint;
307     double ballSize;
308     sco_data *sco = (sco_data *) * (block->work);
309
310     /*
311      * Update data
312      */
313     if (sco != NULL)
314     {
315         for (i = 0; i < block->insz[0]; i++)
316         {
317             upperLeftPoint = sco->internal.data[i];
318             ballSize = sco->internal.ballsSize[i];
319
320             upperLeftPoint[0] = x[i] - (ballSize / 2);  // x
321             upperLeftPoint[1] = y[i] + (ballSize / 2);  // y
322             upperLeftPoint[2] = 0;  // z
323         }
324     }
325 }
326
327 static BOOL pushData(scicos_block * block, int row)
328 {
329     int iFigureUID;
330     int iAxeUID;
331     int iArcUID;
332
333     double *upperLeftPoint;
334     sco_data *sco;
335
336     iFigureUID = getFigure(block);
337     iAxeUID = getAxe(iFigureUID, block);
338     iArcUID = getArc(iAxeUID, block, row);
339
340     sco = getScoData(block);
341     if (sco == NULL)
342     {
343         return FALSE;
344     }
345
346     upperLeftPoint = sco->internal.data[row];
347     return setGraphicObjectProperty(iArcUID, __GO_UPPER_LEFT_POINT__, upperLeftPoint, jni_double_vector, 3);
348 }
349
350 /*****************************************************************************
351  *
352  * Graphic utils
353  *
354  ****************************************************************************/
355
356 /*****************************************************************************
357  *
358  * Graphic
359  *
360  ****************************************************************************/
361
362 static int getFigure(scicos_block * block)
363 {
364     signed int figNum;
365     int iFigureUID = 0;
366     int iAxe = 0;
367     int i__1 = 1;
368     BOOL b_true = TRUE;
369
370     sco_data *sco = (sco_data *) * (block->work);
371
372     // assert the sco is not NULL
373     if (sco == NULL)
374     {
375         return 0;
376     }
377
378     // fast path for an existing object
379     if (sco->scope.cachedFigureUID)
380     {
381         return sco->scope.cachedFigureUID;
382     }
383
384     figNum = block->ipar[0];
385
386     // with a negative id, use the block number indexed from a constant.
387     if (figNum < 0)
388     {
389         figNum = 20000 + get_block_number();
390     }
391
392     iFigureUID = getFigureFromIndex(figNum);
393     // create on demand
394     if (iFigureUID == 0)
395     {
396         iFigureUID = createNewFigureWithAxes();
397         setGraphicObjectProperty(iFigureUID, __GO_ID__, &figNum, jni_int, 1);
398
399         // the stored uid is a reference to the figure map, not to the current figure
400         iFigureUID = getFigureFromIndex(figNum);
401         sco->scope.cachedFigureUID = iFigureUID;
402
403         // allocate the axes through the getter
404         iAxe = getAxe(iFigureUID, block);
405
406         /*
407          * Setup according to block settings
408          */
409         setGraphicObjectProperty(iAxe, __GO_BOX_TYPE__, &i__1, jni_int, 1);
410         setGraphicObjectProperty(iAxe, __GO_ISOVIEW__, &b_true, jni_bool, 1);
411
412         setBounds(block);
413     }
414
415     if (sco->scope.cachedFigureUID == 0)
416     {
417         sco->scope.cachedFigureUID = iFigureUID;
418     }
419     return iFigureUID;
420 }
421
422 static int getAxe(int iFigureUID, scicos_block * block)
423 {
424     int iAxe;
425     int i;
426
427     sco_data *sco = (sco_data *) * (block->work);
428
429     // assert the sco is not NULL
430     if (sco == NULL)
431     {
432         return 0;
433     }
434
435     // fast path for an existing object
436     if (sco->scope.cachedAxeUID)
437     {
438         return sco->scope.cachedAxeUID;
439     }
440
441     iAxe = findChildWithKindAt(iFigureUID, __GO_AXES__, 0);
442
443     /*
444      * Allocate if necessary
445      */
446     if (iAxe == 0)
447     {
448         cloneAxesModel(iFigureUID);
449         iAxe = findChildWithKindAt(iFigureUID, __GO_AXES__, 0);
450     }
451
452     /*
453      * Setup on first access
454      */
455     if (iAxe != 0)
456     {
457         // allocate the polylines through the getter
458         for (i = 0; i < block->insz[0]; i++)
459         {
460             getArc(iAxe, block, i);
461         }
462     }
463     else
464     {
465         return 0;
466     }
467
468     /*
469      * then cache with local storage
470      */
471     sco->scope.cachedAxeUID = iAxe;
472     return sco->scope.cachedAxeUID;
473 }
474
475 static int getArc(int iAxeUID, scicos_block * block, int row)
476 {
477     static double d__0 = 0.0;
478     static double d__2PI = 2 * M_PI;
479     static BOOL b__true = TRUE;
480
481     int iArc;
482     int color;
483
484     sco_data *sco = (sco_data *) * (block->work);
485
486     // assert the sco is not NULL
487     if (sco == NULL || sco->scope.cachedArcsUIDs == NULL)
488     {
489         return 0;
490     }
491
492     // fast path for an existing object
493     if (sco->scope.cachedArcsUIDs[row])
494     {
495         return sco->scope.cachedArcsUIDs[row];
496     }
497
498     iArc = findChildWithKindAt(iAxeUID, __GO_ARC__, row);
499
500     /*
501      * Allocate if necessary
502      */
503     if (iArc == 0)
504     {
505         iArc = createGraphicObject(__GO_ARC__);
506
507         if (iArc != 0)
508         {
509             createDataObject(iArc, __GO_ARC__);
510             setGraphicObjectRelationship(iAxeUID, iArc);
511         }
512         else
513         {
514             return 0;
515         }
516     }
517
518     /*
519      * Setup on first access
520      */
521     setGraphicObjectProperty(iArc, __GO_START_ANGLE__, &d__0, jni_double, 1);
522     setGraphicObjectProperty(iArc, __GO_END_ANGLE__, &d__2PI, jni_double, 1);
523
524     color = block->ipar[2 + row];
525     setGraphicObjectProperty(iArc, __GO_BACKGROUND__, &color, jni_int, 1);
526
527     setGraphicObjectProperty(iArc, __GO_WIDTH__, &sco->internal.ballsSize[row], jni_double, 1);
528     setGraphicObjectProperty(iArc, __GO_HEIGHT__, &sco->internal.ballsSize[row], jni_double, 1);
529
530     setGraphicObjectProperty(iArc, __GO_FILL_MODE__, &b__true, jni_bool, 1);
531
532     {
533         int iClipState = 1; //on
534         setGraphicObjectProperty(iArc, __GO_CLIP_STATE__, &iClipState, jni_int, 1);
535     }
536
537     /*
538      * then cache with local storage
539      */
540     sco->scope.cachedArcsUIDs[row] = iArc;
541     return sco->scope.cachedArcsUIDs[row];
542 }
543
544 static BOOL setBounds(scicos_block * block)
545 {
546     int iFigureUID;
547     int iAxeUID;
548
549     double dataBounds[6];
550
551     dataBounds[0] = block->rpar[0]; // xMin
552     dataBounds[1] = block->rpar[1]; // xMax
553     dataBounds[2] = block->rpar[2]; // yMin
554     dataBounds[3] = block->rpar[3]; // yMax
555     dataBounds[4] = -1.0;       // zMin
556     dataBounds[5] = 1.0;        // zMax
557
558     iFigureUID = getFigure(block);
559     iAxeUID = getAxe(iFigureUID, block);
560
561     return setGraphicObjectProperty(iAxeUID, __GO_DATA_BOUNDS__, dataBounds, jni_double_vector, 6);
562 }