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