Scicos blocks: use the new MVC graphic for scopes
[scilab.git] / scilab / modules / scicos_blocks / src / c / cmat3d.c
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2011 - Scilab Enterprises - ClĂ©ment 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-en.txt
10  *
11  */
12
13 #include "dynlib_scicos_blocks.h"
14 #include "scoUtils.h"
15
16 #include "MALLOC.h"
17 #include "elementary_functions.h"
18
19 #include "getGraphicObjectProperty.h"
20 #include "setGraphicObjectProperty.h"
21 #include "graphicObjectProperties.h"
22 #include "createGraphicObject.h"
23
24 #include "CurrentFigure.h"
25
26 #include "scicos_block4.h"
27 #include "scicos.h"
28 #include "math.h"
29
30 #include "localization.h"
31
32 #include "FigureList.h"
33 #include "BuildObjects.h"
34 #include "AxesModel.h"
35 /*****************************************************************************
36  * Internal container structure
37  ****************************************************************************/
38
39 /**
40  * Container structure
41  */
42 typedef struct
43 {
44     struct
45     {
46         char *cachedFigureUID;
47         char *cachedAxeUID;
48         char *cachedPlot3dUID;
49     } scope;
50 } sco_data;
51
52 /**
53  * Get (and allocate on demand) the internal data used on this scope
54  * \param block the block
55  * \return the scope data
56  */
57 static sco_data *getScoData(scicos_block * block);
58
59 /**
60  * Release any internal data
61  *
62  * \param block the block
63  */
64 static void freeScoData(scicos_block * block);
65
66 /**
67  * Push the block data to the polyline
68  *
69  * \param data the data to push
70  *
71  */
72 static BOOL pushData(scicos_block * block, double *data);
73
74 /*****************************************************************************
75  * Graphics utils
76  ****************************************************************************/
77
78 /**
79  * Get (and allocate on demand) the figure associated with the block
80  * \param block the block
81  * \return a valid figure UID or NULL on error
82  */
83 static char *getFigure(scicos_block * block);
84
85 /**
86  * Get (and allocate on demand) the axe associated with the input
87  *
88  * \param pFigureUID the parent figure UID
89  * \param block the block
90  * \return a valid axe UID or NULL on error
91  */
92 static char *getAxe(char *pFigureUID, scicos_block * block);
93
94 /**
95  * Get (and allocate on demand) the plot3d
96  *
97  * \param pAxeUID the parent axe UID
98  * \param block the block
99  * \return a valid plot3d UID or NULL on error
100  */
101 static char *getPlot3d(char *pAxeUID, scicos_block * block);
102
103 /**
104  * Set the plot3d and axes bounds
105  *
106  * \param block the block
107  * \param pAxeUID the axe
108  * \param pPlot3dUID the plot3d
109  */
110 static BOOL setBounds(scicos_block * block, char *pAxeUID, char *pPlot3dUID);
111
112 /**
113  * Set the plot3d settings
114  *
115  * \param block the block
116  * \param pPlot3dUID the plot3d
117  */
118 static BOOL setPlot3dSettings(scicos_block * block, char *pPlot3dUID);
119
120 /**
121  * Set the plot3d default values
122  *
123  * \param block the block
124  * \param pPlot3dUID the plot3d
125  */
126 static BOOL setDefaultValues(scicos_block * block, char *pPlot3dUID);
127
128 /*****************************************************************************
129  * Simulation function
130  ****************************************************************************/
131
132 /** \fn void cmatview(scicos_block * block,int flag)
133     \brief the computational function
134     \param block A pointer to a scicos_block
135     \param flag An int which indicates the state of the block (init, update, ending)
136 */
137 SCICOS_BLOCKS_IMPEXP void cmat3d(scicos_block * block, scicos_flag flag)
138 {
139     char *pFigureUID;
140
141     double *u;
142     sco_data *sco;
143
144     int i;
145     BOOL result;
146
147     switch (flag)
148     {
149
150     case Initialization:
151         sco = getScoData(block);
152         if (sco == NULL)
153         {
154             set_block_error(-5);
155         }
156         pFigureUID = getFigure(block);
157         if (pFigureUID == NULL)
158         {
159             // allocation error
160             set_block_error(-5);
161         }
162         break;
163
164     case StateUpdate:
165         pFigureUID = getFigure(block);
166
167         u = GetRealInPortPtrs(block, 1);
168
169         result = pushData(block, u);
170         if (result == FALSE)
171         {
172             Coserror("%s: unable to push some data.", "cmatview");
173             break;
174         }
175         break;
176
177     case Ending:
178         freeScoData(block);
179         break;
180
181     default:
182         break;
183     }
184 }
185
186 /*-------------------------------------------------------------------------*/
187
188 /*****************************************************************************
189  *
190  * Container management
191  *
192  ****************************************************************************/
193
194 static sco_data *getScoData(scicos_block * block)
195 {
196     sco_data *sco = (sco_data *) * (block->work);
197     BOOL result;
198
199     if (sco == NULL)
200     {
201         /*
202          * Data allocation
203          */
204
205         sco = (sco_data *) MALLOC(sizeof(sco_data));
206         if (sco == NULL)
207             goto error_handler_sco;
208
209         sco->scope.cachedFigureUID = NULL;
210         sco->scope.cachedAxeUID = NULL;
211         sco->scope.cachedPlot3dUID = NULL;
212
213         *(block->work) = sco;
214     }
215
216     return sco;
217
218     /*
219      * Error management (out of normal flow)
220      */
221
222 error_handler_sco:
223     // allocation error
224     set_block_error(-5);
225     return NULL;
226 }
227
228 static void freeScoData(scicos_block * block)
229 {
230     sco_data *sco = (sco_data *) * (block->work);
231     int i, j;
232
233     if (sco != NULL)
234     {
235         FREE(sco);
236     }
237 }
238
239 static BOOL pushData(scicos_block * block, double *data)
240 {
241     char *pFigureUID;
242     char *pAxeUID;
243     char *pPlot3dUID;
244
245     BOOL result;
246     int i;
247
248     int m, n;
249
250     pFigureUID = getFigure(block);
251     pAxeUID = getAxe(pFigureUID, block);
252     pPlot3dUID = getPlot3d(pAxeUID, block);
253
254     m = GetInPortSize(block, 1, 1);
255     n = GetInPortSize(block, 1, 2);
256
257     result = setGraphicObjectProperty(pPlot3dUID, __GO_DATA_MODEL_Z__, data, jni_double_vector, m * n);
258
259     return result;
260 }
261
262 /*****************************************************************************
263  *
264  * Graphic utils
265  *
266  ****************************************************************************/
267
268 /*****************************************************************************
269  *
270  * Graphic
271  *
272  ****************************************************************************/
273
274 static char *getFigure(scicos_block * block)
275 {
276     signed int figNum;
277     char *pFigureUID = NULL;
278     char *pAxe = NULL;
279     static const int i__1 = 1;
280     sco_data *sco = (sco_data *) * (block->work);
281
282     int i, j;
283
284     // fast path for an existing object
285     if (sco->scope.cachedFigureUID != NULL)
286     {
287         return sco->scope.cachedFigureUID;
288     }
289
290     figNum = block->ipar[0];
291
292     // with a negative id, use the block number indexed from a constant.
293     if (figNum < 0)
294     {
295         figNum = 20000 + get_block_number();
296     }
297
298     pFigureUID = getFigureFromIndex(figNum);
299     // create on demand
300     if (pFigureUID == NULL)
301     {
302         pFigureUID = createNewFigureWithAxes();
303         setGraphicObjectProperty(pFigureUID, __GO_ID__, &figNum, jni_int, 1);
304
305         setGraphicObjectProperty(pFigureUID, __GO_COLORMAP__, block->rpar, jni_double_vector, block->ipar[2]);
306
307         // allocate the axes through the getter
308         pAxe = getAxe(pFigureUID, block);
309
310         /*
311          * Setup according to block settings
312          */
313         setLabel(pAxe, __GO_X_AXIS_LABEL__, "x");
314         setLabel(pAxe, __GO_Y_AXIS_LABEL__, "y");
315         setLabel(pAxe, __GO_Z_AXIS_LABEL__, "z");
316
317         setGraphicObjectProperty(pAxe, __GO_X_AXIS_VISIBLE__, &i__1, jni_bool, 1);
318         setGraphicObjectProperty(pAxe, __GO_Y_AXIS_VISIBLE__, &i__1, jni_bool, 1);
319         setGraphicObjectProperty(pAxe, __GO_Z_AXIS_VISIBLE__, &i__1, jni_bool, 1);
320
321         sco->scope.cachedFigureUID = pFigureUID;
322     }
323
324     if (sco->scope.cachedFigureUID == NULL)
325     {
326         sco->scope.cachedFigureUID = pFigureUID;
327     }
328     return pFigureUID;
329 }
330
331 static char *getAxe(char *pFigureUID, scicos_block * block)
332 {
333     char *pAxe;
334     int i;
335     static const int i__1 = 1;
336     sco_data *sco = (sco_data *) * (block->work);
337
338     // fast path for an existing object
339     if (sco->scope.cachedAxeUID != NULL)
340     {
341         return sco->scope.cachedAxeUID;
342     }
343
344     pAxe = findChildWithKindAt(pFigureUID, __GO_AXES__, 0);
345
346     /*
347      * Allocate if necessary
348      */
349     if (pAxe == NULL)
350     {
351         pAxe = cloneGraphicObject(getAxesModel());
352
353         if (pAxe != NULL)
354         {
355             setGraphicObjectRelationship(pFigureUID, pAxe);
356
357             getPlot3d(pAxe, block);
358         }
359     }
360
361     if (sco->scope.cachedAxeUID == NULL)
362     {
363         sco->scope.cachedAxeUID = pAxe;
364     }
365     return pAxe;
366 }
367
368 static char *getPlot3d(char *pAxeUID, scicos_block * block)
369 {
370     char *pPlot3d;
371     static const double d__0 = 0.0;
372     static const int i__0 = 0;
373     static const BOOL b__true = TRUE;
374
375     int color;
376
377     sco_data *sco = (sco_data *) * (block->work);
378
379     // fast path for an existing object
380     if (sco->scope.cachedPlot3dUID != NULL)
381     {
382         return sco->scope.cachedPlot3dUID;
383     }
384
385     pPlot3d = findChildWithKindAt(pAxeUID, __GO_PLOT3D__, 0);
386
387     /*
388      * Allocate if necessary
389      */
390     if (pPlot3d == NULL)
391     {
392         pPlot3d = createGraphicObject(__GO_PLOT3D__);
393
394         if (pPlot3d != NULL)
395         {
396             createDataObject(pPlot3d, __GO_PLOT3D__);
397             setGraphicObjectRelationship(pAxeUID, pPlot3d);
398
399             setBounds(block, pAxeUID, pPlot3d);
400             setPlot3dSettings(block, pPlot3d);
401             setDefaultValues(block, pPlot3d);
402         }
403     }
404
405     if (sco->scope.cachedPlot3dUID == NULL)
406     {
407         sco->scope.cachedPlot3dUID = pPlot3d;
408     }
409     return pPlot3d;
410 }
411
412 static BOOL setBounds(scicos_block * block, char *pAxeUID, char *pPlot3dUID)
413 {
414     BOOL result;
415
416     int gridSize[4];
417     double dataBounds[6];
418     double rotationAngle[2];
419
420     int m, n;
421     int colormapLen;
422
423     m = GetInPortSize(block, 1, 1);
424     n = GetInPortSize(block, 1, 2);
425
426     gridSize[0] = 1;
427     gridSize[1] = n;
428     gridSize[2] = 1;
429     gridSize[3] = m;
430
431     colormapLen = block->ipar[3];
432     if (colormapLen == 1)
433     {
434         dataBounds[0] = 0;      // xMin
435         dataBounds[1] = (double)n;  // xMax
436         dataBounds[2] = 0;      // yMin
437         dataBounds[3] = (double)m;  // yMax
438     }
439     else
440     {
441         dataBounds[0] = block->rpar[colormapLen + 0];   // xMin
442         dataBounds[1] = block->rpar[colormapLen + 1];   // xMax
443         dataBounds[2] = block->rpar[colormapLen + 2];   // yMin
444         dataBounds[3] = block->rpar[colormapLen + 3];   // yMax
445     }
446
447     dataBounds[4] = (double)block->ipar[0]; // zMin
448     dataBounds[5] = (double)block->ipar[1]; // zMax
449
450     rotationAngle[0] = 80;      // alpha
451     rotationAngle[1] = 250;     // theta
452
453     result = setGraphicObjectProperty(pPlot3dUID, __GO_DATA_MODEL_GRID_SIZE__, gridSize, jni_int_vector, 4);
454     result &= setGraphicObjectProperty(pAxeUID, __GO_DATA_BOUNDS__, dataBounds, jni_double_vector, 6);
455     result &= setGraphicObjectProperty(pAxeUID, __GO_ROTATION_ANGLES__, rotationAngle, jni_double_vector, 2);
456
457     return result;
458 }
459
460 static BOOL setPlot3dSettings(scicos_block * block, char *pPlot3dUID)
461 {
462     static const int i__1 = 1;
463     static const double d__1 = 1.0;
464     static const int i__2 = 2;
465     static const int i__4 = 4;
466
467     BOOL result = TRUE;
468
469     result &= setGraphicObjectProperty(pPlot3dUID, __GO_SURFACE_MODE__, &i__1, jni_bool, 1);
470     result &= setGraphicObjectProperty(pPlot3dUID, __GO_LINE_THICKNESS__, &d__1, jni_double, 1);
471
472     result &= setGraphicObjectProperty(pPlot3dUID, __GO_COLOR_MODE__, &i__2, jni_int, 1);
473     result &= setGraphicObjectProperty(pPlot3dUID, __GO_COLOR_FLAG__, &i__1, jni_int, 1);
474     result &= setGraphicObjectProperty(pPlot3dUID, __GO_HIDDEN_COLOR__, &i__4, jni_int, 1);
475
476     return result;
477 }
478
479 static BOOL setDefaultValues(scicos_block * block, char *pPlot3dUID)
480 {
481     int m, n, len;
482     int i;
483     double *values;
484
485     BOOL result;
486
487     m = GetInPortSize(block, 1, 1);
488     n = GetInPortSize(block, 1, 2);
489
490     /*
491      * Share the same memory for 0 allocation (z) and incremented index (x and y)
492      */
493     values = (double *)CALLOC(n * m, sizeof(double));
494     if (values == NULL)
495     {
496         return FALSE;
497     }
498     result = setGraphicObjectProperty(pPlot3dUID, __GO_DATA_MODEL_Z__, values, jni_double_vector, m * n);
499
500     len = max(m, n);
501     for (i = 1; i <= len; i++)
502     {
503         values[i] = (double)i;
504     }
505
506     result &= setGraphicObjectProperty(pPlot3dUID, __GO_DATA_MODEL_X__, values, jni_double_vector, n);
507     result &= setGraphicObjectProperty(pPlot3dUID, __GO_DATA_MODEL_Y__, values, jni_double_vector, m);
508
509     FREE(values);
510     return result;
511 }