Subversion Repositories wimsdev

Rev

Rev 8147 | 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.  
  18.         /* Compare two curves */
  19. /* Input parameters: environment.
  20.  *
  21.  * w_curvecomp_1 and w_curvecomp_2: curves to compare, as lists of points.
  22.  * w_curvecomp_xrange and w_curvecomp_yrange: list of 2 integers each.
  23.  * w_curvecomp_tolerance: Maximal tolerance of distances.
  24.  *
  25.  * Output: 10 double numbers separated by white spaces.
  26.  *
  27.  * Number 1: Average distance of curve 1 with respect to curve 2.
  28.  * Number 2: Average distance of curve 2 with respect to curve 1.
  29.  * Number 3: Maximal distance of curve 1 with respect to curve 2.
  30.  * Number 4: Maximal distance of curve 2 with respect to curve 1.
  31.  * Number 5: Proportion of curve 1 close to curve 2.
  32.  * Number 6: Proportion of curve 2 close to curve 1.
  33.  * Number 7: Maximal jump of curve 1.
  34.  * Number 8: Maximal jump of curve 2.
  35.  * Number 9: Ratio of repetitions found in curve 1.
  36.  * Number 10: Ratio of repetitions found in curve 2.
  37.  * Furthermore, words "fnofx" and/or "fnofy" will appear if curve 2
  38.  *   represents the graph of a function of x (and/or y).
  39.  *
  40.  * Returns empty if one of the curves is degenerated.
  41. */
  42.  
  43. /*************** Customization: change values hereafter ****************/
  44.  
  45.         /* limit of point buffers */
  46. #define pointlim        4096
  47. #define default_tolerance 10
  48.  
  49. /***************** Nothing should need change hereafter *****************/
  50.  
  51. #include "../wims.h"
  52. char curve1[2*MAX_LINELEN+2], curve2[2*MAX_LINELEN+2];
  53. int bx[2], by[2];
  54. int tol=default_tolerance;
  55. int xfn=0, yfn=0;
  56. int discrete;
  57. double dist1, dist2, max1, max2, ratio1, ratio2, rep1, rep2;
  58. double djump1, djump2;
  59. struct cv {
  60.     int x,y, closest, rep;
  61.     double dist;
  62. } cv1[pointlim], cv2[pointlim];
  63. int points1,points2;
  64.  
  65. int Abs(int t) {if(t>=0) return t; else return -t;}
  66. int Min(int x,int y) {if(x>y) return y; else return x;}
  67. int Max(int x,int y) {if(x<y) return y; else return x;}
  68.  
  69. int listbuf[pointlim*2], listcnt;
  70.  
  71.         /* Strips leading spaces */
  72. char *find_word_start(char *p)
  73. {
  74.     int i;
  75.     for(i=0; isspace(*p) && i<MAX_LINELEN; p++,i++);
  76.     return p;
  77. }
  78.  
  79. void reverse(struct cv *cvbuf, int cnt)
  80. {
  81.     int i;
  82.     struct cv cvt;
  83.     for(i=0;i<cnt/2;i++) {
  84.         memmove(&cvt,cvbuf+i,sizeof(cvt));
  85.         memmove(cvbuf+i,cvbuf+(cnt-i-1),sizeof(cvt));
  86.         memmove(cvbuf+(cnt-i-1),&cvt,sizeof(cvt));
  87.     }
  88. }
  89.  
  90. int str2list(char *p, int lim)
  91. {
  92.     char *p2;
  93.     for(p2=strchr(p,';'); p2; p2=strchr(p2+1,';')) *p2=',';
  94.     for(listcnt=0; p && listcnt<lim; p=p2) {
  95.         p2=strchr(p,','); if(p2!=NULL) *p2++=0;
  96.         p=find_word_start(p); if(*p==0) continue;
  97.         listbuf[listcnt++]=atoi(p);    
  98.     }
  99.     return listcnt;
  100. }
  101.  
  102. int list2curve(struct cv *cvbuf)
  103. {
  104.     int i, j, m, t, st, xx, yy, x2, y2, x3, y3, ll;
  105.  
  106.     ll=listcnt/2; if(ll<2) return 0;
  107.     xx=listbuf[0]; yy=listbuf[1];
  108.     j=0; if(xx>=bx[0] && xx<=bx[1] && yy>=by[0] && yy<=by[1]) {
  109.         cvbuf[0].x=xx; cvbuf[0].y=yy; j++;
  110.     }
  111.     for(i=1; i<ll && j<pointlim; i++) {
  112.         x2=listbuf[2*i]; y2=listbuf[2*i+1];
  113.         m=Max(Abs(x2-xx),Abs(y2-yy)); if(m<=0) continue;
  114.         if(discrete==1) st=m; else st=1;
  115.         for(t=st; t<=m && j<pointlim; t++) {
  116.             x3=(double) (x2*t+xx*(m-t))/m+0.5;
  117.             y3=(double) (y2*t+yy*(m-t))/m+0.5;
  118.             if(x3>=bx[0] && x3<=bx[1] && y3>=by[0] && y3<=by[1]) {
  119.                 cvbuf[j].x=x3; cvbuf[j].y=y3; cvbuf[j].dist=-1;
  120.                 cvbuf[j].rep=0; j++;
  121.             }
  122.         }
  123.         xx=x2; yy=y2;
  124.     }
  125.     return j;
  126. }
  127.  
  128. void compare(void)
  129. {
  130.     int i, j, cl;
  131.     double d, dt;
  132.    
  133.     d=2*pointlim; cl=-1;
  134.     for(i=0,djump1=1;i<points1-1;i++) {
  135.         dt=sqrt(pow(cv1[i].x-cv1[i+1].x,2)+pow(cv1[i].y-cv1[i+1].y,2));
  136.         if(dt>djump1) djump1=dt;
  137.     }
  138.     for(i=0,djump2=1;i<points2-1;i++) {
  139.         dt=sqrt(pow(cv2[i].x-cv2[i+1].x,2)+pow(cv2[i].y-cv2[i+1].y,2));
  140.         if(dt>djump2) djump2=dt;
  141.     }
  142.     for(i=0;i<points1;i++) {
  143.         for(j=0;j<points2;j++) {
  144.             dt=sqrt(pow(cv2[j].x-cv1[i].x,2)+pow(cv2[j].y-cv1[i].y,2));
  145.             if(dt<d) {d=dt; cl=j;}
  146.             else {dt=(dt-d)/djump2; if(dt>2) j+=dt-1;}
  147.         }
  148.         cv1[i].dist=d; cv1[i].closest=cl;
  149.         if(i<points1)
  150.           d+=sqrt(pow(cv1[i].x-cv1[i+1].x,2)+pow(cv1[i].y-cv1[i+1].y,2))+0.1;
  151.     }
  152.     d=2*pointlim; for(i=0;i<points2;i++) {
  153.         for(j=0;j<points1;j++) {
  154.             dt=sqrt(pow(cv1[j].x-cv2[i].x,2)+pow(cv1[j].y-cv2[i].y,2));
  155.             if(dt<d) {d=dt; cl=j;}
  156.             else {dt=(dt-d)/djump1; if(dt>2) j+=dt-1;}
  157.         }
  158.         cv2[i].dist=d; cv2[i].closest=cl;
  159.         if(i<points2)
  160.           d+=sqrt(pow(cv2[i].x-cv2[i+1].x,2)+pow(cv2[i].y-cv2[i+1].y,2))+0.1;
  161.     }
  162.     for(i=1, cl=cv1[0].closest;i<points1;i++) {
  163.         j=cv1[i].closest; if(j!=cl) cv2[j].rep++;
  164.         cl=j;
  165.     }
  166.     for(i=1, cl=cv2[0].closest;i<points2;i++) {
  167.         j=cv2[i].closest; if(j!=cl) cv1[j].rep++;
  168.         cl=j;
  169.     }
  170.     for(i=cl=0; i<points1; i++) if(cv1[i].rep>1) cl+=cv1[i].rep-1;
  171.     rep1=(double) cl/points1;
  172.     for(i=cl=0; i<points1; i++) if(cv2[i].rep>1) cl+=cv2[i].rep-1;
  173.     rep2=(double) cl/points2;
  174. }
  175.  
  176. void check(void)
  177. {
  178.     int i,j,xret1,yret1,xret2,yret2;
  179.     int xx,yy,xmin,xmax,ymin,ymax;
  180.     double d;
  181.     max1=max2=0;
  182.     for(i=j=0,d=0;i<points1;i++) {
  183.         if(cv1[i].dist<=tol) j++;
  184.         d+=pow(cv1[i].dist,4);
  185.         if(max1<cv1[i].dist) max1=cv1[i].dist;
  186.     }
  187.     ratio1=(double) j/points1; dist1=pow(d/points1,0.25)*1.8;
  188.     for(i=j=0,d=0;i<points2;i++) {
  189.         if(cv2[i].dist<=tol) j++;
  190.         d+=pow(cv2[i].dist,4); 
  191.         if(max2<cv2[i].dist) max2=cv2[i].dist;
  192.     }
  193.     ratio2=(double) j/points2; dist2=pow(d/points2,0.25)*1.8;
  194.     xret1=xret2=yret1=yret2=0;
  195.     xmin=xmax=cv2[0].x; ymin=ymax=cv2[0].y;
  196.     for(i=1;i<points2;i++) {
  197.         xx=cv2[i].x; yy=cv2[i].y;
  198.         xret1=Max(xret1,xmax-xx); xret2=Max(xret2,xx-xmin);
  199.         yret1=Max(yret1,ymax-yy); yret2=Max(yret2,yy-ymin);
  200.         xmin=Min(xx,xmin);xmax=Max(xx,xmax);
  201.         ymin=Min(yy,ymin);ymax=Max(yy,ymax);
  202.     }
  203.     if(Min(xret1,xret2)<=2) xfn=1;
  204.     if(Min(yret1,yret2)<=2) yfn=1;
  205. }
  206.  
  207. void output(void)
  208. {
  209.     printf("%.2f %.2f %.2f %.2f \
  210. %.3f %.3f %.1f %.1f \
  211. %.3f %.3f",
  212.            dist1, dist2, max1, max2,
  213.            ratio1, ratio2, djump1, djump2,
  214.            rep1, rep2);
  215.     if(xfn) printf(" fx");
  216.     if(yfn) printf(" fy");
  217. }
  218.  
  219. void test(void)
  220. {
  221.     int i;
  222.     for(i=0;i<points1;i++) printf("%d,%d,%d,%.2f\n",
  223.                                   cv1[i].x,cv1[i].y,cv1[i].closest,cv1[i].dist);
  224.     printf("\n");
  225.     for(i=0;i<points2;i++) printf("%d,%d,%d,%.2f\n",
  226.                                   cv2[i].x,cv2[i].y,cv2[i].closest,cv2[i].dist);
  227.     printf("\n");
  228. }
  229.  
  230. int main(int argc, char *argv[])
  231. {
  232.     int i;
  233.     char *c1, *c2, *op;
  234.     c1=getenv("w_curvecomp_1"); c2=getenv("w_curvecomp_2");
  235.         /* nothing to do */
  236.     if(c1==NULL || c2==NULL || *c1==0 || *c2==0) return 0;
  237.     snprintf(curve1,sizeof(curve1),"%s",c1);
  238.     snprintf(curve2,sizeof(curve2),"%s",c2);
  239.     bx[0]=by[0]=bx[1]=by[1]=-1;
  240.     c1=getenv("w_curvecomp_xrange"); c2=getenv("w_curvecomp_yrange");
  241.     if(c1!=NULL && *c1!=0) {
  242.         str2list(c1,2); for(i=0;i<listcnt;i++) bx[i]=listbuf[i];
  243.     }
  244.     if(c2!=NULL && *c2!=0) {
  245.         str2list(c2,2); for(i=0;i<listcnt;i++) by[i]=listbuf[i];
  246.     }
  247.     op=getenv("w_curvecomp_option"); if(op==NULL) op="";
  248.     if(bx[0]==-1) bx[0]=0; if(bx[1]==-1) bx[1]=pointlim;
  249.     if(by[0]==-1) by[0]=0; if(by[1]==-1) by[1]=pointlim;
  250.     c1=getenv("w_curvecomp_tolerance");
  251.     if(c1!=NULL && *c1!=0) tol=atoi(c1);
  252.     tol=Min(30,Max(5,tol));
  253.    
  254.     if(strstr(op,"discrete1")!=NULL) discrete=1; else discrete=0;
  255.     str2list(curve1,pointlim*2); points1=list2curve(cv1);
  256.     if(strstr(op,"discrete2")!=NULL) discrete=1; else discrete=0;
  257.     str2list(curve2,pointlim*2); points2=list2curve(cv2);
  258.     if(points1<2 || points2<2) return 0;
  259.     compare(); check(); output();
  260.     return 0;
  261. }
  262.  
  263.