c6b3142c840fc6b251889f92675ae6dab09af890
[scilab.git] / scilab / modules / graphics / src / c / Champ.c
1 /*------------------------------------------------------------------------
2  *    Graphic library
3  *    Copyright (C) 1998-2001 Enpc/Jean-Philippe Chancelier
4  *    jpc@cermics.enpc.fr 
5  --------------------------------------------------------------------------*/
6
7 #include <math.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include "math_graphics.h"
11 #include "Graphics.h" 
12 #include "PloEch.h"
13
14 #include "GetProperty.h"
15 #include "SetProperty.h"
16 #include "DrawObjects.h"
17 #include "BuildObjects.h"
18 #include "Axes.h"
19 #include "Xcall1.h"
20 #include "Champ.h"
21
22
23 #include "MALLOC.h" /* MALLOC */
24
25 static double MiniD __PARAMS((double *x,integer n));
26 extern void Champ2DRealToPixel __PARAMS((integer *xm,integer *ym,integer *zm,integer *na,
27                                          integer *arsize,integer *colored,double *x,double *y,
28                                          double  *fx,double *fy,integer *n1,integer *n2,double *arfact));
29 extern void initsubwin();
30 /* extern void compute_data_bounds(int cflag,char dataflag,double *x,double *y,int n1,int n2,double *drect); */
31 extern void compute_data_bounds2(int cflag,char dataflag,char *logflags,double *x,double *y,int n1,int n2,double *drect);
32 extern BOOL update_specification_bounds(sciPointObj *psubwin, double *rect,int flag);
33 extern int re_index_brect(double * brect, double * drect);
34 extern BOOL strflag2axes_properties(sciPointObj * psubwin, char * strflag);
35
36 /*-----------------------------------------------------------------
37  *  int C2F(champ)(x,y,fx,fy,n1,n2,strflag,brect,arfact,lstr)
38  *  int C2F(champ1)(x,y,fx,fy,n1,n2,strflag,brect,arfact,lstr)
39  *
40  * Used for Drawing 2 dimensional vector fields 
41  * (fx[i+(*n1)*j], fy[i+(*n1)*j]) is the value of the vector field 
42  * at point X=(x[i],y[j]);
43  * 
44  * - fx and fy are (*n1)*(*n2) matrix of double
45  * - arfact : a factor by which to multiply the default arrow size 
46  *          usr 1.0 by defaut 
47  * - strflag : a string of length 3 (see plot2d) 
48  * - brect=[xmin,ymin,xmax,ymax]    (see plot2d) 
49  *
50  * - lstr : (used when called from Fortran code)
51  -------------------------------------------------------------------*/
52
53 void champg(char *name, integer colored, double *x, double *y, double *fx, double *fy, integer *n1, 
54             integer *n2, char *strflag, double *brect, double *arfact, integer lstr)
55 {
56   static integer aaint[]={2,10,2,10};
57   integer *xm = NULL,*ym = NULL,*zm = NULL,n;
58   double  xx[2],yy[2];
59   integer nn1=1,nn2=2,iflag=0;  
60   /* NG */
61   sciPointObj  *psubwin;
62   integer flag,type =1;
63   double arsize1;
64   integer *style;
65   integer i;
66   double drect[6];
67   BOOL bounds_changed = FALSE;
68   BOOL axes_properties_changed = FALSE;
69   /* champ with color inheritated from subwin */
70   /* or champ1 (normed vector + color) is enabled */
71   int typeofchamp = ( colored == 0 ? 0 : 1 ) ;
72
73   /* get default dash for arrows **/
74   integer verbose=0,narg,xz[10],uc;
75
76   C2F(dr)("xget","use color",&verbose, &uc, &narg,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
77   if (uc)
78     C2F(dr)("xget","color",&verbose,xz,&narg,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
79   else
80     C2F(dr)("xget","line style",&verbose,xz,&narg,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
81   /** The arrowsize acording to the windowsize **/
82   n=2*(*n1)*((*n2)+1); /*F.Leray 17.02.04*/
83   
84   /* get the bounding rect of the displayed champ */
85   getChampDataBounds( x, y, fx, fy, *n1, *n2,typeofchamp,  &(xx[0]), &(xx[1]), &(yy[0]), &(yy[1]) ) ;
86   
87       
88   psubwin = sciGetSelectedSubWin (sciGetCurrentFigure ());
89   checkRedrawing() ;
90
91   /* Force psubwin->is3d to FALSE: we are in 2D mode */
92   if (sciGetSurface(psubwin) == (sciPointObj *) NULL)
93   {
94     pSUBWIN_FEATURE (psubwin)->is3d = FALSE;
95     pSUBWIN_FEATURE (psubwin)->project[2]= 0;
96   } 
97   else
98   {
99     pSUBWIN_FEATURE (psubwin)->theta_kp=pSUBWIN_FEATURE (psubwin)->theta;
100     pSUBWIN_FEATURE (psubwin)->alpha_kp=pSUBWIN_FEATURE (psubwin)->alpha;  
101   }
102
103   pSUBWIN_FEATURE (psubwin)->alpha  = 0.0;
104   pSUBWIN_FEATURE (psubwin)->theta  = 270.0;
105
106   /* Force psubwin->axes.aaint to those given by argument aaint*/
107   /*****TO CHANGE F.Leray 10.09.04      for (i=0;i<4;i++) pSUBWIN_FEATURE(psubwin)->axes.aaint[i] = aaint[i]; */
108
109   /* Force "cligrf" clipping */
110   sciSetIsClipping (psubwin,0); 
111
112
113   if (sciGetGraphicMode (psubwin)->autoscaling)
114   {
115     /* compute and merge new specified bounds with psubwin->Srect */
116     switch (strflag[1])  {
117         case '0': 
118           /* do not change psubwin->Srect */
119           break;
120         case '1' : case '3' : case '5' : case '7':
121           /* Force psubwin->Srect=brect */
122           re_index_brect(brect,drect);
123           break;
124         case '2' : case '4' : case '6' : case '8': case '9':
125           /* Force psubwin->Srect to the x and y bounds */
126           compute_data_bounds2(0,'g',pSUBWIN_FEATURE (psubwin)->logflags,xx,yy,nn1,nn2,drect);
127           break;
128     }
129     if (!pSUBWIN_FEATURE(psubwin)->FirstPlot &&
130       (strflag[1] == '7' || strflag[1] == '8'|| strflag[1] == '9')) { /* merge psubwin->Srect and drect */
131         drect[0] = Min(pSUBWIN_FEATURE(psubwin)->SRect[0],drect[0]); /*xmin*/
132         drect[2] = Min(pSUBWIN_FEATURE(psubwin)->SRect[2],drect[2]); /*ymin*/
133         drect[1] = Max(pSUBWIN_FEATURE(psubwin)->SRect[1],drect[1]); /*xmax*/
134         drect[3] = Max(pSUBWIN_FEATURE(psubwin)->SRect[3],drect[3]); /*ymax*/
135     }
136
137     if (strflag[1] != '0')
138     {
139       bounds_changed = update_specification_bounds(psubwin, drect,2);
140     }
141   }
142
143   if(pSUBWIN_FEATURE (psubwin)->FirstPlot == TRUE) bounds_changed = TRUE;
144
145   axes_properties_changed = strflag2axes_properties(psubwin, strflag);
146
147   pSUBWIN_FEATURE (psubwin)->FirstPlot = FALSE; /* just after strflag2axes_properties */
148
149   if( bounds_changed || axes_properties_changed )
150   {
151     sciDrawObj(sciGetCurrentFigure());
152   }
153
154   flag = 1; /* je le mets √† 1 pour voir F.Leray 19.02.04*/
155   arsize1 = *arfact;
156
157   /* F.Leray Allocation de style[dim = Nbr1] */
158   if ((style = MALLOC ((*n1) * sizeof (integer))) == NULL)
159   {
160     sciprint("No more memory available\n");
161     return;
162   }
163
164   for(i=0;i<(*n1);i++) { style[i] = i ; }
165
166   sciSetCurrentObj(ConstructSegs(psubwin,type,x,y,*n1,*n2,fx,fy,flag,
167     style,arsize1,colored,*arfact,typeofchamp)); 
168
169   sciDrawObjIfRequired( sciGetCurrentObj() ) ; 
170   DrawAxesIfRequired( sciGetCurrentObj() ) ; /* force axes redrawing */
171   /* F.Leray Lib√©ration de style[dim = Nbr1]*/
172   if( style != NULL )
173   {
174     FREE( style ) ;
175     style = NULL;
176   }
177   
178 }
179
180 int C2F(champ)(double *x, double *y, double *fx, double *fy, integer *n1, integer *n2, char *strflag, double *brect, double *arfact, integer lstr)
181 {
182   champg("champ",0,x,y,fx,fy,n1,n2,strflag,brect,arfact,lstr);
183   return(0); 
184 }
185
186 int C2F(champ1)(double *x, double *y, double *fx, double *fy, integer *n1, integer *n2, char *strflag, double *brect, double *arfact, integer lstr)
187 {
188   champg("champ1",1,x,y,fx,fy,n1,n2,strflag,brect,arfact,lstr);
189   return(0);
190 }
191
192
193 /*----------------------------------
194  * Returns min( abs(x)) excluding null x(i)  values 
195  * if x==0 then 1 is returned 
196  *----------------------------------*/
197
198 static double MiniD(double *x, integer n)
199 {
200   int i;
201   double dx=1,mindx=1;
202   if ( n < 2 ) return(mindx);
203   mindx= Abs(x[1]-x[0]);
204   mindx = ( mindx != 0 ) ? mindx : 1;
205   for ( i = 2 ; i < n ; i++) 
206     {
207       dx = Abs(x[i]-x[i-1]);
208       if ( dx < mindx && dx != 0 ) mindx=dx;
209     }
210   return(mindx);
211 }
212
213
214 extern void Champ2DRealToPixel(xm,ym,zm,na,arsize,colored,x,y,fx,fy,n1,n2,arfact)
215
216      integer *xm,*ym,*zm;
217      integer *na,*arsize,*colored;
218      integer *n1,*n2;
219      double *x, *y, *fx, *fy;
220      double *arfact;
221 {  
222  
223   integer i,j;
224   double  maxx;
225   double  nx,ny,sc,sfx,sfy,sfx2,sfy2;
226   double  arsize1=0.5,arsize2=0.5;
227   /* get default dash for arrows **/
228   integer verbose=0,narg;
229   int xfacteur = 1;
230   int yfacteur = 1;
231
232
233   /* From double to pixels */
234   for ( i = 0 ; i < *n1 ; i++)
235     for ( j =0 ; j < *n2 ; j++)
236       {
237         xm[2*(i +(*n1)*j)]= XScale(x[i]);
238         ym[2*(i +(*n1)*j)]= YScale(y[j]);
239       }
240
241   /** Scaling **/
242   nx=MiniD(x,*n1)*Cscale.Wscx1;
243   ny=MiniD(y,*n2)*Cscale.Wscy1;
244   sfx= Cscale.Wscx1;
245   sfy= Cscale.Wscy1;
246   sfx2= sfx*sfx;
247   sfy2= sfy*sfy;
248   maxx = sfx2*fx[0]*fx[0]+sfy2*fy[0]*fy[0];
249   for (i = 1;  i < (*n1)*(*n2) ; i++)
250     {
251       double maxx1 = sfx2*fx[i]*fx[i]+sfy2*fy[i]*fy[i];
252       if ( maxx1 > maxx) maxx=maxx1;
253     }
254   maxx = ( maxx < SMDOUBLE) ? SMDOUBLE : sqrt(maxx);
255   sc=maxx;
256   /*sc= Min(nx,ny)/sc;*/
257   sc= sqrt(nx*nx+ny*ny)/sc;
258   sfx *= sc;
259   sfy *= sc;
260   /** size of arrow **/
261   arsize1= ((double) Cscale.WIRect1[2])/(5*(*n1));
262   arsize2= ((double) Cscale.WIRect1[3])/(5*(*n2));
263   *arsize=  (arsize1 < arsize2) ? inint(arsize1*10.0) : inint(arsize2*10.0) ;
264   *arsize = (int)((*arsize)*(*arfact));
265
266   set_clip_box(Cscale.WIRect1[0],Cscale.WIRect1[0]+Cscale.WIRect1[2],Cscale.WIRect1[1],
267                Cscale.WIRect1[1]+Cscale.WIRect1[3]);
268
269   if ( *colored == 0 ) 
270     {
271       int j2=0;
272       for ( i = 0 ; i < (*n1)*(*n2) ; i++)
273         {
274           integer x1n,y1n,x2n,y2n,flag1=0;
275           /*      xm[1+2*j]= (int)(sfx*fx[i]/2+xm[2*i]); */
276           /*      xm[2*j]  = (int)(-sfx*fx[i]/2+xm[2*i]); */
277           /*      ym[1+2*j]= (int)(-sfy*fy[i]/2+ym[2*i]); */
278           /*      ym[2*j]  = (int)(sfy*fy[i]/2+ym[2*i]); */
279           xm[1+2*j2]= (int)(xfacteur*sfx*fx[i]+xm[2*i]);
280           xm[2*j2]  = (int)(xm[2*i]);
281           ym[1+2*j2]= (int)(-yfacteur*sfy*fy[i]+ym[2*i]);
282           ym[2*j2]  = (int)(ym[2*i]);
283           clip_line(xm[2*j2],ym[2*j2],xm[2*j2+1],ym[2*j2+1],&x1n,&y1n,&x2n,&y2n,&flag1);
284           if (flag1 !=0)
285             {
286               if (flag1==1||flag1==3) { xm[2*j2]=x1n;ym[2*j2]=y1n;};
287               if (flag1==2||flag1==3) { xm[2*j2+1]=x2n;ym[2*j2+1]=y2n;};
288               j2++;
289             }
290         }
291       *na=2*j2;
292     }
293   else 
294     {
295       integer x1n,y1n,x2n,y2n,flag1=0;
296       integer whiteid;
297       int j2=0;
298       C2F(dr)("xget","lastpattern",&verbose,&whiteid,&narg,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
299       for ( i = 0 ; i < (*n1)*(*n2) ; i++)
300         {
301           double nor= sqrt(sfx2*fx[i]*fx[i]+sfy2*fy[i]*fy[i]);
302           zm[j2] = inint( ((double) whiteid - 1)*(1.0 - nor/maxx)) +1;
303           nor= sqrt(fx[i]*(fx[i])+fy[i]*(fy[i]));
304
305           /*        modif bruno (juin 2003) to have the "queue" of the arrow positionned
306            *        at the point (before the arrow was placed such as the corresponding
307            *        point was at the middle of the arrow)       
308            *
309            *        this is the old code :
310            *
311            *      xm[1+2*j]= (int)(sfx*fx[i]/(2*nor)+xm[2*i]); 
312            *      xm[2*j]  = (int)(-sfx*fx[i]/(2*nor)+xm[2*i]); 
313            *      ym[1+2*j]= (int)(-sfy*fy[i]/(2*nor)+ym[2*i]); 
314            *      ym[2*j]  = (int)(sfy*fy[i]/(2*nor)+ym[2*i]); 
315            *
316            *        the new code :
317            */
318           xm[1+2*j2]= (int)(xfacteur*sfx*(fx[i])/(nor)+xm[2*i]);
319           xm[2*j2]  = (int)(xm[2*i]);
320           ym[1+2*j2]= (int)(-yfacteur*sfy*(fy[i])/(nor)+ym[2*i]);
321           ym[2*j2]  = (int)(ym[2*i]);
322           /* end of the modif */
323
324           clip_line(xm[2*j2],ym[2*j2],xm[2*j2+1],ym[2*j2+1],&x1n,&y1n,&x2n,&y2n,&flag1);
325           if (flag1 !=0)
326             {
327               if (flag1==1||flag1==3) { xm[2*j2]=x1n;ym[2*j2]=y1n;};
328               if (flag1==2||flag1==3) { xm[2*j2+1]=x2n;ym[2*j2+1]=y2n;};
329               j2++;
330             }
331         }
332       *na=2*j2;
333     }
334 }
335
336
337
338 /* F.Leray 11.03.05 */
339 /* For new graphic style only */
340 /* same thing has above (Champ2DRealToPixel) */
341 /* only difference is in the typeofchamp treatment (that replaces the colored flag) */
342 void sciChamp2DRealToPixel( integer * xm         ,
343                             integer * ym         ,
344                             integer * zm         ,
345                             integer * na         ,
346                             integer * arsize     ,
347                             double  * x          ,
348                             double  * y          ,
349                             double  * fx         ,
350                             double  * fy         ,
351                             integer * n1         ,
352                             integer * n2         ,
353                             double  * arfact     ,
354                             int     * typeofchamp,
355                             BOOL      clipping    )
356 {  
357
358   integer i,j;
359   double  maxx;
360   double  nx,ny,sc,sfx,sfy,sfx2,sfy2;
361   double  arsize1=0.5,arsize2=0.5;
362   /* get default dash for arrows **/
363   integer verbose=0,narg;
364   int xfacteur = 1;
365   int yfacteur = 1;
366
367   sciPointObj * psubwin = sciGetSelectedSubWin (sciGetCurrentFigure ());
368   sciSubWindow * ppsubwin = pSUBWIN_FEATURE (psubwin);
369
370   if ( ppsubwin->axes.reverse[0] ) { xfacteur = -1 ; }
371   if ( ppsubwin->axes.reverse[1] ) { yfacteur = -1 ; }
372
373   /* From double to pixels */
374   for ( i = 0 ; i < *n1 ; i++)
375   {
376     for ( j =0 ; j < *n2 ; j++)
377     {
378       xm[2*(i +(*n1)*j)]= XScale(x[i]);
379       ym[2*(i +(*n1)*j)]= YScale(y[j]);
380     }
381   }
382
383   /** Scaling **/
384   nx=MiniD(x,*n1)*Cscale.Wscx1;
385   ny=MiniD(y,*n2)*Cscale.Wscy1;
386   sfx= Cscale.Wscx1;
387   sfy= Cscale.Wscy1;
388   sfx2= sfx*sfx;
389   sfy2= sfy*sfy;
390   maxx = sfx2*fx[0]*fx[0]+sfy2*fy[0]*fy[0];
391   for (i = 1;  i < (*n1)*(*n2) ; i++)
392   {
393     double maxx1 = sfx2*fx[i]*fx[i]+sfy2*fy[i]*fy[i];
394     if ( maxx1 > maxx) maxx=maxx1;
395   }
396   maxx = ( maxx < SMDOUBLE) ? SMDOUBLE : sqrt(maxx);
397   sc=maxx;
398   /*sc= Min(nx,ny)/sc;*/
399   sc= sqrt(nx*nx+ny*ny)/sc;
400   sfx *= sc;
401   sfy *= sc;
402   /** size of arrow **/
403   arsize1= ((double) Cscale.WIRect1[2])/(5*(*n1));
404   arsize2= ((double) Cscale.WIRect1[3])/(5*(*n2));
405   *arsize=  (arsize1 < arsize2) ? inint(arsize1*10.0) : inint(arsize2*10.0) ;
406   *arsize = (int)((*arsize)*(*arfact));
407
408   set_clip_box(Cscale.WIRect1[0],Cscale.WIRect1[0]+Cscale.WIRect1[2],Cscale.WIRect1[1],
409     Cscale.WIRect1[1]+Cscale.WIRect1[3]);
410
411   if ( *typeofchamp == 0 ) 
412   {
413     int j2=0;
414     for ( i = 0 ; i < (*n1)*(*n2) ; i++)
415     {
416       integer x1n,y1n,x2n,y2n,flag1=0;
417       xm[1+2*j2]= (int)(xfacteur*sfx*fx[i]+xm[2*i]);
418       xm[2*j2]  = (int)(xm[2*i]);
419       ym[1+2*j2]= (int)(-yfacteur*sfy*fy[i]+ym[2*i]);
420       ym[2*j2]  = (int)(ym[2*i]);
421       clip_line(xm[2*j2],ym[2*j2],xm[2*j2+1],ym[2*j2+1],&x1n,&y1n,&x2n,&y2n,&flag1);
422       if ( flag1 != 0 )
423       {
424         if (flag1==1||flag1==3)
425         {
426           xm[2*j2] = x1n ;
427           ym[2*j2] = y1n ;
428         }
429         if (flag1==2||flag1==3)
430         {
431           xm[2*j2+1] = x2n ;
432           ym[2*j2+1] = y2n ;
433         }
434         j2++;
435       }
436       else if ( !clipping )
437       {
438         j2++ ;
439       }
440     }
441     *na=2*j2;
442   }
443   else 
444   {
445     integer x1n,y1n,x2n,y2n,flag1=0;
446     integer whiteid;
447     int j2=0;
448     C2F(dr)("xget","lastpattern",&verbose,&whiteid,&narg,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
449     for ( i = 0 ; i < (*n1)*(*n2) ; i++)
450     {
451       double nor= sqrt(sfx2*fx[i]*fx[i]+sfy2*fy[i]*fy[i]);
452       zm[j2] = inint( ((double) whiteid -1 )*(1.0 - nor/maxx)) +1;
453       nor= sqrt(fx[i]*(fx[i])+fy[i]*(fy[i]));
454
455       /*        modif bruno (juin 2003) to have the "queue" of the arrow positionned
456       *        at the point (before the arrow was placed such as the corresponding
457       *        point was at the middle of the arrow)       
458       *
459       *        this is the old code :
460       *
461       *           xm[1+2*j2]= (int)(sfx*fx[i]/(2*nor)+xm[2*i]); 
462       *           xm[2*j2]  = (int)(-sfx*fx[i]/(2*nor)+xm[2*i]); 
463       *           ym[1+2*j2]= (int)(-sfy*fy[i]/(2*nor)+ym[2*i]); 
464       *           ym[2*j2]  = (int)(sfy*fy[i]/(2*nor)+ym[2*i]); 
465       *
466       *        the new code :
467       */
468       xm[1+2*j2]= (int)(xfacteur*sfx*(fx[i])/(nor)+xm[2*i]);
469       xm[2*j2]  = (int)(xm[2*i]);
470       ym[1+2*j2]= (int)(-yfacteur*sfy*(fy[i])/(nor)+ym[2*i]);
471       ym[2*j2]  = (int)(ym[2*i]);
472       /* end of the modif */
473
474       clip_line(xm[2*j2],ym[2*j2],xm[2*j2+1],ym[2*j2+1],&x1n,&y1n,&x2n,&y2n,&flag1);
475       if ( flag1 != 0 )
476       {
477         if (flag1==1||flag1==3)
478         {
479           xm[2*j2] = x1n ;
480           ym[2*j2] = y1n ;
481         }
482         if (flag1==2||flag1==3)
483         {
484           xm[2*j2+1] = x2n ;
485           ym[2*j2+1] = y2n ;
486         }
487         j2++;
488       }
489       else if ( !clipping )
490       {
491         j2++ ;
492       }
493     }
494     *na=2*j2;
495   }
496 }
497
498 /*-------------------------------------------------------------------------------------------*/
499 /**
500 * Compute the size of the area used by a champ object( ie scisegs with ptype = 1).
501 * @param[in]  xCoords     position of the champ grid
502 * @param[in]  yCoords     position of the champ grid
503 * @param[in]  xLength     size of the arrow
504 * @param[in]  yLength     size of the arrow
505 * @param      nbRow       number of row in the champ grid
506 * @param      nbCol       number of column in the champ grid.
507 * @param      typeOfChamp 0 for champ and 1 for champ1
508 * @param[out] xMin        bounding rect of the champ object
509 * @param[out] xMax        bounding rect of the champ object
510 * @param[out] yMin        bounding rect of the champ object
511 * @param[out] yMax        bounding rect of the champ object
512 */
513 void getChampDataBounds( double   xCoords[]  ,
514                         double   yCoords[]  ,
515                         double   xLength[]  ,
516                         double   yLength[]  ,
517                         int      nbRow      ,
518                         int      nbCol      ,
519                         int      typeOfChamp,
520                         double * xMin       ,
521                         double * xMax       ,
522                         double * yMin       ,
523                         double * yMax        )
524 {
525   int      i                                ;
526   int    * xPixCoords   = NULL              ;
527   int    * yPixCoords   = NULL              ;
528   int    * zPixCoords   = NULL              ;
529   int      nbArrowEnds  = 2 * nbRow * nbCol ; /* 2 time the number of arrows */
530   int      nbArrows                         ;
531   int      arrowSize     = 0                ; /* arrow size does not modify bounds for now */
532   double   arrowSizeFact = 0.0              ;
533
534
535   if ( nbArrowEnds == 0 )
536   {
537     *xMin = 0.0 ;
538     *xMax = 0.0 ;
539     *yMin = 0.0 ;
540     *yMax = 0.0 ;
541     return ;
542   }
543
544   xPixCoords = MALLOC( nbArrowEnds   * sizeof(int) ) ;
545   yPixCoords = MALLOC( nbArrowEnds   * sizeof(int) ) ;
546   zPixCoords = MALLOC( nbRow * nbCol * sizeof(int) ) ;
547
548   if ( xPixCoords == NULL || yPixCoords == NULL || zPixCoords == NULL )
549   {
550     FREE( xPixCoords ) ;
551     FREE( yPixCoords ) ;
552     FREE( zPixCoords ) ;
553     sciprint( "Cannot allocate temporary vector, memory full.\n" ) ;
554     *xMin = 0.0 ;
555     *xMax = 0.0 ;
556     *yMin = 0.0 ;
557     *yMax = 0.0 ;
558     return ;
559   }
560
561   /* get the bounds in pixels */
562   sciChamp2DRealToPixel( xPixCoords    ,
563     yPixCoords    ,
564     zPixCoords    ,
565     &nbArrows     ,
566     &arrowSize    ,
567     xCoords       ,
568     yCoords       ,
569     xLength       ,
570     yLength       ,
571     &nbRow        ,
572     &nbCol        ,
573     &arrowSizeFact,
574     &typeOfChamp  ,
575     FALSE          ) ;
576
577
578
579   /* get extrema on X and Y */
580   *xMin = XPixel2Double( xPixCoords[0] ) ;
581   *xMax = *xMin ;
582
583   *yMin = YPixel2Double( yPixCoords[0] ) ;
584   *yMax = *yMin ;
585
586   for ( i = 1 ; i < nbArrows ; i++ )
587   {
588     double currentCoordX = XPixel2Double( xPixCoords[i] ) ;
589     double currentCoordY = YPixel2Double( yPixCoords[i] ) ;
590
591     *xMin = Min( *xMin, currentCoordX ) ;
592     *xMax = Max( *xMax, currentCoordX ) ;
593
594     *yMin = Min( *yMin, currentCoordY ) ;
595     *yMax = Max( *yMax, currentCoordY ) ;
596   }
597
598   FREE( xPixCoords ) ;
599   FREE( yPixCoords ) ;
600   FREE( zPixCoords ) ;
601
602 }
603 /*-------------------------------------------------------------------------------------------*/
604
605
606
607