00001 #include <qstring.h> 00002 #include <math.h> 00003 00004 inline double min(double a, double b) 00005 { 00006 if (a<b) return a; 00007 return b; 00008 } 00009 00010 extern double dist(double, double, double, double); 00011 00012 int sign(double b) 00013 { 00014 if (b>0) return 1; 00015 if (b<0) return -1; 00016 return 0; 00017 } 00018 00019 void pos(double x1, double y1, double x2, double y2, double pct, double& x, double &y) 00020 { 00021 double dx = x2-x1; 00022 double dy = y2-y1; 00023 x = x1 + dx*pct; 00024 y = y1 + dy*pct; 00025 } 00026 00027 class NetPoint{ 00028 public: 00029 double x; 00030 double y; 00031 double shouldbe_x; 00032 double shouldbe_y; 00033 double a; 00034 double b; 00035 double nx; 00036 double ny; 00037 bool free; 00038 NetPoint * up; 00039 NetPoint * down; 00040 NetPoint * left; 00041 NetPoint * right; 00042 NetPoint() 00043 { 00044 x = y = shouldbe_x = shouldbe_y = 0; 00045 free = true; 00046 up = down = left = right = NULL; 00047 } 00048 void setNotFree() 00049 { 00050 shouldbe_x=x; 00051 shouldbe_y=y; 00052 free = false; 00053 } 00054 void mark_as_tx() 00055 { 00056 a = x; 00057 b = y; 00058 x = shouldbe_x; 00059 y = shouldbe_y; 00060 } 00061 void move(bool goto_shouldbe) 00062 { 00063 double bx = x; 00064 double by = y; 00065 if (free) 00066 { 00067 int i = 0; 00068 x = 0; 00069 y = 0; 00070 if (left) 00071 { 00072 x+=left->x; 00073 y+=left->y; 00074 i++; 00075 } 00076 if (right) 00077 { 00078 x+=right->x; 00079 y+=right->y; 00080 i++; 00081 } 00082 if (up) 00083 { 00084 x+=up->x; 00085 y+=up->y; 00086 i++; 00087 } 00088 if (down) 00089 { 00090 x+=down->x; 00091 y+=down->y; 00092 i++; 00093 } 00094 x/=i; 00095 y/=i; 00096 } 00097 else if (goto_shouldbe && (shouldbe_x != x || shouldbe_y != y)) 00098 { 00099 double dx=0; 00100 double dy=0; 00101 dx = sign(shouldbe_x-x); 00102 dy = sign(shouldbe_y-y); 00103 x+=dx; 00104 y+=dy; 00105 } 00106 nx = x; 00107 ny =y; 00108 x = bx; 00109 y = by; 00110 } 00111 00112 void fixx() 00113 { 00114 if (!free) return; 00115 // where are the current endpoints 00116 NetPoint * L; 00117 L = left; 00118 while(L) 00119 { 00120 if (!L->free) break; 00121 L=L->left; 00122 } 00123 00124 NetPoint * R; 00125 R = right; 00126 while(R) 00127 { 00128 if (!R->free) break; 00129 R=R->right; 00130 } 00131 assert(L&&R); 00132 double pct = (a-L->a)/(R->a-L->a); 00133 printf("%g\n",pct); 00134 x = pct*(R->x-L->x)+L->x; 00135 } 00136 00137 void fixy() 00138 { 00139 if (!free) return; 00140 // where are the current endpoints 00141 NetPoint * U; 00142 U = up; 00143 while(U) 00144 { 00145 if (!U->free) break; 00146 U=U->up; 00147 } 00148 00149 NetPoint * D; 00150 D = down; 00151 while(D) 00152 { 00153 if (!D->free) break; 00154 D=D->down; 00155 } 00156 assert(U&&D); 00157 double pct = (b-U->b)/(D->b-U->b); 00158 y = pct*(D->y-U->y)+U->y; 00159 } 00160 00161 void realize() 00162 { 00163 x = nx; 00164 y = ny; 00165 } 00166 00167 void set_bound(int mx, int my) 00168 { 00169 if (x>mx-1) x = mx-1; 00170 if (y>my-1) y = my-1; 00171 if (a>mx-1) a = mx-1; 00172 if (b>my-1) b = my-1; 00173 if (x<0) x = 0; 00174 if (y<0) y = 0; 00175 if (a<0) a = 0; 00176 if (b<0) b = 0; 00177 } 00178 }; 00179 00180 extern QString type_name(NetPoint); 00181 00182 #include "value.h" 00183 #include "runtime.h" 00184 00185 /* 00186 Value * Runtime::morph(Value * image, Value * source, Value * target) 00187 { 00188 // input checks 00189 if (image==NULL) return NULL; 00190 if (source==NULL) return NULL; 00191 if (target==NULL) return NULL; 00192 if (typeid(*image)!=typeid(ImageValue)) return NULL; 00193 if (typeid(*source)!=typeid(ValueArray)) return NULL; 00194 if (typeid(*target)!=typeid(ValueArray)) return NULL; 00195 ImageValue * I = (ImageValue*)image; 00196 ValueArray * S = (ValueArray*)source; 00197 ValueArray * T = (ValueArray*)target; 00198 if (S->sx != T->sx) return NULL; 00199 if (S->sy != T->sy) return NULL; 00200 if (S->sy != 1 && S->sx != 1) return NULL; 00201 int marks = S->sx; 00202 if (marks==1) marks=S->sy; 00203 int xs = I->width(); 00204 int ys = I->height(); 00205 int iteraties=dist(xs,ys,0,0); 00206 int ch = I->channelcount(); 00207 double target_x[marks]; 00208 double target_y[marks]; 00209 double source_x[marks]; 00210 double source_y[marks]; 00211 if (S->sx==1) 00212 for(int i = 0 ; i < marks ; i++) 00213 { 00214 Value * sv = S->get(i,0); 00215 Value * tv = T->get(i,0); 00216 if (sv==NULL) return NULL; 00217 if (tv==NULL) return NULL; 00218 if (typeid(*sv)!=typeid(PointValue)) return NULL; 00219 if (typeid(*tv)!=typeid(PointValue)) return NULL; 00220 PointValue * s = (PointValue*)sv; 00221 PointValue * t = (PointValue*)tv; 00222 target_x[i]=(t->x + 1)*xs/2.0; 00223 target_y[i]=(t->y + 1)*ys/2.0; 00224 source_x[i]=(s->x + 1)*xs/2.0; 00225 source_y[i]=(s->y + 1)*ys/2.0; 00226 } 00227 else 00228 for(int i = 0 ; i < marks ; i++) 00229 { 00230 Value * sv = S->get(0,i); 00231 Value * tv = T->get(0,i); 00232 if (sv==NULL) return NULL; 00233 if (tv==NULL) return NULL; 00234 if (typeid(*sv)!=typeid(PointValue)) return NULL; 00235 if (typeid(*tv)!=typeid(PointValue)) return NULL; 00236 PointValue * s = (PointValue*)sv; 00237 PointValue * t = (PointValue*)tv; 00238 target_x[i]=(t->x + 1)*xs/2.0; 00239 target_y[i]=(t->y + 1)*ys/2.0; 00240 source_x[i]=(s->x + 1)*xs/2.0; 00241 source_y[i]=(s->y + 1)*ys/2.0; 00242 } 00243 // we will work with a superimposed net 00244 // each going through the given points. 00245 Array<2,NetPoint> net(marks+2,marks+2); 00246 Array<1,NetPoint> toprow=net(Select<1>(0)); 00247 int nsx = 1; 00248 double equality_distance = 9; 00249 double px = toprow[0].x = 0; 00250 while(px!=xs-1) 00251 { 00252 double md = xs-1-px; 00253 for(int n = 0 ; n < marks ; n++) 00254 { 00255 double d = target_x[n]-px; 00256 if (d>equality_distance && d < md) md = d; 00257 } 00258 px+=md; 00259 toprow[nsx++].x=px; 00260 } 00261 // do the same for the y coordinates 00262 Array<1,NetPoint> leftcol=net(Select<1>(1)); 00263 int nsy = 1; 00264 double py = leftcol[0].y = 0; 00265 while(py!=ys-1) 00266 { 00267 // find the next closest 00268 double md = ys-1-py; 00269 for(int n = 0 ; n < marks ; n++) 00270 { 00271 double d = target_y[n]-py; 00272 if (d>equality_distance && d < md) md = d; 00273 } 00274 py+=md; 00275 leftcol[nsy++].y=py; 00276 } 00277 printf("%d:%d\n",nsx,nsy); 00278 nsx-=2; 00279 nsy-=2; 00280 Array<2,NetPoint> N = net(From<2>(1,1),Size<2>(nsx-2,nsy-2)); 00281 Array<2,NetPoint>::positions it(N); 00282 while(it.more()) 00283 { 00284 // take the x and y value of the resptive 00285 NetPoint & np = it; 00286 NetPoint & left = N[Position<2>(0,it[1])]; 00287 NetPoint & top = N[Position<2>(it[0],0)]; 00288 if (it[0]>0) 00289 { 00290 np.y=left.y; 00291 np.left = &N[Position<2>(it[0]-1,it[1])]; 00292 } 00293 if (it[0]<nsx-1) 00294 { 00295 np.right = &N[Position<2>(it[0]+1,it[1])]; 00296 } 00297 if (it[1]>0) 00298 { 00299 np.x=top.x; 00300 np.up = &N[Position<2>(it[0],it[1]-1)]; 00301 } 00302 if (it[1]<nsy-1) 00303 { 00304 np.down = &N[Position<2>(it[0],it[1]+1)]; 00305 } 00306 if (it[0]==0 || it[1]==0 || 00307 it[0]==nsx - 1 || it[1]==nsy-1) 00308 np.setNotFree(); 00309 // is there a matching point ? 00310 for(int m = 0 ; m < marks ; m++) 00311 { 00312 if (fabs(target_x[m]-np.x)<=equality_distance && 00313 fabs(target_y[m]-np.y)<=equality_distance) 00314 { 00315 assert(np.free); 00316 np.x=target_x[m]; 00317 np.y=target_y[m]; 00318 np.shouldbe_x=source_x[m]; 00319 np.shouldbe_y=source_y[m]; 00320 np.free = false; 00321 } 00322 } 00323 ++it; 00324 } 00325 // now we oscilate the net until we find a fixpoint 00326 int con = iteraties; 00327 do 00328 { 00329 Array<2,NetPoint>::values v(N); 00330 while(v.more()) 00331 { 00332 NetPoint &np=v; 00333 np.move(false); 00334 ++v; 00335 } 00336 Array<2,NetPoint>::values w(N); 00337 while(w.more()) 00338 { 00339 NetPoint &np=w; 00340 np.realize(); 00341 ++w; 00342 } 00343 } 00344 while(con--); 00345 00346 for(Array<2,NetPoint>::values v(N); v.more(); ++v) 00347 v.current()->mark_as_tx(); 00348 printf("Finished marking target\n"); 00349 { 00350 Array<2,NetPoint>::values v(N); 00351 while(v.more()) 00352 { 00353 NetPoint &np=v; 00354 np.fixx(); 00355 ++v; 00356 } 00357 } 00358 { 00359 Array<2,NetPoint>::values v(N); 00360 while(v.more()) 00361 { 00362 NetPoint &np=v; 00363 np.fixy(); 00364 ++v; 00365 } 00366 } 00367 // now we oscilate the net until we find a fixpoint 00368 con=iteraties; 00369 do 00370 { 00371 Array<2,NetPoint>::values v(N); 00372 while(v.more()) 00373 { 00374 NetPoint &np=v; 00375 np.move(true); 00376 ++v; 00377 } 00378 Array<2,NetPoint>::values w(N); 00379 while(w.more()) 00380 { 00381 NetPoint &np=w; 00382 np.realize(); 00383 ++w; 00384 } 00385 } 00386 while(--con); 00387 00388 printf("Drawing triangles\n"); 00389 00390 00391 // print the result net 00392 for(Array<2,NetPoint>::values v(N); v.more(); ++v) 00393 v.current()->set_bound(xs,ys); 00394 00395 00396 ImageValue * A = new ImageValue(xs,ys,3); 00397 for(Array<2,NetPoint>::values v(N); v.more(); ++v) 00398 { 00399 NetPoint &np=v; 00400 A->set(np.a,np.b,0,255); 00401 A->set(np.x, np.y, 1,255); 00402 if (!np.free) 00403 { 00404 A->set(np.a,np.b,2,255); 00405 A->set(np.x,np.y,2,255); 00406 } 00407 } 00408 // return A; 00409 00410 00411 00412 // create the output image 00413 00414 ImageValue * O = new ImageValue(xs,ys,ch); 00415 Array<2,NetPoint>::values boxes(N); 00416 while(boxes.more()) 00417 { 00418 NetPoint & tl = boxes; 00419 ++boxes; 00420 if (!tl.right) continue; 00421 if (!tl.down) continue; 00422 if (!tl.right->down) continue; 00423 NetPoint & br = *tl.right->down; 00424 NetPoint & bl = *tl.down; 00425 NetPoint & tr = *tl.right; 00426 00427 // a,b is the target image 00428 // x,y is the source image 00429 // h,v are the virtual positions 00430 double dh = 1.0/max(dist(tl.a,tl.b,tr.a,tr.b), 00431 dist(bl.a,bl.b,br.a,br.b)); 00432 double dv = 1.0/max(dist(tl.a,tl.b,bl.a,bl.b), 00433 dist(tr.a,tr.b,br.a,br.b)); 00434 for(double h = 0 ; h < 1.0 ; h+=dh) 00435 { 00436 double Ta, Tb; 00437 double Ba, Bb; 00438 pos(tl.a,tl.b,tr.a,tr.b,h,Ta,Tb); 00439 pos(bl.a,bl.b,br.a,br.b,h,Ba,Bb); 00440 00441 double Tx, Ty; 00442 double Bx, By; 00443 pos(tl.x,tl.y,tr.x,tr.y,h,Tx,Ty); 00444 pos(bl.x,bl.y,br.x,br.y,h,Bx,By); 00445 for(double v = 0 ; v < 1.0 ; v+=dv) 00446 { 00447 double a,b,x,y; 00448 pos(Ta,Tb,Ba,Bb,v,a,b); 00449 pos(Tx,Ty,Bx,By,v,x,y); 00450 00451 for(int c = 0 ; c < ch ; c++) 00452 O->set(a,b,c,I->get(x,y,c)); 00453 } 00454 } 00455 } 00456 return O; 00457 00458 } 00459 */ 00460 00461 QString type_name(NetPoint) 00462 { 00463 return "NetPoint-type"; 00464 } 00465 00466 /* 00467 // we now go through all triangles and point the target pixels 00468 Array<2,NetPoint>::positions it(net); 00469 while(it.more()) 00470 { 00471 // take the x and y value of the resptive 00472 NetPoint & np = it; 00473 if ( 00474 NetPoint & left = net[Position<2>(0,it[1])]; 00475 NetPoint & top = net[Position<2>(it[0],0)]; 00476 if (it[0]>0) 00477 { 00478 np.y=left.y; 00479 np.left = &net[Position<2>(it[0]-1,it[1])]; 00480 } 00481 if (it[0]<nsx) 00482 { 00483 np.right = &net[Position<2>(it[0]+1,it[1])]; 00484 } 00485 if (it[1]>0) 00486 { 00487 np.x=top.x; 00488 np.up = &net[Position<2>(it[0],it[1]-1)]; 00489 } 00490 if (it[1]<nsy) 00491 { 00492 np.down = &net[Position<2>(it[0],it[1]+1)]; 00493 } 00494 // is there a mathcing point ? 00495 for(int m = 0 ; m < marks ; m++) 00496 { 00497 if (target_x[m]==np.x && 00498 target_y[m]==np.y) 00499 { 00500 np.shouldbe_x=source_x[m]; 00501 np.shouldbe_y=source_y[m]; 00502 np.free = false; 00503 } 00504 } 00505 ++it; 00506 } 00507 00508 // calculate the x addresses 00509 ImageValue * A = new ImageValue(xs,ys,3); 00510 for(int a = 0 ; a < xs ; a++) 00511 { 00512 for(int m = 0 , m < marks ; m++) 00513 { 00514 double tx = target_x[m]; 00515 double sx; 00516 if (a < tx) 00517 { 00518 double pxt = a/tx; 00519 sx = 00520 } 00521 } 00522 } 00523 // we first sort the points according to y 00524 00525 int idx[marks]; 00526 qsort(idx,marks,sizeof(int),compare_element); 00527 00528 ImageValue * B = new ImageValue(xs,ys,3); 00529 // calculate the target addresses 00530 // in every step we set the know positions and then 00531 // the field is calculated to fill in the remaining data 00532 // until a stable point is reached 00533 for(int a = 0 ; a < xs ; a++) 00534 for(int b = 0 ; b < ys ; b++) 00535 { 00536 A->set(a,b,0,a); 00537 A->set(a,b,1,b); 00538 B->set(a,b,0,a); 00539 B->set(a,b,1,b); 00540 } 00541 for(int i = 0 ; i < 100 ; i ++) 00542 { 00543 printf("%d\n",i); 00544 for(int m = 0 ; m < marks ; m++) 00545 { 00546 A->set(target_x[m],target_y[m],0,source_x[m]); 00547 A->set(target_x[m],target_y[m],1,source_y[m]); 00548 } 00549 for(int a = 1 ; a < xs-1 ; a++) 00550 for(int b = 1 ; b < ys-1 ; b++) 00551 { 00552 double sum_x=0; 00553 double sum_y=0; 00554 for(int x = - 1 ; x <= 1 ; x++) 00555 for(int y = -1 ; y <= 1 ; y++) 00556 { 00557 // we subtract x and y because 00558 // if we take the pixel left then we must assume 00559 // that pixel ab will be one position higher 00560 sum_x += A->get(a+x,b+y,0)-x-y; 00561 sum_y += A->get(a+x,b+y,1)-x-y; 00562 } 00563 sum_x/=9; 00564 sum_y/=9; 00565 B->set(a,b,0,sum_x); 00566 B->set(a,b,1,sum_y); 00567 } 00568 ImageValue * t = A; 00569 A = B; 00570 B = t; 00571 } 00572 00573 ImageValue * O = new ImageValue(xs,ys,ch); 00574 for(int a = 0 ; a < xs ; a++) 00575 for(int b = 0 ; b < ys ; b++) 00576 { 00577 int x = A->get(a,b,0); 00578 int y = A->get(a,b,1); 00579 // printf("Fetching %d:%d from %d:%d\n",a,b,x,y); 00580 if (x<0) x = 0; 00581 if (y<0) y = 0; 00582 if (x>=xs) x = xs-1; 00583 if (y>=ys) y = ys-1; 00584 // copy pixel 00585 for(int c = 0 ; c < ch ; c++) 00586 O->set(a,b,c,I->get(x,y,c)); 00587 } 00588 return O; 00589 } 00590 */ 00591 00592 Value * Runtime::morph(vector<Value*> v) 00593 { 00594 if (v.size()!=3) return NULL; 00595 return morph(v[0],v[1],v[2]); 00596 } 00597 00598 int side(double a, double b, double x1, double y1, double x2, double y2) 00599 { 00600 return sign( (a-x1)*(y2-y1) - (b-y1)*(x2-x1) ); 00601 } 00602 00603 00604 /*Value * Runtime::morph(Value * image, Value * source, Value * target) 00605 { 00606 // input checks 00607 if (image==NULL) return NULL; 00608 if (source==NULL) return NULL; 00609 if (target==NULL) return NULL; 00610 if (typeid(*image)!=typeid(ImageValue)) return NULL; 00611 if (typeid(*source)!=typeid(ValueArray)) return NULL; 00612 if (typeid(*target)!=typeid(ValueArray)) return NULL; 00613 ImageValue * I = (ImageValue*)image; 00614 ValueArray * S = (ValueArray*)source; 00615 ValueArray * T = (ValueArray*)target; 00616 if (S->sx != T->sx) return NULL; 00617 if (S->sy != T->sy) return NULL; 00618 if (S->sy != 1) return NULL; 00619 int marks = S->sx; 00620 int xs = I->width(); 00621 int ys = I->height(); 00622 int ch = I->channelcount(); 00623 double target_x[marks]; 00624 double target_y[marks]; 00625 double source_x[marks]; 00626 double source_y[marks]; 00627 for(int i = 0 ; i < marks ; i++) 00628 { 00629 Value * sv = S->get(i,0); 00630 Value * tv = T->get(i,0); 00631 if (sv==NULL) return NULL; 00632 if (tv==NULL) return NULL; 00633 if (typeid(*sv)!=typeid(PointValue)) return NULL; 00634 if (typeid(*tv)!=typeid(PointValue)) return NULL; 00635 PointValue * s = (PointValue*)sv; 00636 PointValue * t = (PointValue*)tv; 00637 I->ocsToDcs(t,target_x[i],target_y[i]); 00638 i->ocsToDcs(s,source_x[i],source_y[i]); 00639 } 00640 // create the output image 00641 ImageValue * O = new ImageValue(xs,ys,ch); 00642 for(int a = 0 ; a < xs ; a++) 00643 for(int b = 0 ; b < ys ; b++) 00644 { 00645 // first closest point 00646 double md = dist(0,0,xs,ys); 00647 int p1 = -1; 00648 for(int m = 0 ; m < marks ; m++) 00649 { 00650 double d = dist(a,b,target_x[m],target_y[m]); 00651 if (d<md) 00652 { 00653 md = d; 00654 p1 = m; 00655 } 00656 } 00657 // second and third point 00658 md = dist(0,0,xs,ys); 00659 md*=md; 00660 int p2 = -1; 00661 int p3 = -1; 00662 for(int m = 0 ; m < marks ; m++) 00663 { 00664 if (m==p1) continue; 00665 for(int n = 0 ; n < marks ; n++) 00666 { 00667 if (n == p1) continue; 00668 if (n == m) continue; 00669 00670 // does the triangle contain (a,b) ? 00671 int s1 = side(a,b,target_x[p1],target_y[p1],target_x[m],target_y[m]); 00672 int s2 = side(a,b,target_x[m],target_y[m],target_x[n],target_y[n]); 00673 int s3 = side(a,b,target_x[n],target_y[n],target_x[p1],target_y[p1]); 00674 bool ok = (s1>=0 && s2>=0 && s3>=0) || (s1<=0 && s2<=0 && s3<=0); 00675 if (!ok) continue; 00676 // weigh the triangle. the smaller the d the better 00677 double d = dist(target_x[n],target_y[n],target_x[m],target_y[m]) 00678 * dist(target_x[n],target_y[n],target_x[p1],target_y[p1]); 00679 if (d<md) 00680 { 00681 md = d; 00682 p2 = m; 00683 p3 = n; 00684 } 00685 } 00686 } 00687 if (a>30 && a < xs-30 && b > 30 && b < ys-30) 00688 { 00689 assert(p3!=-1); 00690 } 00691 if (p3==-1) continue; 00692 // we find two points on two lines of the target triangle 00693 double d12 = dist(target_x[p1],target_y[p1],target_x[p2],target_y[p2]); 00694 double d23 = dist(target_x[p3],target_y[p3],target_x[p2],target_y[p2]); 00695 double d13 = dist(target_x[p1],target_y[p1],target_x[p3],target_y[p3]); 00696 int q1,q2,q3; 00697 if (d12>d23) 00698 { 00699 if (d13 > d12) 00700 { 00701 // 1 - 3 is maximum side 00702 q1 = p1; 00703 q2 = p3; 00704 q3 = p2; 00705 } 00706 else 00707 { 00708 // 1 - 2 is maximum side 00709 q1 = p1; 00710 q2 = p2; 00711 q3 = p3; 00712 } 00713 } 00714 else 00715 { 00716 if (d13 > d23) 00717 { 00718 // 1 - 3 is maximum side 00719 q1 = p1; 00720 q2 = p3; 00721 q3 = p2; 00722 } 00723 else 00724 { 00725 // 2 - 3 is maximum side 00726 q1 = p2; 00727 q2 = p3; 00728 q3 = p1; 00729 } 00730 } 00731 // here we determine then which point axis provides highest 00732 // accuracy 00733 double ddx = fabs(target_x[q1]-target_x[q2]); 00734 double ddy = fabs(target_y[q1]-target_y[q2]); 00735 bool swap = false; 00736 if (ddx>ddy) 00737 { 00738 // we take the x axis 00739 double sq2 = sign(a - target_x[q2]); 00740 double sq3 = sign(a - target_x[q3]); 00741 swap = (sq3>=0 && sq2<=0) || (sq3<=0 && sq2>=0); 00742 } 00743 else 00744 { 00745 // we must take the y axis for best accuacy 00746 double sq2 = sign(b - target_y[q2]); 00747 double sq3 = sign(b - target_y[q3]); 00748 swap = (sq3>=0 && sq2<=0) || (sq3<=0 && sq2>=0); 00749 } 00750 // we now swap them 00751 if (swap) 00752 { 00753 int tmp = q1; 00754 q1 = q2; 00755 q2 = tmp; 00756 } 00757 // determine x or y positions on segments 1-3 & 1-2 00758 int x, y; 00759 { 00760 double d13; 00761 double d12; 00762 if (ddx>ddy) 00763 { 00764 d13 = (a - target_x[q1]) / (target_x[q3]-target_x[q1]); 00765 d12 = (a - target_x[q1]) / (target_x[q2]-target_x[q1]); 00766 } 00767 else 00768 { 00769 d13 = (b - target_y[q1]) / (target_y[q3]-target_y[q1]); 00770 d12 = (b - target_y[q1]) / (target_y[q2]-target_y[q1]); 00771 } 00772 // assert(d13>=0); 00773 // assert(d13<=1.1); 00774 // assert(d12>=0); 00775 // assert(d12<=1.1); 00776 // find the line segment position starting from d12 00777 double t12x; 00778 double t12y; 00779 double t13x; 00780 double t13y; 00781 pos(target_x[q1],target_y[q1],target_x[q2],target_y[q2],d12,t12x,t12y); 00782 pos(target_x[q1],target_y[q1],target_x[q3],target_y[q3],d13,t13x,t13y); 00783 double ds = dist(a,b,t12x,t12y)/dist(t13x,t13y,t12x,t12y); 00784 if (ds>1) continue; 00785 assert(ds>=0); 00786 assert(ds<=1); 00787 double s12x; 00788 double s12y; 00789 double s13x; 00790 double s13y; 00791 pos(source_x[q1],source_y[q1],source_x[q2],source_y[q2],d12,s12x,s12y); 00792 pos(source_x[q1],source_y[q1],source_x[q3],source_y[q3],d13,s13x,s13y); 00793 double fx,fy; 00794 pos(s12x,s12y,s13x,s13y,ds,fx,fy); 00795 x = fx; 00796 y = fy; 00797 } 00798 // within bounds ? 00799 // printf("Fetching %d:%d from %d:%d\n",a,b,x,y); 00800 if (x<0) x = 0; 00801 if (y<0) y = 0; 00802 if (x>=xs) x = xs-1; 00803 if (y>=ys) y = ys-1; 00804 // copy pixel 00805 for(int c = 0 ; c < ch ; c++) 00806 O->set(a,b,c,I->get(x,y,c)); 00807 } 00808 return O; 00809 } 00810 00811 */ 00812 // triangles ? 00813 // if we make a grid of equal sized corners then it should be possible 00814 // to bend various lines, somewhat like a spring. Those lines can then be used to 00815 // 00816 00817 int * getRing(double *x, double *y, int & count, bool* enabled, int points) 00818 { 00819 int * result = new int[points]; 00820 count = 0; 00821 double largestx = -1; 00822 int idx = -1; 00823 for(int i = 0 ; i < points; i++) 00824 if (enabled[i] && x[i]>largestx) 00825 largestx=x[idx=i]; 00826 if (idx==-1) 00827 { 00828 printf("No points left\n"); 00829 return NULL; 00830 } 00831 result[count++]=idx; 00832 printf("pointidx %d\n",idx); 00833 00834 while(true) 00835 { 00836 bool added_something = false; 00837 for(int i = 0 ; i < points; i++) 00838 { 00839 if (!enabled[i]) continue; 00840 bool already_in_result = false; 00841 for(int k = 0 ; k < count ; k++) 00842 if (result[k]==i) already_in_result = true; 00843 if (already_in_result) continue; 00844 int j; 00845 for(j = 0 ; j < points; j++) 00846 { 00847 if (!enabled[j]) continue; 00848 if (j==result[count-1]) continue; 00849 if (j==i) continue; 00850 if (side(x[j], 00851 y[j], 00852 x[result[count-1]], 00853 y[result[count-1]], 00854 x[i], 00855 y[i])>0) break; 00856 } 00857 if (j==points) 00858 { 00859 printf("pointidx %d\n",i); 00860 added_something = true; 00861 result[count++]=i; 00862 assert(count < 1000); 00863 break; 00864 } 00865 } 00866 if (!added_something) return result; 00867 } 00868 } 00869 00870 class Triangle 00871 { 00872 public: 00873 int A; 00874 int B; 00875 int C; 00876 }; 00877 00878 void newpoint(double ax, double ay, double bx, double by, double cx, double cy, 00879 double ix, double iy, double &tx, double &ty) 00880 { 00881 ax-=bx; 00882 ay-=by; 00883 cx-=bx; 00884 cy-=by; 00885 tx = ax + cx; 00886 ty = ay + cy; 00887 double d = dist(0,0,tx,ty); 00888 tx /= d; 00889 ty /= d; 00890 tx *= 40; 00891 ty *= 40; 00892 tx = ix - tx; 00893 ty = iy - ty; 00894 } 00895 00896 /* 00897 00898 Value * Runtime::morph(Value * image, Value * source, Value * target) 00899 { 00900 // input checks 00901 if (image==NULL) return NULL; 00902 if (source==NULL) return NULL; 00903 if (target==NULL) return NULL; 00904 if (typeid(*image)!=typeid(ImageValue)) return NULL; 00905 if (typeid(*source)!=typeid(ValueArray)) return NULL; 00906 if (typeid(*target)!=typeid(ValueArray)) return NULL; 00907 ImageValue * I = (ImageValue*)image; 00908 ValueArray * S = (ValueArray*)source; 00909 ValueArray * T = (ValueArray*)target; 00910 if (S->sx != T->sx) return NULL; 00911 if (S->sy != T->sy) return NULL; 00912 if (S->sy != 1 && S->sx != 1) return NULL; 00913 int marks = S->sx; 00914 if (marks==1) marks=S->sy; 00915 int xs = I->width(); 00916 int ys = I->height(); 00917 int ch = I->channelcount(); 00918 // the extra 1 element is useful to create the last ring 00919 double *target_x = new double[marks+1]; 00920 double *target_y = new double[marks+1]; 00921 double *source_x = new double[marks+1]; 00922 double *source_y = new double[marks+1]; 00923 if (S->sx==1) 00924 for(int i = 0 ; i < marks ; i++) 00925 { 00926 Value * sv = S->get(i,0); 00927 Value * tv = T->get(i,0); 00928 if (sv==NULL) return NULL; 00929 if (tv==NULL) return NULL; 00930 if (typeid(*sv)!=typeid(PointValue)) return NULL; 00931 if (typeid(*tv)!=typeid(PointValue)) return NULL; 00932 PointValue * s = (PointValue*)sv; 00933 PointValue * t = (PointValue*)tv; 00934 target_x[i]=(t->x + 1)*xs/2.0; 00935 target_y[i]=(t->y + 1)*ys/2.0; 00936 source_x[i]=(s->x + 1)*xs/2.0; 00937 source_y[i]=(s->y + 1)*ys/2.0; 00938 } 00939 else 00940 for(int i = 0 ; i < marks ; i++) 00941 { 00942 Value * sv = S->get(0,i); 00943 Value * tv = T->get(0,i); 00944 if (sv==NULL) return NULL; 00945 if (tv==NULL) return NULL; 00946 if (typeid(*sv)!=typeid(PointValue)) return NULL; 00947 if (typeid(*tv)!=typeid(PointValue)) return NULL; 00948 PointValue * s = (PointValue*)sv; 00949 PointValue * t = (PointValue*)tv; 00950 target_x[i]=(t->x + 1)*xs/2.0; 00951 target_y[i]=(t->y + 1)*ys/2.0; 00952 source_x[i]=(s->x + 1)*xs/2.0; 00953 source_y[i]=(s->y + 1)*ys/2.0; 00954 } 00955 00956 int triangle_count = 0; 00957 Triangle triangles[1000]; 00958 bool enabled[marks]; 00959 for(int i = 0 ; i < marks ; i++) 00960 enabled[i]=true; 00961 int outer_count; 00962 int * outer_index = getRing(target_x,target_y,outer_count,enabled,marks); 00963 // fix the marks array with outer_count extra fields 00964 if (outer_count > 2) 00965 { 00966 double *ntarget_x=new double[marks+outer_count+1]; 00967 double *ntarget_y=new double[marks+outer_count+1]; 00968 double *nsource_x=new double[marks+outer_count+1]; 00969 double *nsource_y=new double[marks+outer_count+1]; 00970 for(int i = 0 ; i < marks ; i ++) 00971 { 00972 ntarget_x[i]=target_x[i]; 00973 ntarget_y[i]=target_y[i]; 00974 nsource_x[i]=source_x[i]; 00975 nsource_y[i]=source_y[i]; 00976 } 00977 target_x=ntarget_x; 00978 target_y=ntarget_y; 00979 source_x=nsource_x; 00980 source_y=nsource_y; 00981 for(int c = 0 ; c < outer_count ; c++) 00982 { 00983 int p = c - 1; 00984 if (p<0) p=outer_count-1; 00985 int n = (c + 1)%outer_count; 00986 newpoint(target_x[outer_index[p]],target_y[outer_index[p]], 00987 target_x[outer_index[c]],target_y[outer_index[c]], 00988 target_x[outer_index[n]],target_y[outer_index[n]], 00989 target_x[outer_index[c]],target_y[outer_index[c]], 00990 target_x[c+marks], target_y[c+marks]); 00991 newpoint(target_x[outer_index[p]],target_y[outer_index[p]], 00992 target_x[outer_index[c]],target_y[outer_index[c]], 00993 target_x[outer_index[n]],target_y[outer_index[n]], 00994 source_x[outer_index[c]],source_y[outer_index[c]], 00995 source_x[c+marks], source_y[c+marks]); 00996 } 00997 marks+=outer_count; 00998 // restart with extra ring... 00999 for(int i = 0 ; i < marks ; i++) enabled[i]=true; 01000 outer_index = getRing(target_x,target_y,outer_count,enabled,marks); 01001 } 01002 01003 // here we add a boundary to the outer layer; 01004 bool last_ring_processed = false; 01005 while (!last_ring_processed) 01006 { 01007 // we disable all these positions 01008 for(int i = 0 ; i < outer_count ; i++) 01009 enabled[outer_index[i]]=false; 01010 // and find the inner ring 01011 int inner_count; 01012 int * inner_index = getRing(target_x,target_y,inner_count,enabled,marks); 01013 // we then create the triangles 01014 if (!inner_index) 01015 { 01016 // find the mean 01017 double a,x; 01018 double b,y; 01019 a=b=x=y=0; 01020 for(int i = 0 ; i < outer_count; i++) 01021 { 01022 a+=target_x[outer_index[i]]; 01023 b+=target_y[outer_index[i]]; 01024 x+=source_x[outer_index[i]]; 01025 y+=source_y[outer_index[i]]; 01026 } 01027 a/=outer_count; 01028 b/=outer_count; 01029 x/=outer_count; 01030 y/=outer_count; 01031 target_x[marks]=a; 01032 target_y[marks]=b; 01033 source_x[marks]=x; 01034 source_y[marks]=y; 01035 last_ring_processed = true; 01036 inner_count = 1; 01037 inner_index = new int[1]; 01038 inner_index[0] = marks; 01039 } 01040 int oi = 0; 01041 int ii = 0; 01042 while(true) 01043 { 01044 // the current segment is oi -- ii 01045 // the next one is either from o to i2 01046 // or from i to o2 01047 int oi2 = (oi+1)%outer_count; 01048 int ii2 = (ii+1)%inner_count; 01049 double do1i2=dist(target_x[outer_index[oi]],target_y[outer_index[oi]], 01050 target_x[inner_index[ii2]],target_y[inner_index[ii2]]); 01051 double do2i1=dist(target_x[outer_index[oi2]],target_y[outer_index[oi2]], 01052 target_x[inner_index[ii]],target_y[inner_index[ii]]); 01053 int tA; 01054 int tB; 01055 int tC; 01056 if (do1i2<do2i1 && ii!=ii2) 01057 { 01058 tA = outer_index[oi]; 01059 tB = inner_index[ii]; 01060 tC = inner_index[ii2]; 01061 oi = oi; 01062 ii = ii2; 01063 } 01064 else 01065 { 01066 tA = outer_index[oi]; 01067 tB = inner_index[ii]; 01068 tC = outer_index[oi2]; 01069 oi = oi2; 01070 ii = ii; 01071 } 01072 // do we have the triangle ? 01073 bool have_triangle = false; 01074 for(int i = 0 ; i < triangle_count ; i++) 01075 { 01076 if (triangles[i].A==tA 01077 && triangles[i].B==tB 01078 && triangles[i].C==tC) 01079 have_triangle = true; 01080 } 01081 // we add the triangle 01082 if (have_triangle) 01083 break; 01084 triangles[triangle_count].A=tA; 01085 triangles[triangle_count].B=tB; 01086 triangles[triangle_count].C=tC; 01087 triangle_count++; 01088 assert(triangle_count<1000); 01089 // if (last_ring_processed) 01090 printf("%d - %d\n",oi,ii); 01091 } 01092 printf("triangle_count %d\n",triangle_count); 01093 outer_index = inner_index; 01094 outer_count = inner_count; 01095 } 01096 01097 // create the output image 01098 ImageValue * O = new ImageValue(xs,ys,ch); 01099 for(int triangle = 0 ; triangle< triangle_count ; triangle++) 01100 { 01101 Triangle t = triangles[triangle]; 01102 double Aa = target_x[t.A]; 01103 double Ab = target_y[t.A]; 01104 double Ax = source_x[t.A]; 01105 double Ay = source_y[t.A]; 01106 01107 double Ba = target_x[t.B]; 01108 double Bb = target_y[t.B]; 01109 double Bx = source_x[t.B]; 01110 double By = source_y[t.B]; 01111 01112 double Ca = target_x[t.C]; 01113 double Cb = target_y[t.C]; 01114 double Cx = source_x[t.C]; 01115 double Cy = source_y[t.C]; 01116 01117 // a,b is the target image 01118 // x,y is the source image 01119 // h,v are the virtual positions 01120 double dh = 1.0/max(dist(Aa,Ab,Ba,Bb), 01121 dist(Ca,Cb,Ca,Cb)); 01122 double dv = 1.0/max(dist(Aa,Ab,Ca,Cb), 01123 dist(Ba,Bb,Ca,Cb)); 01124 for(double h = 0 ; h < 1.0 ; h+=dh) 01125 { 01126 double Ta, Tb; 01127 pos(Aa,Ab,Ba,Bb,h,Ta,Tb); 01128 01129 double Tx, Ty; 01130 pos(Ax,Ay,Bx,By,h,Tx,Ty); 01131 for(double v = 0 ; v < 1.0 ; v+=dv) 01132 { 01133 double a,b,x,y; 01134 pos(Ta,Tb,Ca,Cb,v,a,b); 01135 pos(Tx,Ty,Cx,Cy,v,x,y); 01136 01137 if (a<0) continue; 01138 if (b<0) continue; 01139 if (x<0) continue; 01140 if (y<0) continue; 01141 if (a>=xs) continue; 01142 if (b>=ys) continue; 01143 if (x>=xs) continue; 01144 if (y>=ys) continue; 01145 01146 for(int c = 0 ; c < ch ; c++) 01147 O->set(a,b,c,I->get(x,y,c)); 01148 } 01149 } 01150 } 01151 return O; 01152 } 01153 01154 */ 01155 01156 bool Q1(double a) 01157 { 01158 while (a<0) a+=2*M_PI; 01159 while (a>=2*M_PI) a-=2*M_PI; 01160 bool r = a<=M_PI/2; 01161 return r; 01162 } 01163 01164 bool Q3(double a) 01165 { 01166 while (a<0) a+=2*M_PI; 01167 while (a>=2*M_PI) a-=2*M_PI; 01168 bool r = a>=3*M_PI/2; 01169 return r; 01170 } 01171 01172 double calc_step(double x1, double y1, double x2, double y2) 01173 { 01174 double d = dist(x1,y1,x2,y2); 01175 if (d==0) return 1; 01176 return 0.5/d; 01177 } 01178 01179 Value * Runtime::morph(Value * image, Value * source, Value * target) 01180 { 01181 // input checks 01182 if (image==NULL) return NULL; 01183 if (source==NULL) return NULL; 01184 if (target==NULL) return NULL; 01185 if (typeid(*image)!=typeid(ImageValue)) return NULL; 01186 if (typeid(*source)!=typeid(ValueArray)) return NULL; 01187 if (typeid(*target)!=typeid(ValueArray)) return NULL; 01188 ImageValue * I = (ImageValue*)image; 01189 ValueArray * S = (ValueArray*)source; 01190 ValueArray * T = (ValueArray*)target; 01191 if (S->sx != T->sx) return NULL; 01192 if (S->sy != T->sy) return NULL; 01193 if (S->sy != 1 && S->sx != 1) return NULL; 01194 int marks = S->sx; 01195 if (marks==1) marks=S->sy; 01196 int xs = I->width_direct(); 01197 int ys = I->height_direct(); 01198 int ch = I->channelcount(); 01199 // the extra 1 element is useful to create the last ring 01200 double *target_x = new double[marks+1]; 01201 double *target_y = new double[marks+1]; 01202 double *source_x = new double[marks+1]; 01203 double *source_y = new double[marks+1]; 01204 if (S->sx==1) 01205 for(int i = 0 ; i < marks ; i++) 01206 { 01207 Value * sv = S->get(i,0); 01208 Value * tv = T->get(i,0); 01209 if (sv==NULL) return NULL; 01210 if (tv==NULL) return NULL; 01211 if (typeid(*sv)!=typeid(PointValue)) return NULL; 01212 if (typeid(*tv)!=typeid(PointValue)) return NULL; 01213 01214 PointValue * s = (PointValue*)sv; 01215 PointValue * t = (PointValue*)tv; 01216 I->ocsToDcs(*t,target_x[i],target_y[i]); 01217 I->ocsToDcs(*s,source_x[i],source_y[i]); 01218 } 01219 else 01220 for(int i = 0 ; i < marks ; i++) 01221 { 01222 Value * sv = S->get(0,i); 01223 Value * tv = T->get(0,i); 01224 if (sv==NULL) return NULL; 01225 if (tv==NULL) return NULL; 01226 if (typeid(*sv)!=typeid(PointValue)) return NULL; 01227 if (typeid(*tv)!=typeid(PointValue)) return NULL; 01228 PointValue * s = (PointValue*)sv; 01229 PointValue * t = (PointValue*)tv; 01230 I->ocsToDcs(*t,target_x[i],target_y[i]); 01231 I->ocsToDcs(*s,source_x[i],source_y[i]); 01232 } 01233 01234 bool enabled[marks]; 01235 for(int i = 0 ; i < marks ; i++) 01236 enabled[i]=true; 01237 int outer_count; 01238 int * outer_index = getRing(target_x,target_y,outer_count,enabled,marks); 01239 ImageValue * O = new ImageValue(xs,ys,ch); 01240 while (true) 01241 { 01242 // find the middle of the outer circle... 01243 double ca,cx; 01244 double cb,cy; 01245 ca=cb=cx=cy=0; 01246 for(int i = 0 ; i < outer_count; i++) 01247 { 01248 ca+=target_x[outer_index[i]]; 01249 cb+=target_y[outer_index[i]]; 01250 cx+=source_x[outer_index[i]]; 01251 cy+=source_y[outer_index[i]]; 01252 } 01253 ca/=outer_count; 01254 cb/=outer_count; 01255 cx/=outer_count; 01256 cy/=outer_count; 01257 // we disable all the outer positions 01258 for(int i = 0 ; i < outer_count ; i++) 01259 enabled[outer_index[i]]=false; 01260 // and find the inner ring 01261 int inner_count; 01262 int * inner_index = getRing(target_x,target_y,inner_count,enabled,marks); 01263 // go through 360 degree and fill the gap between the outer and inner circle 01264 01265 // we don't go through all possible angles, instead we iterate over every outer segment 01266 // and try to figure out a matching inner segment 01267 for(int s = 0 ; s < outer_count ; s++) 01268 { 01269 int n = (s+1)%outer_count; 01270 double ab = target_x[outer_index[s]]; 01271 double bb = target_y[outer_index[s]]; 01272 double ae = target_x[outer_index[n]]; 01273 double be = target_y[outer_index[n]]; 01274 double xb = source_x[outer_index[s]]; 01275 double yb = source_y[outer_index[s]]; 01276 double xe = source_x[outer_index[n]]; 01277 double ye = source_y[outer_index[n]]; 01278 double pct_out_delta = calc_step(ab,bb,ae,be); 01279 for(double pct_out = 0 ; pct_out<=1.0 ; pct_out+=pct_out_delta) 01280 { 01281 double a_out,b_out; 01282 double x_out,y_out; 01283 double angle = atan2(b_out-cb,a_out-ca); 01284 pos(ab,bb,ae,be,pct_out,a_out,b_out); 01285 pos(xb,yb,xe,ye,pct_out,x_out,y_out); 01286 01287 // we need to find the correct inner segment 01288 double a_in=ca,b_in=cb; 01289 double x_in=cx, y_in=cy; 01290 for(int s = 0 ; s < inner_count ; s++) 01291 { 01292 int n = (s+1)%inner_count; 01293 double ab = target_x[inner_index[s]]; 01294 double bb = target_y[inner_index[s]]; 01295 double ae = target_x[inner_index[n]]; 01296 double be = target_y[inner_index[n]]; 01297 double angle_b = atan2(bb-cb,ab-ca); 01298 double angle_e = atan2(be-cb,ae-ca); 01299 angle_b-=angle; 01300 angle_e-=angle; 01301 if ( (Q1(angle_b) && Q3(angle_e)) || 01302 (Q3(angle_b) && Q1(angle_e))) 01303 { 01304 double db = dist(ab,bb,ca,cb); 01305 double de = dist(ae,be,ca,cb); 01306 // we subtract the angle 01307 double x1 = cos(angle_b)*db; 01308 double x2 = cos(angle_e)*de; 01309 double y1 = sin(angle_b)*db; 01310 double y2 = sin(angle_e)*de; 01311 double din = (-y1*(x2-x1)/(y2-y1))+x1; 01312 a_in = cos(angle)*din + ca; 01313 b_in = sin(angle)*din + cb; 01314 double pct_in = dist(a_in,b_in,ab,bb)/dist(ab,bb,ae,be); 01315 double xb = source_x[inner_index[s]]; 01316 double yb = source_y[inner_index[s]]; 01317 double xe = source_x[inner_index[n]]; 01318 double ye = source_y[inner_index[n]]; 01319 pos(xb,yb,xe,ye,pct_in,x_in,y_in); 01320 break; 01321 } 01322 } 01323 // iterate through the positions 01324 double pct_delta = calc_step(a_out,b_out,a_in,b_in); 01325 for(double pct = 0 ; pct<=1.0 ; pct+=pct_delta) 01326 { 01327 double a,b; 01328 double x,y; 01329 pos(a_out,b_out,a_in,b_in,pct,a,b); 01330 pos(x_out,y_out,x_in,y_in,pct,x,y); 01331 01332 if (a<0) continue; 01333 if (b<0) continue; 01334 if (x<0) continue; 01335 if (y<0) continue; 01336 if (a>=xs) continue; 01337 if (b>=ys) continue; 01338 if (x>=xs) continue; 01339 if (y>=ys) continue; 01340 01341 for(int c = 0 ; c < ch ; c++) 01342 O->set_direct(a,b,c,I->get_direct(x,y,c)); 01343 } 01344 } 01345 } 01346 if (inner_count==0 || inner_index==NULL) break; 01347 for(int s = 0 ; s < inner_count ; s++) 01348 { 01349 int n = (s+1)%inner_count; 01350 double ab = target_x[inner_index[s]]; 01351 double bb = target_y[inner_index[s]]; 01352 double ae = target_x[inner_index[n]]; 01353 double be = target_y[inner_index[n]]; 01354 double xb = source_x[inner_index[s]]; 01355 double yb = source_y[inner_index[s]]; 01356 double xe = source_x[inner_index[n]]; 01357 double ye = source_y[inner_index[n]]; 01358 double pct_out_delta = calc_step(ab,bb,ae,be); 01359 for(double pct_out = 0 ; pct_out<=1.0 ; pct_out+=pct_out_delta) 01360 { 01361 double a_out,b_out; 01362 double x_out,y_out; 01363 double angle = atan2(b_out-cb,a_out-ca); 01364 pos(ab,bb,ae,be,pct_out,a_out,b_out); 01365 pos(xb,yb,xe,ye,pct_out,x_out,y_out); 01366 01367 // we need to find the correct outer segment 01368 double a_in,b_in; 01369 double x_in, y_in; 01370 for(int s = 0 ; s < outer_count ; s++) 01371 { 01372 int n = (s+1)%outer_count; 01373 double ab = target_x[outer_index[s]]; 01374 double bb = target_y[outer_index[s]]; 01375 double ae = target_x[outer_index[n]]; 01376 double be = target_y[outer_index[n]]; 01377 double angle_b = atan2(bb-cb,ab-ca); 01378 double angle_e = atan2(be-cb,ae-ca); 01379 angle_b-=angle; 01380 angle_e-=angle; 01381 if ( (Q1(angle_b) && Q3(angle_e)) || 01382 (Q3(angle_b) && Q1(angle_e))) 01383 { 01384 double db = dist(ab,bb,ca,cb); 01385 double de = dist(ae,be,ca,cb); 01386 // we subtract the angle 01387 double x1 = cos(angle_b)*db; 01388 double x2 = cos(angle_e)*de; 01389 double y1 = sin(angle_b)*db; 01390 double y2 = sin(angle_e)*de; 01391 double din = (-y1*(x2-x1)/(y2-y1))+x1; 01392 a_in = cos(angle)*din + ca; 01393 b_in = sin(angle)*din + cb; 01394 double pct_in = dist(a_in,b_in,ab,bb)/dist(ab,bb,ae,be); 01395 double xb = source_x[outer_index[s]]; 01396 double yb = source_y[outer_index[s]]; 01397 double xe = source_x[outer_index[n]]; 01398 double ye = source_y[outer_index[n]]; 01399 pos(xb,yb,xe,ye,pct_in,x_in,y_in); 01400 break; 01401 } 01402 } 01403 // iterate through the positions 01404 double pct_delta = calc_step(a_out,b_out,a_in,b_in); 01405 for(double pct = 0 ; pct<=1.0 ; pct+=pct_delta) 01406 { 01407 double a,b; 01408 double x,y; 01409 pos(a_out,b_out,a_in,b_in,pct,a,b); 01410 pos(x_out,y_out,x_in,y_in,pct,x,y); 01411 01412 if (a<0) continue; 01413 if (b<0) continue; 01414 if (x<0) continue; 01415 if (y<0) continue; 01416 if (a>=xs) continue; 01417 if (b>=ys) continue; 01418 if (x>=xs) continue; 01419 if (y>=ys) continue; 01420 01421 for(int c = 0 ; c < ch ; c++) 01422 O->set_direct(a,b,c,I->get_direct(x,y,c)); 01423 } 01424 } 01425 } 01426 outer_index = inner_index; 01427 outer_count = inner_count; 01428 } 01429 return O; 01430 }