Back to index

wims  3.65+svn20090927
levelcurve.c
Go to the documentation of this file.
00001 /*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
00002  *
00003  *  This program is free software; you can redistribute it and/or modify
00004  *  it under the terms of the GNU General Public License as published by
00005  *  the Free Software Foundation; either version 2 of the License, or
00006  *  (at your option) any later version.
00007  *
00008  *  This program is distributed in the hope that it will be useful,
00009  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00010  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00011  *  GNU General Public License for more details.
00012  *
00013  *  You should have received a copy of the GNU General Public License
00014  *  along with this program; if not, write to the Free Software
00015  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00016  */
00017 
00018 static int _lcomp(const void *l1, const void *l2)
00019 {
00020     const double *d1, *d2;
00021     double d;
00022     d1=(const double *) l1; d2=(const double *) l2;
00023     d=*d1-*d2;
00024     if(d<0) return -1; if(d>0) return 1;
00025     return 0;
00026 }
00027 
00028 static double lc_scalex(leveldata *ld, int x)
00029 {
00030     if(x<0) x=0; if(x>=ld->xsize) x=ld->xsize-1;
00031     return ld->xspan*((double) x - 0.40127)/ld->xsize+ld->xrange[0];
00032 }
00033 
00034 static double lc_scaley(leveldata *ld, int y)
00035 {
00036     if(y<0) y=0; if(y>=ld->ysize) y=ld->ysize-1;
00037     return -ld->yspan*((double) y - 0.40127)/ld->ysize+ld->yrange[1];
00038 }
00039 
00040 static int _getlevel(leveldata *ld, int x, int y)
00041 {
00042     double dd;
00043     int i;
00044     
00045     eval_setval(ld->xevpos,lc_scalex(ld,x));
00046     eval_setval(ld->yevpos,lc_scaley(ld,y));
00047     set_evalue_error(0); set_evalue_pointer(ld->fn); dd=_evalue(10);
00048     for(i=0;i<ld->levelcnt && dd>ld->levels[i];i++);
00049     return i;
00050 }
00051 
00052 static void lc_replacexy(leveldata *ld)
00053 {
00054     char *pp;
00055     for(pp=varchr(ld->fn,ld->xname);pp!=NULL;pp=varchr(pp,ld->xname)) {
00056        string_modify(ld->fn,pp,pp+strlen(ld->xname),EV_X);
00057        pp+=strlen(EV_X);
00058     }
00059     for(pp=varchr(ld->fn,ld->yname);pp!=NULL;pp=varchr(pp,ld->yname)) {
00060        string_modify(ld->fn,pp,pp+strlen(ld->yname),EV_Y);
00061        pp+=strlen(EV_Y);
00062     }
00063 }
00064 
00065        /* produces level curve data. Returns non-zero if error. */
00066 int levelcurve(leveldata *ld)
00067 {
00068     int xx,yy,xi,yi,xsteps,ysteps;
00069     int i,x,y,xt,yt;
00070     short int l1[LEVELSIZE_LIM+16], l2[LEVELSIZE_LIM+16];
00071     short int l3[LEVELGRAIN_LIM+2][LEVELGRAIN_LIM+2];
00072     char f[MAX_LINELEN+1];
00073     
00074     ld->datacnt=0;
00075     if(ld->fn==NULL || *(ld->fn)==0 || ld->levelcnt<1) return 1;
00076     if(ld->grain<1) ld->grain=4;
00077     if(ld->grain>LEVELGRAIN_LIM) ld->grain=LEVELGRAIN_LIM;
00078     if(ld->levelcnt>LEVEL_LIM) ld->levelcnt=LEVEL_LIM;
00079     if(ld->xsize<10 || ld->xsize>LEVELSIZE_LIM) return 2;
00080     if(ld->ysize<10 || ld->ysize>LEVELSIZE_LIM) return 2;
00081     if(check_parentheses(ld->fn,0)) return 3;
00082     ld->xspan=ld->xrange[1]-ld->xrange[0];
00083     ld->yspan=ld->yrange[1]-ld->yrange[0];
00084     if(ld->levelcnt>1) qsort(ld->levels,ld->levelcnt,sizeof(double),_lcomp);
00085     if(ld->xname==NULL || *(ld->xname)==0) ld->xname="x";
00086     if(ld->yname==NULL || *(ld->yname)==0) ld->yname="y";
00087     snprintf(f,sizeof(f),"%s",ld->fn); substitute(f); ld->fn=f;
00088     ld->xevpos=eval_getpos(EV_X); ld->yevpos=eval_getpos(EV_Y);
00089     if(ld->xevpos<0 || ld->yevpos<0) return 4;
00090     lc_replacexy(ld); evalue_compile(f);
00091     xsteps=(ld->xsize+ld->grain-1)/ld->grain+1;
00092     ysteps=(ld->ysize+ld->grain-1)/ld->grain+1;
00093     for(yy=yi=0;yi<ysteps;yy+=ld->grain,yi++) l2[yi]=_getlevel(ld,0,yy);
00094     l2[ysteps]=l2[ysteps-1];
00095     for(xi=1,xx=ld->grain;xi<xsteps && ld->datacnt<LEVELPOINT_LIM;xx+=ld->grain,xi++) {
00096        memmove(l1,l2,(ysteps+1)*sizeof(short int));
00097        for(yi=yy=0;yi<ysteps;yy+=ld->grain,yi++) l2[yi]=_getlevel(ld,xx,yy);
00098        l2[ysteps]=l2[ysteps-1];
00099        for(yi=0;yi<ysteps && ld->datacnt<LEVELPOINT_LIM;yi++)
00100          if(l1[yi]!=l1[yi+1] || l1[yi]!=l2[yi] || l1[yi]!=l2[yi+1]) {
00101              for(x=0,xt=(xi-1)*ld->grain;x<=ld->grain;x++,xt++)
00102               for(y=0,yt=yi*ld->grain;y<=ld->grain;y++,yt++) {
00103                   if(x==0 && y==0) {l3[x][y]=l1[yi]; continue;}
00104                   if(x==0 && y==ld->grain) {l3[x][y]=l1[yi+1]; continue;}
00105                   if(x==ld->grain && y==0) {l3[x][y]=l2[yi]; continue;}
00106                   if(x==ld->grain && y==ld->grain) {l3[x][y]=l2[yi+1]; continue;}
00107                   l3[x][y]=_getlevel(ld,xt,yt);
00108               }
00109              for(x=0,xt=(xi-1)*ld->grain;x<ld->grain;x++,xt++)
00110               for(y=0,yt=yi*ld->grain;y<ld->grain;y++,yt++) {
00111                   i=l3[x][y];
00112                   if((i!=l3[x][y+1] || i!=l3[x+1][y]) && 
00113                      ld->datacnt<LEVELPOINT_LIM && 
00114                      (i!=l3[x][y+1] || ld->datacnt==0 ||
00115                      l3[x+1][y+1]==l3[x+1][y] ||
00116                      ld->xdata[ld->datacnt-1]!=xt ||
00117                      ld->ydata[ld->datacnt-1]!=yt-1)) {
00118                      ld->xdata[ld->datacnt]=xt;
00119                      ld->ydata[ld->datacnt++]=yt;
00120                   }
00121               }
00122          }
00123     }
00124     return 0;
00125 }
00126