Subversion Repositories wimsdev

Rev

Rev 8160 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
  2.  *
  3.  *  This program is free software; you can redistribute it and/or modify
  4.  *  it under the terms of the GNU General Public License as published by
  5.  *  the Free Software Foundation; either version 2 of the License, or
  6.  *  (at your option) any later version.
  7.  *
  8.  *  This program is distributed in the hope that it will be useful,
  9.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.  *  GNU General Public License for more details.
  12.  *
  13.  *  You should have received a copy of the GNU General Public License
  14.  *  along with this program; if not, write to the Free Software
  15.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16.  */
  17. #include "libwims.h"
  18.  
  19. static int _lcomp(const void *l1, const void *l2)
  20. {
  21.     const double *d1, *d2;
  22.     double d;
  23.     d1=(const double *) l1; d2=(const double *) l2;
  24.     d=*d1-*d2;
  25.     if(d<0) return -1;
  26.     if(d>0) return 1;
  27.     return 0;
  28. }
  29.  
  30. static double lc_scalex(leveldata *ld, int x)
  31. {
  32.     if(x<0) x=0;
  33.     if(x>=ld->xsize) x=ld->xsize-1;
  34.     return ld->xspan*((double) x - 0.40127)/ld->xsize+ld->xrange[0];
  35. }
  36.  
  37. static double lc_scaley(leveldata *ld, int y)
  38. {
  39.     if(y<0) y=0;
  40.     if(y>=ld->ysize) y=ld->ysize-1;
  41.     return -ld->yspan*((double) y - 0.40127)/ld->ysize+ld->yrange[1];
  42. }
  43.  
  44. static int _getlevel(leveldata *ld, int x, int y)
  45. {
  46.     double dd;
  47.     int i;
  48.  
  49.     eval_setval(ld->xevpos,lc_scalex(ld,x));
  50.     eval_setval(ld->yevpos,lc_scaley(ld,y));
  51.     dd=checked_eval(ld->fn);
  52.     for(i=0;i<ld->levelcnt && dd>ld->levels[i];i++);
  53.     return i;
  54. }
  55.  
  56. static void lc_replacexy(leveldata *ld)
  57. {
  58.     char *pp;
  59.     for(pp=varchr(ld->fn,ld->xname);pp!=NULL;pp=varchr(pp,ld->xname)) {
  60.       string_modify(ld->fn,pp,pp+strlen(ld->xname),EV_X);
  61.       pp+=strlen(EV_X);
  62.     }
  63.     for(pp=varchr(ld->fn,ld->yname);pp!=NULL;pp=varchr(pp,ld->yname)) {
  64.       string_modify(ld->fn,pp,pp+strlen(ld->yname),EV_Y);
  65.       pp+=strlen(EV_Y);
  66.     }
  67. }
  68.  
  69. /* produces level curve data. Returns non-zero if error. */
  70. int levelcurve(leveldata *ld)
  71. {
  72.     int xx,yy,xi,yi,xsteps,ysteps;
  73.     int i,x,y,xt,yt;
  74.     short int l1[LEVELSIZE_LIM+16], l2[LEVELSIZE_LIM+16];
  75.     short int l3[LEVELGRAIN_LIM+2][LEVELGRAIN_LIM+2];
  76.     char f[MAX_LINELEN+1];
  77.  
  78.     ld->datacnt=0;
  79.     if(ld->fn==NULL || *(ld->fn)==0 || ld->levelcnt<1) return 1;
  80.     if(ld->grain<1) ld->grain=4;
  81.     if(ld->grain>LEVELGRAIN_LIM) ld->grain=LEVELGRAIN_LIM;
  82.     if(ld->levelcnt>LEVEL_LIM) ld->levelcnt=LEVEL_LIM;
  83.     if(ld->xsize<10 || ld->xsize>LEVELSIZE_LIM) return 2;
  84.     if(ld->ysize<10 || ld->ysize>LEVELSIZE_LIM) return 2;
  85.     if(check_parentheses(ld->fn,0)) return 3;
  86.     ld->xspan=ld->xrange[1]-ld->xrange[0];
  87.     ld->yspan=ld->yrange[1]-ld->yrange[0];
  88.     if(ld->levelcnt>1) qsort(ld->levels,ld->levelcnt,sizeof(double),_lcomp);
  89.     if(ld->xname==NULL || *(ld->xname)==0) ld->xname="x";
  90.     if(ld->yname==NULL || *(ld->yname)==0) ld->yname="y";
  91.     snprintf(f,sizeof(f),"%s",ld->fn); substitute(f); ld->fn=f;
  92.     ld->xevpos=eval_getpos(EV_X); ld->yevpos=eval_getpos(EV_Y);
  93.     if(ld->xevpos<0 || ld->yevpos<0) return 4;
  94.     lc_replacexy(ld); evalue_compile(f);
  95.     xsteps=(ld->xsize+ld->grain-1)/ld->grain+1;
  96.     ysteps=(ld->ysize+ld->grain-1)/ld->grain+1;
  97.     for(yy=yi=0;yi<ysteps;yy+=ld->grain,yi++) l2[yi]=_getlevel(ld,0,yy);
  98.     l2[ysteps]=l2[ysteps-1];
  99.     for(xi=1,xx=ld->grain;xi<xsteps && ld->datacnt<LEVELPOINT_LIM;xx+=ld->grain,xi++) {
  100.       memmove(l1,l2,(ysteps+1)*sizeof(short int));
  101.       for(yi=yy=0;yi<ysteps;yy+=ld->grain,yi++) l2[yi]=_getlevel(ld,xx,yy);
  102.       l2[ysteps]=l2[ysteps-1];
  103.       for(yi=0;yi<ysteps && ld->datacnt<LEVELPOINT_LIM;yi++)
  104.         if(l1[yi]!=l1[yi+1] || l1[yi]!=l2[yi] || l1[yi]!=l2[yi+1]) {
  105.             for(x=0,xt=(xi-1)*ld->grain;x<=ld->grain;x++,xt++)
  106.               for(y=0,yt=yi*ld->grain;y<=ld->grain;y++,yt++) {
  107.                 if(x==0 && y==0) {l3[x][y]=l1[yi]; continue;}
  108.                 if(x==0 && y==ld->grain) {l3[x][y]=l1[yi+1]; continue;}
  109.                 if(x==ld->grain && y==0) {l3[x][y]=l2[yi]; continue;}
  110.                 if(x==ld->grain && y==ld->grain) {l3[x][y]=l2[yi+1]; continue;}
  111.                 l3[x][y]=_getlevel(ld,xt,yt);
  112.               }
  113.             for(x=0,xt=(xi-1)*ld->grain;x<ld->grain;x++,xt++)
  114.               for(y=0,yt=yi*ld->grain;y<ld->grain;y++,yt++) {
  115.                 i=l3[x][y];
  116.                 if((i!=l3[x][y+1] || i!=l3[x+1][y]) &&
  117.                    ld->datacnt<LEVELPOINT_LIM &&
  118.                    (i!=l3[x][y+1] || ld->datacnt==0 ||
  119.                   l3[x+1][y+1]==l3[x+1][y] ||
  120.                   ld->xdata[ld->datacnt-1]!=xt ||
  121.                   ld->ydata[ld->datacnt-1]!=yt-1)) {
  122.                   ld->xdata[ld->datacnt]=xt;
  123.                   ld->ydata[ld->datacnt++]=yt;
  124.                 }
  125.               }
  126.         }
  127.     }
  128.     return 0;
  129. }
  130.  
  131.