Merge remote-tracking branch 'origin/master' into yasp
[scilab.git] / scilab / modules / graphics / sci_gateway / c / sci_plot2d.c
1 /*
2 * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 * Copyright (C) 2006 - INRIA - Fabrice Leray
4 * Copyright (C) 2006 - INRIA - Jean-Baptiste Silvy
5 *
6 * This file must be used under the terms of the CeCILL.
7 * This source file is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution.  The terms
9 * are also available at
10 * http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt
11 *
12 */
13
14 /*------------------------------------------------------------------------*/
15 /* file: sci_plot2d.c                                                     */
16 /* desc : interface for plot2d routine                                    */
17 /*------------------------------------------------------------------------*/
18 #include <string.h>
19 #include "gw_graphics.h"
20 #include "GetCommandArg.h"
21 #include "api_scilab.h"
22 #include "BasicAlgos.h"
23 #include "sciCall.h"
24 #include "DefaultCommandArg.h"
25 #include "Scierror.h"
26 #include "localization.h"
27 #include <sciprint.h>
28
29 #include "BuildObjects.h"
30 #include "MALLOC.h"
31
32 /*------------------------------------------------------------------------*/
33 int sci_plot2d(char* fname, void *pvApiCtx)
34 {
35     SciErr sciErr;
36
37     int* piAddrl1 = NULL;
38     double* l1 = NULL;
39     int* piAddrl2 = NULL;
40     double* l2 = NULL;
41     double* lt = NULL;
42     int iTypel1 = 0;
43     int iTypel2 = 0;
44     int lw = 0;
45
46     int m1 = 0, n1 = 0, m2 = 0, n2 = 0;
47     int test = 0, i = 0, j = 0, iskip = 0;
48     int frame_def = 8;
49     int *frame = &frame_def;
50     int axes_def = 1;
51     int *axes = &axes_def;
52
53     /* F.Leray 18.05.04 : log. case test*/
54     int size_x = 0, size_y = 0;
55     char dataflag = 0;
56
57     char* logFlags = NULL;
58     int* style = NULL;
59     double* rect = NULL;
60     char* strf = NULL;
61     char* legend = NULL;
62     int* nax = NULL;
63     BOOL flagNax = FALSE;
64     char strfl[4];
65
66     rhs_opts opts[] =
67     {
68         { -1, "axesflag", -1, 0, 0, NULL},
69         { -1, "frameflag", -1, 0, 0, NULL},
70         { -1, "leg", -1, 0, 0, NULL},
71         { -1, "logflag", -1, 0, 0, NULL},
72         { -1, "nax", -1, 0, 0, NULL},
73         { -1, "rect", -1, 0, 0, NULL},
74         { -1, "strf", -1, 0, 0, NULL},
75         { -1, "style", -1, 0, 0, NULL},
76         { -1, NULL, -1, 0, 0, NULL}
77     };
78
79     if (nbInputArgument(pvApiCtx) == 0)
80     {
81         sci_demo(fname, pvApiCtx);
82         return 0;
83     }
84
85     CheckInputArgument(pvApiCtx, 1, 9);
86
87     iskip = 0;
88     if (getOptionals(pvApiCtx, fname, opts) == 0)
89     {
90         ReturnArguments(pvApiCtx);
91         return 0;
92     }
93
94     if (checkInputArgumentType(pvApiCtx, 1, sci_strings))
95     {
96         /* logflags */
97         GetLogflags(pvApiCtx, fname, 1, opts, &logFlags);
98         iskip = 1;
99     }
100
101     if (FirstOpt(pvApiCtx) == 2 + iskip)                                /** plot2d([loglags,] y, <opt_args>); **/
102     {
103         sciErr = getVarAddressFromPosition(pvApiCtx, 1 + iskip, &piAddrl2);
104         if (sciErr.iErr)
105         {
106             printError(&sciErr, 0);
107             return 1;
108         }
109
110         sciErr = getVarType(pvApiCtx, piAddrl2, &iTypel2);
111         if (sciErr.iErr)
112         {
113             printError(&sciErr, 0);
114             return 1;
115         }
116
117         // the argument can be a matrix of doubles or other
118         // If it is not a matrix of doubles, call overload
119         if (iTypel2 == sci_matrix)
120         {
121
122             // Retrieve a matrix of double at position 1 + iskip.
123             sciErr = getMatrixOfDouble(pvApiCtx, piAddrl2, &m2, &n2, &l2);
124             if (sciErr.iErr)
125             {
126                 printError(&sciErr, 0);
127                 Scierror(202, _("%s: Wrong type for argument %d: A real expected.\n"), fname, 1 + iskip);
128                 return 1;
129             }
130         }
131         else
132         {
133             OverLoad(1);
134             return 0;
135         }
136
137         if (m2 == 1 && n2 > 1)
138         {
139             m2 = n2;
140             n2 = 1;
141         }
142
143         m1 = m2;
144         n1 = n2;
145
146         sciErr = allocMatrixOfDouble(pvApiCtx, nbInputArgument(pvApiCtx) + 1, m1, n1, &l1);
147         if (sciErr.iErr)
148         {
149             printError(&sciErr, 0);
150             Scierror(999, _("%s: Memory allocation error.\n"), fname);
151             return 1;
152         }
153
154         for (i = 0; i < m2 ; ++i)
155         {
156             for (j = 0 ; j < n2 ;  ++j)
157             {
158                 *(l1 + i + m2 * j) = (double) i + 1;
159             }
160         }
161     }
162     else if (FirstOpt(pvApiCtx) >= 3 + iskip)     /** plot2d([loglags,] x, y[, style [,...]]); **/
163     {
164         /* x */
165         sciErr = getVarAddressFromPosition(pvApiCtx, 1 + iskip, &piAddrl1);
166         if (sciErr.iErr)
167         {
168             printError(&sciErr, 0);
169             return 1;
170         }
171
172         sciErr = getVarType(pvApiCtx, piAddrl1, &iTypel1);
173         if (sciErr.iErr)
174         {
175             printError(&sciErr, 0);
176             return 1;
177         }
178
179         // x can be a matrix of doubles or other
180         // If x is not a matrix of doubles, call overload
181         if (iTypel1 == sci_matrix)
182         {
183
184             // Retrieve a matrix of double at position 1 + iskip.
185             sciErr = getMatrixOfDouble(pvApiCtx, piAddrl1, &m1, &n1, &l1);
186             if (sciErr.iErr)
187             {
188                 printError(&sciErr, 0);
189                 Scierror(202, _("%s: Wrong type for argument %d: A real expected.\n"), fname, 1 + iskip);
190                 return 1;
191             }
192         }
193         else
194         {
195             OverLoad(1);
196             return 0;
197         }
198
199         /* y */
200         sciErr = getVarAddressFromPosition(pvApiCtx, 2 + iskip, &piAddrl2);
201         if (sciErr.iErr)
202         {
203             printError(&sciErr, 0);
204             return 1;
205         }
206
207         sciErr = getVarType(pvApiCtx, piAddrl2, &iTypel2);
208         if (sciErr.iErr)
209         {
210             printError(&sciErr, 0);
211             return 1;
212         }
213
214         // y can be a matrix of doubles or other
215         // If y is not a matrix of doubles, call overload
216         if (iTypel2 == sci_matrix)
217         {
218
219             // Retrieve a matrix of double at position 1 + iskip.
220             sciErr = getMatrixOfDouble(pvApiCtx, piAddrl2, &m2, &n2, &l2);
221             if (sciErr.iErr)
222             {
223                 printError(&sciErr, 0);
224                 Scierror(202, _("%s: Wrong type for argument %d: A real expected.\n"), fname, 2 + iskip);
225                 return 1;
226             }
227         }
228         else
229         {
230             OverLoad(2);
231             return 0;
232         }
233
234         test = (m1 * n1 == 0) ||
235                ((m1 == 1 || n1 == 1) && (m2 == 1 || n2 == 1) && (m1 * n1 == m2 * n2))  ||
236                ((m1 == m2) && (n1 == n2)) ||
237                ((m1 == 1 && n1 == m2) || (n1 == 1 && m1 == m2));
238         //CheckDimProp
239         if (!test)
240         {
241             Scierror(999, _("%s: Wrong size for input arguments: Incompatible sizes.\n"), fname);
242             return 1;
243         }
244
245         if (m1 * n1 == 0)
246         {
247             /* default x=1:n */
248             sciErr = allocMatrixOfDouble(pvApiCtx, nbInputArgument(pvApiCtx) + 1, m2, n2, &lt);
249             if (sciErr.iErr)
250             {
251                 printError(&sciErr, 0);
252                 Scierror(999, _("%s: Memory allocation error.\n"), fname);
253                 return 1;
254             }
255
256             if (m2 == 1 && n2 > 1)
257             {
258                 m2 = n2;
259                 n2 = 1;
260             }
261             for (i = 0; i < m2 ; ++i)
262             {
263                 for (j = 0 ; j < n2 ;  ++j)
264                 {
265                     *(lt + i + m2 * j) = (double) i + 1;
266                 }
267             }
268             m1 = m2;
269             n1 = n2;
270             l1 = lt;
271         }
272         else if ((m1 == 1 || n1 == 1) && (m2 != 1 && n2 != 1))
273         {
274             /* a single x vector for mutiple columns for y */
275             sciErr = allocMatrixOfDouble(pvApiCtx, nbInputArgument(pvApiCtx) + 1, m2, n2, &lt);
276             if (sciErr.iErr)
277             {
278                 printError(&sciErr, 0);
279                 Scierror(999, _("%s: Memory allocation error.\n"), fname);
280                 return 1;
281             }
282
283             for (i = 0; i < m2 ; ++i)
284             {
285                 for (j = 0 ; j < n2 ;  ++j)
286                 {
287                     *(lt + i + m2 * j) = *(l1 + i);
288                 }
289             }
290             m1 = m2;
291             n1 = n2;
292             l1 = lt;
293         }
294         else if ((m1 == 1 && n1 == 1) && (n2 != 1))
295         {
296             /* a single y row vector  for a single x */
297             sciErr = allocMatrixOfDouble(pvApiCtx, nbInputArgument(pvApiCtx) + 1, m1, n2, &lt);
298             if (sciErr.iErr)
299             {
300                 printError(&sciErr, 0);
301                 Scierror(999, _("%s: Memory allocation error.\n"), fname);
302                 return 1;
303             }
304
305             for (j = 0 ; j < n2 ;  ++j)
306             {
307                 lt[j] = *l1;
308             }
309             n1 = n2;
310             l1 = lt;
311         }
312         else
313         {
314             if (m2 == 1 && n2 > 1)
315             {
316                 m2 = n2;
317                 n2 = 1;
318             }
319             if (m1 == 1 && n1 > 1)
320             {
321                 m1 = n1;
322                 n1 = 1;
323             }
324         }
325     }
326     else
327     {
328         Scierror(999, _("%s: Wrong number of mandatory input arguments. At least %d expected.\n"), fname, 1);
329         return 0;
330     }
331
332     if (n1 == -1 || n2 == -1 || m1 == -1 || m2 == -1)
333     {
334         Scierror(999, _("%s: Wrong size for input arguments #%d and #%d.\n"), fname, 1, 2); /* @TODO : detail error */
335         return 0;
336     }
337
338     sciGetStyle(pvApiCtx, fname, 3 + iskip, n1, opts, &style);
339     GetStrf(pvApiCtx, fname, 4 + iskip, opts, &strf);
340     GetLegend(pvApiCtx, fname, 5 + iskip, opts, &legend);
341     GetRect(pvApiCtx, fname, 6 + iskip, opts, &rect);
342     GetNax(pvApiCtx, 7 + iskip, opts, &nax, &flagNax);
343
344     if (iskip == 0)
345     {
346         GetLogflags(pvApiCtx, fname, 8, opts, &logFlags);
347     }
348
349     if (isDefStrf(strf))
350     {
351         strcpy(strfl, DEFSTRFN);
352
353         strf = strfl;
354         if (!isDefRect(rect))
355         {
356             strfl[1] = '7';
357         }
358         if (!isDefLegend(legend))
359         {
360             strfl[0] = '1';
361         }
362
363         GetOptionalIntArg(pvApiCtx, fname, 9, "frameflag", &frame, 1, opts);
364         if (frame != &frame_def)
365         {
366             strfl[1] = (char)(*frame + 48);
367         }
368
369         GetOptionalIntArg(pvApiCtx, fname, 9, "axesflag", &axes, 1, opts);
370
371         if (axes != &axes_def)
372         {
373             strfl[2] = (char)(*axes + 48);
374         }
375     }
376
377     /* Make a test on log. mode : available or not depending on the bounds set by Rect arg. or xmin/xmax :
378     Rect case :
379     - if the min bound is strictly posivite, we can use log. mode
380     - if not, send error message
381     x/y min/max case:
382     - we find the first strictly positive min bound in Plo2dn.c ?? */
383
384     switch (strf[1])
385     {
386         case '0':
387             /* no computation, the plot use the previous (or default) scale */
388             break;
389         case '1' :
390         case '3' :
391         case '5' :
392         case '7':
393             /* based on Rect arg */
394             if (rect[0] > rect[2] || rect[1] > rect[3])
395             {
396                 Scierror(999, _("%s: Impossible status min > max in x or y rect data.\n"), fname);
397                 return -1;
398             }
399
400             if (rect[0] <= 0. && logFlags[1] == 'l') /* xmin */
401             {
402                 Scierror(999, _("%s: Bounds on x axis must be strictly positive to use logarithmic mode.\n"), fname);
403                 return -1;
404             }
405
406             if (rect[1] <= 0. && logFlags[2] == 'l') /* ymin */
407             {
408                 Scierror(999, _("%s: Bounds on y axis must be strictly positive to use logarithmic mode.\n"), fname);
409                 return -1;
410             }
411
412             break;
413         case '2' :
414         case '4' :
415         case '6' :
416         case '8':
417         case '9':
418             /* computed from the x/y min/max */
419             if ((int)strlen(logFlags) < 1)
420             {
421                 dataflag = 'g';
422             }
423             else
424             {
425                 dataflag = logFlags[0];
426             }
427
428             switch (dataflag)
429             {
430                 case 'e' :
431                     size_x = (m1 != 0) ? 2 : 0;
432                     break;
433                 case 'o' :
434                     size_x = m1;
435                     break;
436                 case 'g' :
437                 default  :
438                     size_x = (n1 * m1);
439                     break;
440             }
441
442             if (size_x != 0)
443             {
444                 if (logFlags[1] == 'l' && sciFindStPosMin((l1), size_x) <= 0.0)
445                 {
446                     Scierror(999, _("%s: At least one x data must be strictly positive to compute the bounds and use logarithmic mode.\n"), fname);
447                     return -1;
448                 }
449             }
450
451             size_y = (n1 * m1);
452
453             if (size_y != 0)
454             {
455                 if (logFlags[2] == 'l' && sciFindStPosMin((l2), size_y) <= 0.0)
456                 {
457                     Scierror(999, _("%s: At least one y data must be strictly positive to compute the bounds and use logarithmic mode\n"), fname);
458                     return -1;
459                 }
460             }
461
462             break;
463     }
464
465     // open a figure if none already exists
466     getOrCreateDefaultSubwin();
467
468     Objplot2d (1, logFlags, (l1), (l2), &n1, &m1, style, strf, legend, rect, nax, flagNax);
469
470     // Allocated by sciGetStyle (get_style_arg function in GetCommandArg.c)
471     FREE(style);
472
473     AssignOutputVariable(pvApiCtx, 1) = 0;
474     ReturnArguments(pvApiCtx);
475     return 0;
476 }
477 /*------------------------------------------------------------------------*/