Added some missing headers reported by /usr/lib/build/checks-data/check_gcc_output
[scilab.git] / scilab / modules / graphics / src / c / Plo2dn.c
1 /*
2  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  * Copyright (C) 2002-2004 - INRIA - Djalel Abdemouche
4  * Copyright (C) 2004-2006 - INRIA - Fabrice Leray
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  *    Graphic library
16  --------------------------------------------------------------------------*/
17 #include <string.h>
18 #include "math_graphics.h"
19 #include "PloEch.h"
20 #include "Plot2d.h"
21
22 #define spINSIDE_SPARSE
23 #include "../../sparse/includes/spConfig.h"
24
25 #include "SetProperty.h"
26 #include "DrawObjects.h"
27 #include "BuildObjects.h"
28 #include "Axes.h"
29 #include "BasicAlgos.h"
30 #include "sciprint.h"
31 #include "Scierror.h"
32 #include "CurrentObjectsManagement.h"
33 #include "GraphicSynchronizerInterface.h"
34
35 #include "MALLOC.h" /* MALLOC */
36 #include "DrawingBridge.h"
37 #include "scitokenize.h"
38 #include "localization.h"
39 #include "get_ticks_utils.h"
40 #include "HandleManagement.h"
41 #include "freeArrayOfString.h"
42
43 /*--------------------------------------------------------------------
44  *  plot2dn(ptype,Logflags,x,y,n1,n2,style,strflag,legend,brect,aaint,lstr1,lstr2)
45  *  
46  *  Draw *n1 curves of *n2 points each
47  *
48  *  ptype is an int which gives the polyline drawind mode (0,1,2,3,4)
49  *
50  *  Logflags is a two character string
51  *
52  *  (x[i+(*n2)*j] ,y[i+(*n2)*j]) Double values giving the point
53  *  position of point i of curve j (i=0,*n2-1 j=0,*n1-1)
54  *
55  *  style[*n1]-> give the style to use for each curve 
56  *     if style is positive --> a mark is used (mark id = style[i])
57  *     if style is strictly negative --> a dashed line is used 
58  *        (dash id = abs(style[i])
59  *     if there's only one curve, style can be of type style[0]=style,
60  *     style[1]=pos ( pos in [1,6]) 
61  *     pos give the legend position (1 to 6) (this can be iteresting
62  *     if you want to superpose curves with different legends by 
63  *     calling plot2d more than one time.
64  *
65  *  strflag[3] is a string
66  *  
67  *     if strflag[0] == '1' then legends are added 
68  *        legend = "leg1@leg2@....@legn"; gives the legend for each curve
69  *      else no legend
70  *
71  *     if strflag[1] == '1' then  the values of brect are used to fix 
72  *        the drawing boundaries :  brect[]= <xmin,ymin,xmax,ymax>;
73  *      if strflag[1] == '2' then the values  are computed from data
74  *      else if strflag[1]=='0' the previous values 
75  *                (previous call or defaut values) are used 
76  *
77  *     if  strflag[2] == '1' ->then an axis is added
78  *        the number of intervals 
79  *        is specified by the vector aaint[4] of integers 
80  *         <aaint[0],aaint[1]> specifies the x-axis number of  points 
81  *         <aaint[2],aaint[3]> same for y-axis
82  *     if  strflag[2] == '2' -> no axis, only a box around the curves
83  *     else no box and no axis 
84
85  * lstr* : unused ( but used by Fortran ) 
86  *--------------------------------------------------------------------------*/
87   
88 int plot2dn(int ptype,char *logflags,double *x,double *y,int *n1,int *n2,int *style,char *strflag,char *legend,double *brect,int *aaint,BOOL flagNax, int lstr1,int lstr2)
89 {
90   int closeflag = 0;
91   int jj = 0;
92   long long *tabofhandles = NULL ;
93   sciPointObj  *psubwin = NULL ;
94   sciPointObj * curFigure = NULL;
95   long hdl;
96   long *hdltab = NULL ;
97   int cmpt=0;
98   int with_leg;
99   double drect[6];
100   char dataflag;
101   sciSubWindow * ppsubwin = NULL;
102   BOOL bounds_changed = FALSE;
103   BOOL axes_properties_changed = FALSE;
104
105   startGraphicDataWriting();
106   curFigure = sciGetCurrentFigure();
107   psubwin = sciGetCurrentSubWin();
108   ppsubwin = pSUBWIN_FEATURE(psubwin);
109   endGraphicDataWriting();
110
111   startFigureDataWriting(curFigure);
112
113   /* check if the auto_clear property is on and then erase everything */
114   checkRedrawing() ;
115   
116   if (sciGetSurface(psubwin) == (sciPointObj *) NULL) /* F.Leray 18.05.04 */
117     {
118       ppsubwin->is3d = FALSE;
119       ppsubwin->project[2]= 0;
120     }
121   else
122     {
123       ppsubwin->theta_kp=ppsubwin->theta;
124       ppsubwin->alpha_kp=ppsubwin->alpha;
125     }
126   
127   ppsubwin->alpha  = 0.0;
128   ppsubwin->theta  = 270.0;
129
130   /* Force psubwin->logflags to those given by argument*/
131   if ( ppsubwin->FirstPlot )
132   {
133     char newLogFlags[3];
134     sciGetLogFlags(psubwin, newLogFlags);
135     newLogFlags[0] = logflags[1];
136     newLogFlags[1] = logflags[2];
137     sciSetLogFlags(psubwin, newLogFlags);
138   }
139
140   /* Force "cligrf" clipping */
141   sciSetIsClipping (psubwin,0); 
142
143   if (sciGetGraphicMode (psubwin)->autoscaling) {
144     /* compute and merge new specified bounds with psubwin->Srect */
145     switch (strflag[1])  {
146     case '0': 
147       /* do not change psubwin->Srect */
148       break;
149     case '1' : case '3' : case '5' : case '7':
150       /* Force psubwin->Srect=brect */
151       re_index_brect(brect, drect);
152       break;
153     case '2' : case '4' : case '6' : case '8': case '9':
154       /* Force psubwin->Srect to the x and y bounds */
155       if ( (int)strlen(logflags) < 1) dataflag='g' ; else dataflag=logflags[0];
156       compute_data_bounds2(0,dataflag,ppsubwin->logflags,x,y,*n1,*n2,drect);
157       break;
158     }
159     if (!pSUBWIN_FEATURE(psubwin)->FirstPlot && 
160         (strflag[1] == '5' || strflag[1] == '7' || strflag[1] == '8' || strflag[1] == '9')) { /* merge psubwin->Srect and drect */
161       
162       drect[0] = Min(ppsubwin->SRect[0],drect[0]); /*xmin*/
163       drect[2] = Min(ppsubwin->SRect[2],drect[2]); /*ymin*/
164       drect[1] = Max(ppsubwin->SRect[1],drect[1]); /*xmax*/
165       drect[3] = Max(ppsubwin->SRect[3],drect[3]); /*ymax*/
166       
167     }
168     if (strflag[1] != '0')
169       bounds_changed = update_specification_bounds(psubwin, drect,2);
170   } 
171   
172   if(ppsubwin->FirstPlot == TRUE) bounds_changed = TRUE;
173   
174   axes_properties_changed = strflag2axes_properties(psubwin, strflag);
175      
176   ppsubwin->FirstPlot = FALSE; /* just after strflag2axes_properties */
177    
178   with_leg= (strflag[0] == '1');
179
180   /* F.Leray 07.10.04 : trigger algo to init. manual graduation u_xgrads and 
181      u_ygrads if nax (in matdes.c which is == aaint HERE) was specified */
182   
183   ppsubwin->flagNax = flagNax; /* store new value for flagNax */
184
185   if(ppsubwin->flagNax == TRUE){
186     if(ppsubwin->logflags[0] == 'n' && ppsubwin->logflags[1] == 'n')
187       {
188         BOOL autoTicks[3];
189         sciGetAutoTicks(psubwin, autoTicks);
190         /* x and y graduations are imposed by Nax */
191         sciSetAutoTicks(psubwin, FALSE, FALSE, autoTicks[2]);
192         
193         CreatePrettyGradsFromNax(psubwin,aaint);
194       }
195     else
196     {
197       sciprint(_("Warning: Nax does not work with logarithmic scaling.\n"));
198     }
199   }
200   endFigureDataWriting(curFigure);
201   
202   /*if(bounds_changed == TRUE || axes_properties_changed == TRUE)
203   {
204     
205     sciDrawObj(sciGetCurrentFigure());
206   }*/
207   
208   /*---- Drawing the curves and the legends ----*/
209   if ( *n1 != 0 ) {
210           if ((hdltab = MALLOC ((*n1+1) * sizeof (long))) == NULL) {
211                   Scierror(999, _("%s: No more memory.\n"),"plot2d");
212                   return -1;
213     }
214     if (with_leg) {
215       /* tabofhandles allocated for legends */
216       if ((tabofhandles = MALLOC((*n1)*sizeof(long long))) == NULL) {
217         Scierror(999, _("%s: No more memory.\n"),"plot2d");
218         FREE(hdltab);
219         return -1;
220       }
221     }
222
223     startFigureDataWriting(curFigure);
224     for (jj = 0;jj < *n1; jj++) {/*A.Djalel 3D axes*/
225       sciPointObj * pobj = NULL;
226       if (style[jj] > 0) { 
227         BOOL isline = TRUE;
228         if (ptype==3)
229         {
230           isline=FALSE;
231         }
232         pobj = ConstructPolyline(sciGetCurrentSubWin(),&(x[jj*(*n2)]),
233                                  &(y[jj*(*n2)]),PD0,closeflag,*n2,ptype,
234                                  &style[jj],NULL,NULL,NULL,NULL, 
235                                  isline,FALSE,FALSE,FALSE);
236       }
237       else {
238         int minusstyle = -style[jj];
239         pobj = ConstructPolyline(sciGetCurrentSubWin(),&(x[jj*(*n2)]),
240                                  &(y[jj*(*n2)]),PD0,closeflag,*n2,ptype,
241                                  NULL,NULL,&minusstyle,NULL,NULL,FALSE,FALSE,TRUE,FALSE);
242       }
243       if (pobj == NULL)
244       {
245         // skip
246         Scierror(999, _("%s: No more memory.\n"), "plot2d");
247       }
248       else
249       {
250         
251         sciSetCurrentObj(pobj);
252       
253         /*sciDrawObjIfRequired(pobj);*/
254         hdl=sciGetHandle(pobj);
255         if (with_leg)
256         {
257           tabofhandles[cmpt] = hdl;
258         }
259
260         hdltab[cmpt]=hdl;
261         cmpt++;
262       }
263       
264     }
265     endFigureDataWriting(curFigure);
266     forceRedraw(psubwin);
267     
268     /*---- Drawing the Legends ----*/
269     startFigureDataWriting(curFigure);
270
271     if (with_leg) {
272       char ** Str;
273       int nleg;
274       sciPointObj * Leg;
275       if (scitokenize(legend, &Str, &nleg)) {
276         FREE(tabofhandles);
277         FREE(hdltab);
278         Scierror(999, _("%s: No more memory.\n"),"plot2d");
279         endFigureDataWriting(curFigure);
280         return 0;
281       }
282       Leg = ConstructLegend(sciGetCurrentSubWin(),Str,tabofhandles,Min(nleg,cmpt));
283         if (Leg != NULL)
284           {
285             pLEGEND_FEATURE(Leg)->place = SCI_LEGEND_LOWER_CAPTION;
286             sciSetIsFilled (Leg, FALSE);
287             sciSetIsLine (Leg, FALSE);
288             sciSetCurrentObj (Leg); 
289           }
290
291     freeArrayOfString(Str, nleg);  
292
293         FREE(tabofhandles);
294         /* }*/
295     }
296
297     /*---- construct Compound ----*/
298     if (cmpt > 0)
299     {
300       sciSetCurrentObj(ConstructCompound (hdltab, cmpt));
301     }
302     FREE(hdltab);
303     endFigureDataWriting(curFigure);
304     
305   }
306   
307   sciDrawObj(curFigure);
308   return(0);
309 }
310
311
312
313
314 /* Given two set of coordinates x and y this routine computes the corresponding 
315  *  data bounds rectangle drect=[xmin,ymin,xmax,ymax] taking into account the logflag
316  *  -> means we have to find among the data the min > 0.
317  */
318 void compute_data_bounds2(int cflag,char dataflag, char * logflags, double *x,double  *y, int n1,int n2, double *drect)
319 {
320   int size_x,size_y;
321   double xd[2];
322   double *x1;
323   switch ( dataflag ) {
324   case 'e' : 
325     xd[0] = 1.0; xd[1] = (double)n2;
326     x1 = xd;size_x = (n2 != 0) ? 2 : 0 ;
327     break; 
328   case 'o' : 
329     x1 = x;size_x = n2;
330     break;
331   case 'g' : 
332   default  : 
333     x1 = x;size_x = (cflag == 1) ? n1 : (n1*n2) ;
334     break; 
335   }
336
337   if (size_x != 0) {
338     if(logflags[0] != 'l'){
339       drect[0] =  Mini(x1, size_x); 
340       drect[1] =  Maxi(x1,size_x); 
341     }
342     else { /* log. case */
343       drect[0] =  sciFindStPosMin(x1,size_x); 
344       drect[1] =  Maxi(x1,size_x); 
345     }
346     
347   }
348   else {
349     if(logflags[0] != 'l'){
350       drect[0] = 0.0;
351       drect[1] = 10.0;
352     }
353     else{/* log. case */
354       drect[0] = 1.0;
355       drect[1] = 10.0;
356     }
357   }
358
359   size_y = (cflag == 1) ? n2 : (n1*n2) ;
360   if (size_y != 0) {
361     if(logflags[1] != 'l'){
362       drect[2] =  Mini(y, size_y); 
363       drect[3] =  Maxi(y,size_y); 
364     }
365     else{/* log. case */
366       drect[2] =  sciFindStPosMin(y,size_y); 
367       drect[3] =  Maxi(y,size_y); 
368     }
369
370   }
371   else {
372     if(logflags[1] != 'l'){
373       drect[2] = 0.0;
374       drect[3] = 10.0;
375     }
376     else{/* log. case */
377       drect[2] = 1.0;
378       drect[3] = 10.0;
379     }
380   }
381   /* back to default values for  x=[] and y = [] */
382   if ( drect[2] == LARGEST_REAL ) { drect[2] = 0.0; drect[3] = 10.0 ;} 
383   if ( drect[0] == LARGEST_REAL ) { drect[0] = 0.0; drect[1] = 10.0 ;} 
384
385 }
386
387
388
389 BOOL update_specification_bounds(sciPointObj  *psubwin,double rect[6],int flag)
390 {
391   sciSubWindow * ppsubwin = pSUBWIN_FEATURE (psubwin);
392   BOOL haschanged = FALSE;
393   
394   ppsubwin->SRect[0] = rect[0];
395   ppsubwin->SRect[1] = rect[1];
396   ppsubwin->SRect[2] = rect[2];
397   ppsubwin->SRect[3] = rect[3];
398   if (flag==3) {
399     ppsubwin->SRect[4] = rect[4];
400     ppsubwin->SRect[5] = rect[5];
401   }
402   
403   if(flag != 3)
404     haschanged = sci_update_frame_bounds_2d(psubwin);
405   else
406     haschanged = sci_update_frame_bounds_3d(psubwin);
407   
408   
409   return haschanged;
410 }
411
412
413
414
415 /* F.Leray */
416 /* brect must have the same format as drect i.e.: [xmin,xmax,ymin,ymax] */
417 /* brect = INPUT ; drect = OUTPUT (warning drect is dim 6) */
418 int re_index_brect(double * brect, double * drect)
419 {
420   drect[0] = brect[0];
421   drect[1] = brect[2];
422   drect[2] = brect[1];
423   drect[3] = brect[3];
424   
425   return 0;
426 }
427 /* F.Leray 07.05.04 */
428 /* Dispatch info contained in strflag to all the flag available in
429    sciSubwin object (tight_limits, isoview, isaxes...) */
430 BOOL strflag2axes_properties(sciPointObj * psubwin, char * strflag)
431 {
432   BOOL haschanged = FALSE;
433   sciSubWindow * ppsubwin = pSUBWIN_FEATURE (psubwin);
434         BOOL axesVisiblePrev[3] = {ppsubwin->axes.axes_visible[0],
435                                    ppsubwin->axes.axes_visible[1],
436                                    ppsubwin->axes.axes_visible[2]};
437         EAxesBoxType boxPrev = ppsubwin->axes.rect;
438         char xLocPrev = ppsubwin->axes.xdir;
439         char yLocPrev = ppsubwin->axes.ydir;
440         BOOL tightLimitsPrev = ppsubwin->tight_limits;
441         BOOL isoviewPrev = ppsubwin->isoview;
442
443   /* F.Leray 07.05.04 */
444   /* strflag[1] Isoview & tight_limits flags management*/
445   switch (strflag[1])  {
446   case '0': case '9':
447     /* no changes */
448     break;
449   case '1' : case '2' : case '7' : case '8' :
450     ppsubwin->tight_limits = TRUE;
451     break;
452   case '3' : case '4' :
453     ppsubwin->isoview = TRUE;
454     break;
455   case '5' : case '6' :
456     ppsubwin->tight_limits = FALSE; /* pretty axes */
457     break;
458   }
459       
460   /* F.Leray 07.05.04 */
461   /* strflag[2] */
462   switch (strflag[2])  {
463   case '0': 
464     if(ppsubwin->FirstPlot == TRUE){
465       ppsubwin->axes.axes_visible[0] = FALSE;
466       ppsubwin->axes.axes_visible[1] = FALSE;
467       ppsubwin->axes.axes_visible[2] = FALSE; /* also trigger z axis */
468       ppsubwin->axes.rect = BT_OFF;
469     }
470     /*else no changes : the isaxes properties is driven by the previous plot */
471     break;
472   case '1' : 
473     ppsubwin->axes.axes_visible[0] = TRUE;
474     ppsubwin->axes.axes_visible[1] = TRUE;
475     ppsubwin->axes.axes_visible[2] = TRUE; /* also trigger z axis */
476     ppsubwin->axes.ydir ='l';
477     ppsubwin->axes.rect = BT_ON;
478     break;
479   case '2' : 
480     ppsubwin->axes.axes_visible[0] = FALSE;
481     ppsubwin->axes.axes_visible[1] = FALSE;
482     ppsubwin->axes.axes_visible[2] = FALSE; /* also trigger z axis */
483     ppsubwin->axes.rect = BT_ON;
484     break;
485   case '3' : 
486     ppsubwin->axes.axes_visible[0] = TRUE;
487     ppsubwin->axes.axes_visible[1] = TRUE;
488     ppsubwin->axes.axes_visible[2] = TRUE; /* also trigger z axis */
489                 ppsubwin->axes.rect = BT_OFF;
490     ppsubwin->axes.ydir ='r';
491     break;
492   case '4' :
493     ppsubwin->axes.axes_visible[0] = TRUE;
494     ppsubwin->axes.axes_visible[1] = TRUE;
495     ppsubwin->axes.axes_visible[2] = TRUE; /* also trigger z axis */
496                 ppsubwin->axes.xdir ='c';
497     ppsubwin->axes.ydir ='c';
498                 ppsubwin->axes.rect = BT_OFF;
499     break;
500   case '5' :
501     ppsubwin->axes.axes_visible[0] = TRUE;
502     ppsubwin->axes.axes_visible[1] = TRUE;
503     ppsubwin->axes.axes_visible[2] = TRUE; /* also trigger z axis */
504     ppsubwin->axes.xdir ='c';
505     ppsubwin->axes.ydir ='c';
506     ppsubwin->axes.rect = BT_ON;
507     break;
508   case '9' :
509     ppsubwin->axes.axes_visible[0] = TRUE;
510     ppsubwin->axes.axes_visible[1] = TRUE;
511     ppsubwin->axes.axes_visible[2] = TRUE; /* also trigger z axis */
512   }
513
514         /* Find if something has changed */
515         if (   ppsubwin->axes.axes_visible[0] != axesVisiblePrev[0]
516             || ppsubwin->axes.axes_visible[1] != axesVisiblePrev[1]
517                         || ppsubwin->axes.axes_visible[2] != axesVisiblePrev[2]
518                         || ppsubwin->axes.rect != boxPrev
519                         || ppsubwin->axes.xdir != xLocPrev
520                         || ppsubwin->axes.ydir != yLocPrev
521                         || ppsubwin->tight_limits != tightLimitsPrev
522                         || ppsubwin->isoview != isoviewPrev)
523         {
524                 haschanged = TRUE;
525         }
526         else
527         {
528                 haschanged = FALSE;
529         }
530
531
532   return haschanged;
533 }
534
535
536