00001
00002
00003
00004
00005
00006
00007 #include <string.h>
00008 #include <stdio.h>
00009 #include <math.h>
00010 #include "math_graphics.h"
00011 #include "PloEch.h"
00012 #include "Xcall1.h"
00013 #include "sciprint.h"
00014 #include "MALLOC.h"
00015 #include "Format.h"
00016 #include "Contour.h"
00017
00018 #include "GetProperty.h"
00019
00020 typedef void (level_f) __PARAMS((integer ival, double Cont, double xncont,
00021 double yncont));
00022 typedef void (*ptr_level_f) __PARAMS((integer ival, double Cont, double xncont,
00023 double yncont));
00024
00025
00026 static void
00027 contourI __PARAMS((ptr_level_f,double *, double *, double *,
00028 double *, integer *, integer *, integer *));
00029 static void
00030 look __PARAMS((ptr_level_f, integer i, integer j, integer ib,
00031 integer jb, integer qq,double Cont, integer style));
00032
00033 static integer ffnd __PARAMS((ptr_level_f,integer,integer,integer,integer,integer,
00034 integer,integer,integer,integer,integer,
00035 double,integer *));
00036
00037 static int Gcont_size = 0;
00038
00039 static void ContourTrace __PARAMS((double Cont, integer style));
00040 static level_f GContStore2;
00041 static void GContStore2Last __PARAMS((void));
00042 static double x_cont __PARAMS((integer i));
00043 static double y_cont __PARAMS((integer i));
00044 static double phi_cont __PARAMS((integer, integer));
00045 static double f_intercept __PARAMS((double, double, double, double, double ));
00046 static integer not_same_sign __PARAMS((double val1, double val2));
00047 static integer get_itg_cont __PARAMS((integer i, integer j));
00048 static void inc_itg_cont __PARAMS((integer i, integer j, integer val));
00049 static integer oddp __PARAMS((integer i));
00050
00051
00052
00053
00054
00055
00056
00057 #define HIDDENFRAMECOLOR 2L
00058
00059
00060
00061
00062
00063
00064 static double *GX,*GY,*GZ;
00065 static integer Gn1,Gn2;
00066
00067 static double * Gxcont = NULL ;
00068 static double * Gycont = NULL ;
00069
00070 static integer * xcont = NULL ;
00071 static integer * ycont = NULL ;
00072
00073 static void InitValues(double *x, double *y, double *z, integer n1, integer n2)
00074 {
00075 Gn1=n1; Gn2=n2; GX = x; GY = y; GZ = z;
00076 }
00077
00078
00079
00080 static double phi_cont(integer i, integer j)
00081 {
00082 return(GZ[i+Gn1*j]);
00083 }
00084
00085
00086
00087
00088 static double f_intercept(double zCont, double fi, double xi, double fj, double xj)
00089 {
00090 return( xi+ (zCont-fi)*(xj-xi)/ (fj-fi));
00091 }
00092
00093
00094
00095 static integer bdyp(integer i, integer j)
00096 {
00097 return ( j == 0 || i == 0 || j == Gn2-1 || i == Gn1-1 );
00098 }
00099
00100
00101
00102 static integer *itg_cont, *xbd_cont,*ybd_cont;
00103
00104 static integer get_itg_cont(integer i, integer j)
00105 {
00106 return( itg_cont[i+Gn1*j]);
00107 }
00108
00109 static void inc_itg_cont(integer i, integer j, integer val)
00110 {
00111 itg_cont[i+Gn1*j] += val;
00112 }
00113
00114 static integer not_same_sign(double val1, double val2)
00115 {
00116 if ( ISNAN(val1) ==1 || ISNAN(val2) == 1) return(0);
00118 if ( val1 >= 0.0)
00119 {
00120 if (val2 < 0.0) return(1) ; else return(0);}
00121 else
00122 {
00123 if ( val2 >= 0.0) return(1) ; else return(0);}
00124 }
00125
00126 static integer oddp(integer i) { return( i == 1 || i ==3 );}
00127
00128
00129
00130 static double x_cont(integer i) { return GX[i] ;}
00131
00132
00133
00134 static double y_cont(integer i) { return GY[i] ;}
00135
00136
00137 static char ContNumFormat[100];
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147 static void look(ptr_level_f func, integer i, integer j, integer ib, integer jb, integer qq, double Cont, integer style)
00148 {
00149 integer ip,jp,im,jm,zds,ent=0,flag=0,wflag;
00150 jp= j+1; ip= i+1; jm=j-1;im=i-1;
00151
00152 if ( jb == jm) flag = 1;
00153 else {
00154 if ( ib == im ) flag = 2 ;
00155 else {
00156 if ( jb == jp ) flag = 3 ;
00157 else if ( ib == ip ) flag = 4;}}
00158 switch ( flag)
00159 {
00160 case 1 :
00161 if (get_itg_cont(i,jm) > 1) return;
00162 ent=1 ;
00163
00164 (*func)(0,Cont, x_cont(i),
00165 f_intercept(Cont,phi_cont(i,jm),
00166 y_cont(jm),phi_cont(i,j),y_cont(j)));
00167 break;
00168 case 2 :
00169 if (get_itg_cont(im,j) == 1 || get_itg_cont(im,j)==3 ) return;
00170 ent=2 ;
00171
00172 (*func)( 0,Cont,
00173 f_intercept(Cont,phi_cont(im,j),
00174 x_cont(im),phi_cont(i,j),x_cont(i)), y_cont(j));
00175 break ;
00176 case 3 :
00177 if (get_itg_cont(i,j) > 1 ) return;
00178 ent=3 ;
00179
00180 (*func)(0,Cont,x_cont(i), f_intercept(Cont,phi_cont(i,j),
00181 y_cont(j),phi_cont(i,jp),y_cont(jp)));
00182 break ;
00183 case 4 :
00184 if (get_itg_cont(i,j) == 1 || get_itg_cont(i,j)==3 ) return;
00185 ent=4 ;
00186
00187 (*func)(0,Cont,f_intercept(Cont,phi_cont(i,j),
00188 x_cont(i),phi_cont(ip,j),x_cont(ip)),
00189 y_cont(j));
00190 break;
00191 default :
00192 sciprint(" Error in case wrong value ");
00193 break;
00194 }
00195 wflag=1;
00196 while ( wflag)
00197 {
00198 jp= j+1; ip= i+1; jm=j-1;im=i-1;
00199 switch ( ent)
00200 {case 1 :
00201 inc_itg_cont(i,jm,2L);
00202 ent = ffnd(func,i,ip,ip,i,j,j,jm,jm,ent,qq,Cont,&zds);
00203
00204
00205 switch ( ent)
00206 {
00207 case -1: wflag=0; break;
00208 case 1 : i=ip ; break ;
00209 case 2 : i=ip;j=jm; break ;
00210 }
00211 break ;
00212 case 2 :
00213 inc_itg_cont(im,j,1L);
00214 ent = ffnd(func,i,i,im,im,j,jm,jm,j,ent,qq,Cont,&zds);
00215 switch ( ent)
00216 {
00217 case -1: wflag=0; break;
00218 case 2 : j = jm ;break ;
00219 case 3 : i=im;j=jm; break ;
00220 }
00221 break ;
00222 case 3 :
00223 inc_itg_cont(i,j,2L);
00224 ent = ffnd(func,i,im,im,i,j,j,jp,jp,ent,qq,Cont,&zds);
00225 switch ( ent)
00226 {
00227 case -1: wflag=0; break;
00228 case 3 : i=im; break ;
00229 case 4 : i=im;j=jp; break ;
00230 }
00231 break ;
00232 case 4 :
00233 inc_itg_cont(i,j,1L);
00234 ent = ffnd(func,i,i,ip,ip,j,jp,jp,j,ent,qq,Cont,&zds);
00235 switch ( ent)
00236 {
00237 case -1: wflag=0; break;
00238 case 4 :j=jp;break ;
00239 case 1 :i=ip;j=jp;break ;
00240 }
00241 break ;
00242 }
00243
00245 if ( zds == 1)
00246 {
00247 switch ( ent)
00248 {
00249 case 1 : inc_itg_cont(i,(j-1),2L); break ;
00250 case 2 : inc_itg_cont(i-1,j,1L); break ;
00251 case 3 : inc_itg_cont(i,j,2L); break ;
00252 case 4 : inc_itg_cont(i,j,1L); break ;
00253 }
00255 wflag = 0 ;
00256 }
00258 if ( qq == 2)
00259 {
00260 switch ( ent)
00261 {
00262 case 1 : if ( get_itg_cont (i,j-1) > 1) wflag = 0 ; break ;
00263 case 2 : if ( oddp(get_itg_cont(i-1,j))) wflag = 0 ; break ;
00264 case 3 : if ( get_itg_cont(i,j) > 1) wflag = 0 ; break ;
00265 case 4 : if ( oddp(get_itg_cont(i,j))) wflag = 0 ; break ;
00266 }
00267 }
00268 }
00269 if ( func == GContStore2 )
00270 GContStore2Last();
00271 else
00272 ContourTrace(Cont,style);
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286 static void contourI(ptr_level_f func, double *x, double *y, double *z, double *zCont, integer *N, integer *style, integer *err)
00287 {
00288 int check = 1;
00289 char *F;
00290 integer n1,n2,ncont,i,c,j,k,n5;
00291 integer stylec;
00292 n1=N[0];n2=N[1];ncont=N[2];
00293 F=getFPF();
00294 if ( F[0] == '\0')
00295 ChoixFormatE1(ContNumFormat,zCont,N[2]);
00296 InitValues(x,y,z,n1,n2);
00297 n5 = 2*(n1)+2*(n2)-3;
00298
00299 Gcont_size = 0;
00300 xbd_cont = MALLOC( n5 * sizeof(int) ) ;
00301 ybd_cont = MALLOC( n5 * sizeof(int) ) ;
00302 itg_cont = MALLOC( n1*n2 * sizeof(int) ) ;
00303 if ( (xbd_cont == NULL) && n5 != 0) check= 0;
00304 if ( (ybd_cont == NULL) && n5 != 0) check= 0;
00305 if ( (itg_cont == NULL) && n1*n2 != 0) check= 0;
00306 if ( check == 0)
00307 {
00308 FREE( xbd_cont ) ;
00309 FREE( ybd_cont ) ;
00310 FREE( itg_cont ) ;
00311 sciprint("contourI_: Running out of memory\n");
00312 return;
00313 }
00314
00315 for ( i = 0 ; i < n2 ; i++)
00316 {
00317 ybd_cont[i] = i ;
00318 xbd_cont[i] = 0 ;
00319 }
00320 for ( i = 1 ; i < n1 ; i++)
00321 {
00322 ybd_cont[n2+i-1] = n2-1 ;
00323 xbd_cont[n2+i-1] = i ;
00324 }
00325 for ( i = n2-2; i >= 0 ; i--)
00326 {
00327 ybd_cont[2*n2 +n1-3-i] = i ;
00328 xbd_cont[2*n2 +n1-3-i] = n1-1 ;
00329 }
00330 for ( i = n1-2 ; i >= 0 ; i--)
00331 {
00332 ybd_cont[2*n2 +2*n1-4-i] = 0 ;
00333 xbd_cont[2*n2 +2*n1-4-i] = i ;
00334 }
00335 for ( c= 0 ; c < ncont ; c++)
00336 {
00337 stylec = ( style != (integer *) 0) ? style[c] : c;
00339 for ( i = 0 ; i < n1; i++)
00340 for ( j =0 ; j < n2 ; j++)
00341 itg_cont[i+n1*j]=0 ;
00343 for ( k = 1 ; k < n5 ; k++)
00344 { integer ib,jb;
00345 i = xbd_cont[k] ; j = ybd_cont[k];
00346 ib = xbd_cont[k-1] ; jb= ybd_cont[k-1];
00347 if (not_same_sign (phi_cont(i,j)-zCont[c] ,
00348 phi_cont(ib,jb)-zCont[c]))
00349 look(func,i,j,ib,jb,1L,zCont[c],stylec);
00350 }
00352 for ( i = 1 ; i < n1-1; i++)
00353 for ( j = 1 ; j < n2-1 ; j++)
00354 if (not_same_sign ( phi_cont(i,j)-zCont[c] ,
00355 phi_cont(i, j-1)-zCont[c]))
00356 look(func,i,j,i,j-1,2L,zCont[c],stylec);
00357 }
00358 FREE( xbd_cont ) ;
00359 FREE( ybd_cont ) ;
00360 FREE( itg_cont ) ;
00361
00362 }
00363
00364 int C2F(contourif)(double *x, double *y, double *z, integer *n1, integer *n2, integer *flagnz, integer *nz, double *zz, integer *style)
00365 {
00366 integer err=0;
00367 static double *zconst;
00368 double zmin,zmax;
00369 integer N[3],i;
00370
00371 zmin=(double) Mini(z,*n1*(*n2));
00372 zmax=(double) Maxi(z,*n1*(*n2));
00373
00374 if (*flagnz==0)
00375 {
00376 if ( ( zconst = MALLOC( (*nz) * sizeof(double) ) ) == 0 )
00377 {
00378 sciprint("Running out of memory\r\n");
00379 return 0;
00380 }
00381 for ( i =0 ; i < *nz ; i++)
00382 zconst[i]=zmin + (i+1)*(zmax-zmin)/(*nz+1);
00383 N[0]= *n1;N[1]= *n2;N[2]= *nz;
00384 contourI(GContStore2,x,y,z,zconst,N,style,&err);
00385 FREE(zconst) ;
00386 zconst = NULL ;
00387 }
00388 else
00389 {
00390 N[0]= *n1;N[1]= *n2;N[2]= *nz;
00391 contourI(GContStore2,x,y,z,zz,N,style,&err);
00392 }
00393
00394 return(0);
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 static integer ffnd (ptr_level_f func, integer i1, integer i2, integer i3, integer i4, integer jj1, integer jj2, integer jj3, integer jj4, integer ent, integer qq, double Cont, integer *zds)
00410 {
00411 double phi1,phi2,phi3,phi4,xav,yav,phiav;
00412 integer revflag,i;
00413 phi1=phi_cont(i1,jj1)-Cont;
00414 phi2=phi_cont(i2,jj2)-Cont;
00415 phi3=phi_cont(i3,jj3)-Cont;
00416 phi4=phi_cont(i4,jj4)-Cont;
00417 revflag = 0;
00418 *zds = 0;
00419
00420 xav = ( x_cont(i1)+ x_cont(i3))/2.0 ;
00421 yav = ( y_cont(jj1)+ y_cont(jj3))/2.0 ;
00422 phiav = ( phi1+phi2+phi3+phi4) / 4.0;
00423 if (ISNAN(phiav)==1)
00424 {
00425 return -1;
00426 }
00427 if ( not_same_sign( phiav,phi4))
00428 {
00429 integer l1, k1;
00430 double phi;
00431 revflag = 1 ;
00432 l1= i4; k1= jj4;
00433 i4=i1; jj4 = jj1; i1= l1; jj1= k1;
00434 l1= i3; k1= jj3;
00435 i3=i2; jj3= jj2; i2=l1; jj2= k1;
00436 phi = phi1; phi1 = phi4; phi4= phi;
00437 phi = phi3; phi3 = phi2; phi2= phi;
00438 }
00439
00440 (*func)(1,Cont,f_intercept(0.0,phi1,x_cont(i1),phiav,xav),
00441 f_intercept(0.0,phi1,y_cont(jj1),phiav,yav));
00442
00443
00444
00445
00446 for ( i = 0 ; ; i++)
00447 { integer l1,k1;
00448 double phi;
00449 if ( not_same_sign ( phi1,phi2)) break ;
00450 if ( phiav != 0.0 )
00451 {
00452 (*func)(1,Cont,f_intercept(0.0,phi2,x_cont(i2),phiav,xav),
00453 f_intercept(0.0,phi2,y_cont(jj2),phiav,yav));
00454 }
00456 l1=i1; k1= jj1;
00457 i1=i2;jj1=jj2;i2=i3;jj2=jj3;i3=i4;jj3=jj4;i4=l1;jj4=k1;
00458 phi=phi1; phi1=phi2;phi2=phi3;phi3=phi4;phi4=phi;
00459 }
00460 (*func)(1,Cont,f_intercept(0.0,phi1,x_cont(i1),phi2,x_cont(i2)),
00461 f_intercept(0.0,phi1,y_cont(jj1),phi2,y_cont(jj2)));
00462 if ( qq==1 && bdyp(i1,jj1) && bdyp(i2,jj2)) *zds = 1 ;
00463 if ( revflag == 1 && ! oddp (i) ) i = i+2;
00464 return ( 1 + ( ( i + ent + 2) % 4));
00465 }
00466
00467
00468
00469
00470
00471 static integer cont_size ;
00472
00473
00474
00475
00476
00477
00478
00479 static void ContourTrace(double Cont, integer style)
00480 {
00481 char *F;
00482 integer verbose=0 ,Dnarg,Dvalue[10];
00483 integer close=0, flag=0, uc;
00484 double angle=0.0;
00485 char str[100];
00486
00487 C2F(dr)("xget","use color",&verbose,&uc,&Dnarg,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
00488 if (uc) {
00489 C2F(dr)("xget","color",&verbose,Dvalue,&Dnarg,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
00490 C2F(dr)("xset","color",&style,PI0,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
00491 C2F(dr)("xlines","void",&cont_size,xcont,ycont,&close,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
00492 C2F(dr)("xset","color",Dvalue,PI0,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
00493 }
00494 else {
00495 C2F(dr)("xget","line style",&verbose,Dvalue,&Dnarg,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
00496 C2F(dr)("xset","line style",&style,PI0,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
00497 C2F(dr)("xlines","void",&cont_size,xcont,ycont,&close,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
00498 C2F(dr)("xset","line style",Dvalue,PI0,PI0,PI0,PI0,PI0,PD0,PD0,PD0,PD0,0L,0L);
00499 }
00500
00501 F=getFPF();
00502 if ( F[0] == '\0')
00503 sprintf(str,ContNumFormat,Cont);
00504 else
00505 sprintf(str,F,Cont);
00506 C2F(dr)("xstring",str, &xcont[cont_size / 2],&ycont[cont_size /2],
00507 PI0,&flag,PI0,PI0, &angle,PD0,PD0,PD0,0L,0L);
00508 }
00509
00510
00511
00512
00513
00514
00515 static int last=-1;
00516 static int count=0;
00517
00520 int C2F(getconts)(double **x, double **y, integer *mm, integer *n)
00521 {
00522 *x = Gxcont;
00523 *y = Gycont;
00524 *mm= 1;
00525 *n= Gcont_size;
00526 return 0;
00527 }
00528
00529 static void GContStore2(integer ival, double Cont, double xncont, double yncont)
00530 {
00531 int n;
00532 if ( ival == 0)
00533 {
00534
00535
00536
00537 n= Gcont_size + 2;
00538 if ( Gxcont == NULL )
00539 {
00540 Gxcont = MALLOC( n * sizeof(double) ) ;
00541 Gycont = MALLOC( n * sizeof(double) ) ;
00542 }
00543 else
00544 {
00545 Gxcont = REALLOC( Gxcont, n * sizeof(double) ) ;
00546 Gycont = REALLOC( Gycont, n * sizeof(double) ) ;
00547 }
00548 if ( (Gxcont == NULL) && n != 0) return ;
00549 if ( (Gycont == NULL) && n != 0) return ;
00550 Gxcont[Gcont_size] = Cont;
00551 if ( last != -1 && last < n ) Gycont[last]= count;
00552 last = Gcont_size;
00553 Gcont_size++;
00554 count = 0;
00555 }
00556 else
00557 {
00558 n = Gcont_size + 1 ;
00559 if ( Gxcont == NULL )
00560 {
00561 Gxcont = MALLOC( n * sizeof(double) ) ;
00562 Gycont = MALLOC( n * sizeof(double) ) ;
00563 }
00564 else
00565 {
00566 Gxcont = REALLOC( Gxcont, n * sizeof(double) ) ;
00567 Gycont = REALLOC( Gycont, n * sizeof(double) ) ;
00568 }
00569 if ( (Gxcont == NULL) && n != 0) return ;
00570 if ( (Gycont == NULL) && n != 0) return ;
00571 }
00572 Gxcont[Gcont_size]=xncont;
00573 Gycont[Gcont_size++]=yncont;
00574 count++;
00575 }
00576
00577 static void GContStore2Last(void)
00578 {
00579 if ( last != -1 ) Gycont[last]= count;
00580 }
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591