Champ.c

Go to the documentation of this file.
00001 /*------------------------------------------------------------------------
00002  *    Graphic library
00003  *    Copyright (C) 1998-2001 Enpc/Jean-Philippe Chancelier
00004  *    jpc@cermics.enpc.fr 
00005  --------------------------------------------------------------------------*/
00006 
00007 #include <math.h>
00008 #include <stdio.h>
00009 #include <string.h>
00010 #include "math_graphics.h"
00011 #include "PloEch.h"
00012 
00013 #include "GetProperty.h"
00014 #include "SetProperty.h"
00015 #include "DrawObjects.h"
00016 #include "BuildObjects.h"
00017 #include "Axes.h"
00018 #include "Xcall1.h"
00019 #include "Champ.h"
00020 #include "sciprint.h"
00021 #include "periScreen.h"
00022 #include "CurrentObjectsManagement.h"
00023 
00024 
00025 #include "MALLOC.h" /* MALLOC */
00026 
00027 static double MiniD __PARAMS((double *x,integer n));
00028 extern void initsubwin();
00029 /* extern void compute_data_bounds(int cflag,char dataflag,double *x,double *y,int n1,int n2,double *drect); */
00030 extern void compute_data_bounds2(int cflag,char dataflag,char *logflags,double *x,double *y,int n1,int n2,double *drect);
00031 extern BOOL update_specification_bounds(sciPointObj *psubwin, double *rect,int flag);
00032 extern int re_index_brect(double * brect, double * drect);
00033 extern BOOL strflag2axes_properties(sciPointObj * psubwin, char * strflag);
00034 
00035 /*-----------------------------------------------------------------
00036  *  int C2F(champ)(x,y,fx,fy,n1,n2,strflag,brect,arfact,lstr)
00037  *  int C2F(champ1)(x,y,fx,fy,n1,n2,strflag,brect,arfact,lstr)
00038  *
00039  * Used for Drawing 2 dimensional vector fields 
00040  * (fx[i+(*n1)*j], fy[i+(*n1)*j]) is the value of the vector field 
00041  * at point X=(x[i],y[j]);
00042  * 
00043  * - fx and fy are (*n1)*(*n2) matrix of double
00044  * - arfact : a factor by which to multiply the default arrow size 
00045  *          usr 1.0 by defaut 
00046  * - strflag : a string of length 3 (see plot2d) 
00047  * - brect=[xmin,ymin,xmax,ymax]    (see plot2d) 
00048  *
00049  * - lstr : (used when called from Fortran code)
00050  -------------------------------------------------------------------*/
00051 
00052 void champg(char *name, integer colored, double *x, double *y, double *fx, double *fy, integer *n1, 
00053             integer *n2, char *strflag, double *brect, double *arfact, integer lstr)
00054 {
00055   integer n;
00056   double  xx[2],yy[2];
00057   integer nn1=1,nn2=2;  
00058   /* NG */
00059   sciPointObj  *psubwin;
00060   integer flag,type =1;
00061   double arsize1;
00062   integer *style;
00063   integer i;
00064   double drect[6];
00065   BOOL bounds_changed = FALSE;
00066   BOOL axes_properties_changed = FALSE;
00067   /* champ with color inheritated from subwin */
00068   /* or champ1 (normed vector + color) is enabled */
00069   int typeofchamp = ( colored == 0 ? 0 : 1 ) ;
00070 
00071   /* get default dash for arrows **/
00072   integer verbose=0,narg,xz[10],uc;
00073 
00074   C2F(dr)("xget","use color",&verbose, &uc, &narg,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
00075   if (uc)
00076     C2F(dr)("xget","color",&verbose,xz,&narg,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
00077   else
00078     C2F(dr)("xget","line style",&verbose,xz,&narg,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
00080   n=2*(*n1)*((*n2)+1); /*F.Leray 17.02.04*/
00081   
00082   /* get the bounding rect of the displayed champ */
00083   getChampDataBounds( x, y, fx, fy, *n1, *n2,typeofchamp,  &(xx[0]), &(xx[1]), &(yy[0]), &(yy[1]) ) ;
00084   
00085       
00086   psubwin = sciGetCurrentSubWin() ;
00087   checkRedrawing() ;
00088 
00089   /* Force psubwin->is3d to FALSE: we are in 2D mode */
00090   if (sciGetSurface(psubwin) == (sciPointObj *) NULL)
00091   {
00092     pSUBWIN_FEATURE (psubwin)->is3d = FALSE;
00093     pSUBWIN_FEATURE (psubwin)->project[2]= 0;
00094   } 
00095   else
00096   {
00097     pSUBWIN_FEATURE (psubwin)->theta_kp=pSUBWIN_FEATURE (psubwin)->theta;
00098     pSUBWIN_FEATURE (psubwin)->alpha_kp=pSUBWIN_FEATURE (psubwin)->alpha;  
00099   }
00100 
00101   pSUBWIN_FEATURE (psubwin)->alpha  = 0.0;
00102   pSUBWIN_FEATURE (psubwin)->theta  = 270.0;
00103 
00104   /* Force psubwin->axes.aaint to those given by argument aaint*/
00105   /*****TO CHANGE F.Leray 10.09.04      for (i=0;i<4;i++) pSUBWIN_FEATURE(psubwin)->axes.aaint[i] = aaint[i]; */
00106 
00107   /* Force "cligrf" clipping */
00108   sciSetIsClipping (psubwin,0); 
00109 
00110 
00111   if (sciGetGraphicMode (psubwin)->autoscaling)
00112   {
00113     /* compute and merge new specified bounds with psubwin->Srect */
00114     switch (strflag[1])  {
00115         case '0': 
00116           /* do not change psubwin->Srect */
00117           break;
00118         case '1' : case '3' : case '5' : case '7':
00119           /* Force psubwin->Srect=brect */
00120           re_index_brect(brect,drect);
00121           break;
00122         case '2' : case '4' : case '6' : case '8': case '9':
00123           /* Force psubwin->Srect to the x and y bounds */
00124           compute_data_bounds2(0,'g',pSUBWIN_FEATURE (psubwin)->logflags,xx,yy,nn1,nn2,drect);
00125           break;
00126     }
00127     if (!pSUBWIN_FEATURE(psubwin)->FirstPlot &&
00128       (strflag[1] == '7' || strflag[1] == '8'|| strflag[1] == '9')) { /* merge psubwin->Srect and drect */
00129         drect[0] = Min(pSUBWIN_FEATURE(psubwin)->SRect[0],drect[0]); /*xmin*/
00130         drect[2] = Min(pSUBWIN_FEATURE(psubwin)->SRect[2],drect[2]); /*ymin*/
00131         drect[1] = Max(pSUBWIN_FEATURE(psubwin)->SRect[1],drect[1]); /*xmax*/
00132         drect[3] = Max(pSUBWIN_FEATURE(psubwin)->SRect[3],drect[3]); /*ymax*/
00133     }
00134 
00135     if (strflag[1] != '0')
00136     {
00137       bounds_changed = update_specification_bounds(psubwin, drect,2);
00138     }
00139   }
00140 
00141   if(pSUBWIN_FEATURE (psubwin)->FirstPlot == TRUE) bounds_changed = TRUE;
00142 
00143   axes_properties_changed = strflag2axes_properties(psubwin, strflag);
00144 
00145   pSUBWIN_FEATURE (psubwin)->FirstPlot = FALSE; /* just after strflag2axes_properties */
00146 
00147   if( bounds_changed || axes_properties_changed )
00148   {
00149     sciDrawObj(sciGetCurrentFigure());
00150   }
00151 
00152   flag = 1; /* je le mets à 1 pour voir F.Leray 19.02.04*/
00153   arsize1 = *arfact;
00154 
00155   /* F.Leray Allocation de style[dim = Nbr1] */
00156   if ((style = MALLOC ((*n1) * sizeof (integer))) == NULL)
00157   {
00158     sciprint("No more memory available\n");
00159     return;
00160   }
00161 
00162   for(i=0;i<(*n1);i++) { style[i] = i ; }
00163 
00164   sciSetCurrentObj(ConstructSegs(psubwin,type,x,y,*n1,*n2,fx,fy,flag,
00165     style,arsize1,colored,*arfact,typeofchamp)); 
00166 
00167   sciDrawObjIfRequired( sciGetCurrentObj() ) ; 
00168   DrawAxesIfRequired( sciGetCurrentObj() ) ; /* force axes redrawing */
00169   /* F.Leray Libération de style[dim = Nbr1]*/
00170   if( style != NULL )
00171   {
00172     FREE( style ) ;
00173     style = NULL;
00174   }
00175   
00176 }
00177 
00178 int C2F(champ)(double *x, double *y, double *fx, double *fy, integer *n1, integer *n2, char *strflag, double *brect, double *arfact, integer lstr)
00179 {
00180   champg("champ",0,x,y,fx,fy,n1,n2,strflag,brect,arfact,lstr);
00181   return(0); 
00182 }
00183 
00184 int C2F(champ1)(double *x, double *y, double *fx, double *fy, integer *n1, integer *n2, char *strflag, double *brect, double *arfact, integer lstr)
00185 {
00186   champg("champ1",1,x,y,fx,fy,n1,n2,strflag,brect,arfact,lstr);
00187   return(0);
00188 }
00189 
00190 
00191 /*----------------------------------
00192  * Returns min( abs(x)) excluding null x(i)  values 
00193  * if x==0 then 1 is returned 
00194  *----------------------------------*/
00195 
00196 static double MiniD(double *x, integer n)
00197 {
00198   int i;
00199   double dx=1,mindx=1;
00200   if ( n < 2 ) return(mindx);
00201   mindx= Abs(x[1]-x[0]);
00202   mindx = ( mindx != 0 ) ? mindx : 1;
00203   for ( i = 2 ; i < n ; i++) 
00204     {
00205       dx = Abs(x[i]-x[i-1]);
00206       if ( dx < mindx && dx != 0 ) mindx=dx;
00207     }
00208   return(mindx);
00209 }
00210 
00211 
00212 /* F.Leray 11.03.05 */
00213 /* For new graphic style only */
00214 /* same thing has above (Champ2DRealToPixel) */
00215 /* only difference is in the typeofchamp treatment (that replaces the colored flag) */
00216 void sciChamp2DRealToPixel( integer * xm         ,
00217                             integer * ym         ,
00218                             integer * zm         ,
00219                             integer * na         ,
00220                             integer * arsize     ,
00221                             double  * x          ,
00222                             double  * y          ,
00223                             double  * fx         ,
00224                             double  * fy         ,
00225                             integer * n1         ,
00226                             integer * n2         ,
00227                             double  * arfact     ,
00228                             int     * typeofchamp,
00229                             BOOL      clipping    )
00230 {  
00231 
00232   integer i,j;
00233   double  maxx;
00234   double  nx,ny,sc,sfx,sfy,sfx2,sfy2;
00235   double  arsize1=0.5,arsize2=0.5;
00236   /* get default dash for arrows **/
00237   integer verbose=0,narg;
00238   int xfacteur = 1;
00239   int yfacteur = 1;
00240 
00241   sciPointObj * psubwin = sciGetCurrentSubWin();
00242   sciSubWindow * ppsubwin = pSUBWIN_FEATURE (psubwin);
00243 
00244   if ( ppsubwin->axes.reverse[0] ) { xfacteur = -1 ; }
00245   if ( ppsubwin->axes.reverse[1] ) { yfacteur = -1 ; }
00246 
00247   /* From double to pixels */
00248   for ( i = 0 ; i < *n1 ; i++)
00249   {
00250     for ( j =0 ; j < *n2 ; j++)
00251     {
00252       xm[2*(i +(*n1)*j)]= XScale(x[i]);
00253       ym[2*(i +(*n1)*j)]= YScale(y[j]);
00254     }
00255   }
00256 
00258   nx=MiniD(x,*n1)*Cscale.Wscx1;
00259   ny=MiniD(y,*n2)*Cscale.Wscy1;
00260   sfx= Cscale.Wscx1;
00261   sfy= Cscale.Wscy1;
00262   sfx2= sfx*sfx;
00263   sfy2= sfy*sfy;
00264   maxx = getLongestVector( fx, fy, *n1, *n2, sfx, sfy ) ;
00265   sc=maxx;
00266   sc= sqrt(nx*nx+ny*ny)/sc;
00267   sfx *= sc;
00268   sfy *= sc;
00270   arsize1= ((double) Cscale.WIRect1[2])/(5*(*n1));
00271   arsize2= ((double) Cscale.WIRect1[3])/(5*(*n2));
00272   *arsize=  (arsize1 < arsize2) ? inint(arsize1*10.0) : inint(arsize2*10.0) ;
00273   *arsize = (int)((*arsize)*(*arfact));
00274 
00275   set_clip_box(Cscale.WIRect1[0],Cscale.WIRect1[0]+Cscale.WIRect1[2],Cscale.WIRect1[1],
00276     Cscale.WIRect1[1]+Cscale.WIRect1[3]);
00277 
00278   if ( *typeofchamp == 0 ) 
00279   {
00280     int j2=0;
00281     for ( i = 0 ; i < (*n1)*(*n2) ; i++)
00282     {
00283       integer x1n,y1n,x2n,y2n,flag1=0;
00284       xm[1+2*j2]= (int)(xfacteur*sfx*fx[i]+xm[2*i]);
00285       xm[2*j2]  = (int)(xm[2*i]);
00286       ym[1+2*j2]= (int)(-yfacteur*sfy*fy[i]+ym[2*i]);
00287       ym[2*j2]  = (int)(ym[2*i]);
00288       clip_line(xm[2*j2],ym[2*j2],xm[2*j2+1],ym[2*j2+1],&x1n,&y1n,&x2n,&y2n,&flag1);
00289       if ( flag1 != 0 )
00290       {
00291         if (flag1==1||flag1==3)
00292         {
00293           xm[2*j2] = x1n ;
00294           ym[2*j2] = y1n ;
00295         }
00296         if (flag1==2||flag1==3)
00297         {
00298           xm[2*j2+1] = x2n ;
00299           ym[2*j2+1] = y2n ;
00300         }
00301         j2++;
00302       }
00303       else if ( !clipping )
00304       {
00305         j2++ ;
00306       }
00307     }
00308     *na=2*j2;
00309   }
00310   else 
00311   {
00312     integer x1n,y1n,x2n,y2n,flag1=0;
00313     integer whiteid;
00314     int j2=0;
00315     C2F(dr)("xget","lastpattern",&verbose,&whiteid,&narg,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
00316     for ( i = 0 ; i < (*n1)*(*n2) ; i++)
00317     {
00318       double nor= sqrt(sfx2*fx[i]*fx[i]+sfy2*fy[i]*fy[i]);
00319       zm[j2] = inint( ((double) whiteid -1 )*(1.0 - nor/maxx)) +1;
00320       nor= sqrt(fx[i]*(fx[i])+fy[i]*(fy[i]));
00321 
00322       /*        modif bruno (juin 2003) to have the "queue" of the arrow positionned
00323       *        at the point (before the arrow was placed such as the corresponding
00324       *        point was at the middle of the arrow)       
00325       *
00326       *        this is the old code :
00327       *
00328       *           xm[1+2*j2]= (int)(sfx*fx[i]/(2*nor)+xm[2*i]); 
00329       *           xm[2*j2]  = (int)(-sfx*fx[i]/(2*nor)+xm[2*i]); 
00330       *           ym[1+2*j2]= (int)(-sfy*fy[i]/(2*nor)+ym[2*i]); 
00331       *           ym[2*j2]  = (int)(sfy*fy[i]/(2*nor)+ym[2*i]); 
00332       *
00333       *        the new code :
00334       */
00335       xm[1+2*j2]= (int)(xfacteur*sfx*(fx[i])/(nor)+xm[2*i]);
00336       xm[2*j2]  = (int)(xm[2*i]);
00337       ym[1+2*j2]= (int)(-yfacteur*sfy*(fy[i])/(nor)+ym[2*i]);
00338       ym[2*j2]  = (int)(ym[2*i]);
00339       /* end of the modif */
00340 
00341       clip_line(xm[2*j2],ym[2*j2],xm[2*j2+1],ym[2*j2+1],&x1n,&y1n,&x2n,&y2n,&flag1);
00342       if ( flag1 != 0 )
00343       {
00344         if (flag1==1||flag1==3)
00345         {
00346           xm[2*j2] = x1n ;
00347           ym[2*j2] = y1n ;
00348         }
00349         if (flag1==2||flag1==3)
00350         {
00351           xm[2*j2+1] = x2n ;
00352           ym[2*j2+1] = y2n ;
00353         }
00354         j2++;
00355       }
00356       else if ( !clipping )
00357       {
00358         j2++ ;
00359       }
00360     }
00361     *na=2*j2;
00362   }
00363 }
00364 
00365 /*-------------------------------------------------------------------------------------------*/
00380 void getChampDataBounds( double   xCoords[]  ,
00381                         double   yCoords[]  ,
00382                         double   xLength[]  ,
00383                         double   yLength[]  ,
00384                         int      nbRow      ,
00385                         int      nbCol      ,
00386                         int      typeOfChamp,
00387                         double * xMin       ,
00388                         double * xMax       ,
00389                         double * yMin       ,
00390                         double * yMax        )
00391 {
00392   int      i                                ;
00393   int    * xPixCoords   = NULL              ;
00394   int    * yPixCoords   = NULL              ;
00395   int    * zPixCoords   = NULL              ;
00396   int      nbArrowEnds  = 2 * nbRow * nbCol ; /* 2 time the number of arrows */
00397   int      nbArrows                         ;
00398   int      arrowSize     = 0                ; /* arrow size does not modify bounds for now */
00399   double   arrowSizeFact = 0.0              ;
00400 
00401 
00402   if ( nbArrowEnds == 0 )
00403   {
00404     *xMin = 0.0 ;
00405     *xMax = 0.0 ;
00406     *yMin = 0.0 ;
00407     *yMax = 0.0 ;
00408     return ;
00409   }
00410 
00411   xPixCoords = MALLOC( nbArrowEnds   * sizeof(int) ) ;
00412   yPixCoords = MALLOC( nbArrowEnds   * sizeof(int) ) ;
00413   zPixCoords = MALLOC( nbRow * nbCol * sizeof(int) ) ;
00414 
00415   if ( xPixCoords == NULL || yPixCoords == NULL || zPixCoords == NULL )
00416   {
00417     FREE( xPixCoords ) ;
00418     FREE( yPixCoords ) ;
00419     FREE( zPixCoords ) ;
00420     sciprint( "Cannot allocate temporary vector, memory full.\n" ) ;
00421     *xMin = 0.0 ;
00422     *xMax = 0.0 ;
00423     *yMin = 0.0 ;
00424     *yMax = 0.0 ;
00425     return ;
00426   }
00427 
00428   /* get the bounds in pixels */
00429   sciChamp2DRealToPixel( xPixCoords    ,
00430     yPixCoords    ,
00431     zPixCoords    ,
00432     &nbArrows     ,
00433     &arrowSize    ,
00434     xCoords       ,
00435     yCoords       ,
00436     xLength       ,
00437     yLength       ,
00438     &nbRow        ,
00439     &nbCol        ,
00440     &arrowSizeFact,
00441     &typeOfChamp  ,
00442     FALSE          ) ;
00443 
00444 
00445 
00446   /* get extrema on X and Y */
00447   *xMin = XPixel2Double( xPixCoords[0] ) ;
00448   *xMax = *xMin ;
00449 
00450   *yMin = YPixel2Double( yPixCoords[0] ) ;
00451   *yMax = *yMin ;
00452 
00453   for ( i = 1 ; i < nbArrows ; i++ )
00454   {
00455     double currentCoordX = XPixel2Double( xPixCoords[i] ) ;
00456     double currentCoordY = YPixel2Double( yPixCoords[i] ) ;
00457 
00458     *xMin = Min( *xMin, currentCoordX ) ;
00459     *xMax = Max( *xMax, currentCoordX ) ;
00460 
00461     *yMin = Min( *yMin, currentCoordY ) ;
00462     *yMax = Max( *yMax, currentCoordY ) ;
00463   }
00464 
00465   FREE( xPixCoords ) ;
00466   FREE( yPixCoords ) ;
00467   FREE( zPixCoords ) ;
00468 
00469 }
00470 /*-------------------------------------------------------------------------------------------*/
00471 double computeGridMinGap( double gridX[], double gridY[], int nbRow, int nbCol )
00472 {
00473   int i ;
00474   double min = 0 ;
00475   double minX = Abs( gridX[1] - gridX[0] ) ;
00476   double minY = Abs( gridY[1] - gridY[0] ) ;
00477 
00478   for ( i = 1 ; i < nbRow-1 ; i++ )
00479   {
00480     double tmp = Abs( gridX[i+1] - gridX[i] ) ;
00481     if ( tmp < minX )
00482     {
00483       minX = tmp ;
00484     }
00485   }
00486 
00487   for ( i = 1 ; i < nbCol-1 ; i++ )
00488   {
00489     double tmp = Abs( gridY[i+1] - gridY[i] ) ;
00490     if ( tmp < minY )
00491     {
00492       minY = tmp ;
00493     }
00494   }
00495 
00496 
00497   min = minX * minX + minY * minY ;
00498   min = ( min < SMDOUBLE) ? SMDOUBLE : sqrt(min) ;
00499 
00500   return min ;
00501 }
00502 /*-------------------------------------------------------------------------------------------*/
00503 int computeArrowColor( double gridX[], double gridY[], int nbRow, int nbCol, int index )
00504 {
00505   integer whiteid;
00506   int verbose = 0 ;
00507   int narg = 0 ;
00508   int j2=0 ;
00509   int color = 0 ;
00510   double scx = Cscale.Wscx1 ;
00511   double scy = Cscale.Wscy1 ;
00512 
00513   double nor = sqrt( scx*scx*gridX[index]*gridX[index] + scy*scy*gridY[index]*gridY[index] ) ;
00514   double max = getLongestVector( gridX, gridY, nbRow, nbCol, scx, scy ) ;
00515   
00516   C2F(dr)("xget","lastpattern",&verbose,&whiteid,&narg,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
00517   
00518   
00519   color = inint( (whiteid-1) * (1.0-nor/max) ) + 1 ;
00520 
00521   return color ;
00522 }
00523 /*-------------------------------------------------------------------------------------------*/
00524 double getLongestVector( double vectX[], double vectY[], int nbRow, int nbCol, double scx, double scy )
00525 {
00526   int i ;
00527 
00528   double scx2 = scx * scx ;
00529   double scy2 = scy * scy ;
00530   double max  = ( scx2 * vectX[0] * vectX[0] ) + ( scy2 * vectY[0] * vectY[0] ) ;
00531 
00532   for ( i = 1 ; i < nbRow * nbCol ; i++ )
00533   {
00534     double tmp = ( scx2 * vectX[i] * vectX[i] ) + ( scy2 * vectY[i] * vectY[i] ) ;
00535     if ( tmp > max ) { max = tmp ; }
00536   }
00537   max = ( max < SMDOUBLE) ? SMDOUBLE : sqrt(max) ;
00538 
00539   return max ;
00540 }
00541 /*-------------------------------------------------------------------------------------------*/

Generated on Sun Mar 4 15:03:50 2007 for Scilab [trunk] by  doxygen 1.5.1