morph.cpp

Go to the documentation of this file.
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 }

Generated on Mon Jun 5 22:08:42 2006 for iis by  doxygen 1.4.6