realroot_doc 0.1.1
/Users/mourrain/Devel/mmx/realroot/include/realroot/fatarcs_fcts.hpp
Go to the documentation of this file.
00001 #include <vector>
00002 #include <realroot/Interval.hpp>
00003 #include <realroot/Seq.hpp>
00004 #define SMALL  C(10e-20)
00005 #define REP    poly.rep()
00006 #define SIZE   poly.size()
00007 
00008 #pragma once
00009 
00010 using namespace mmx;
00011 
00013 //vec_t fcts
00014 
00015 template<class C>
00016 std::vector<C> vec (const C c1, const C c2) {
00017   std::vector<C> a(2, C(0));
00018    a[0]= c1; a[1]= c2;
00019   return a;
00020 }
00021 
00022 template<class C>
00023 std::vector<C> rotl(std::vector<C> p){
00024   std::vector<C> v; v=vec(C(-1)*p[1],p[0]); return(v);
00025 };       /*rotate left*/
00026 
00027 template<class C>
00028 C dot(std::vector<C> p ,std::vector<C> q){
00029   C v=C(0);
00030  for(unsigned i=0; i<p.size(); i++){
00031    v +=p[i]*q[i];
00032  } 
00033 return(v);
00034 };
00035 
00036 template<class C>
00037 std::vector<C> v_plus(std::vector<C> p ,std::vector<C> q){
00038   std::vector<C> v(p.size(),C(0));
00039  assert( p.size()==q.size() );
00040  for(unsigned i=0; i<p.size(); i++){
00041    v[i]=p[i]+q[i];
00042  } 
00043 return(v);
00044 };
00045 
00046 template<class C>
00047 std::vector<C> v_minus(std::vector<C> p ,std::vector<C> q){
00048   std::vector<C> v(p.size(),C(0));
00049   assert( p.size()==q.size() );
00050  for(unsigned i=0; i<p.size(); i++){
00051    v[i]=p[i]-q[i];
00052  } 
00053 return(v);
00054 };
00055 
00056 template<class C>
00057 std::vector<C> v_div(std::vector<C> p ,C q){
00058   if (q!=C(0)){
00059     std::vector<C>  v(p.size(),C(0));
00060     for(unsigned i=0; i<p.size(); i++){
00061       v[i]=p[i]/q;}; 
00062     return(v);}else{return std::vector<C>();}
00063 };
00064 
00065 template<class C>
00066 std::vector<C> v_mul(C q, std::vector<C> p){
00067   std::vector<C>  v(p.size(),C(0));
00068  for(unsigned i=0; i<p.size(); i++){
00069    v[i]=p[i]*q;
00070  } 
00071 return(v);
00072 };
00073 
00074 template<class C>
00075 C v_length(std::vector<C> p){
00076   return(sqrt(dot(p,p)));
00077 };   /*length of vector*/
00078 
00079 template<class C>
00080 std::vector<C> matrat(std::vector<C> v1,std::vector<C> v2){
00081   std::vector<C> mm; mm=vec(v1[0]*v2[0]+v1[1]*v2[1],v1[0]*v2[1]-v2[0]*v1[1]); 
00082   return(mm);
00083 };
00084 
00085 template<class C>
00086 std::vector<C> crossrat(std::vector<C> v1,std::vector<C> v2,std::vector<C> v3,std::vector<C> v4){ 
00087   std::vector<C> mm=matrat(matrat(v_minus(v1,v2),v_minus(v3,v2)),matrat(v_minus(v1,v4),v_minus(v3,v4))); 
00088 return(mm);
00089 };
00090 
00091 
00093 //solver and test fcts
00094 template<class C>
00095 bool is_zero(C p){
00096   if(p==C(0)){return true;}
00097   else{return false;}
00098   };
00099 
00100 template<class C>
00101 bool is_small(C p){
00102   if(p==C(0)){return true;}
00103   else{return false;}
00104   };
00105 
00106 /*
00107 template<class C>
00108 bool is_small(C p){
00109   if(p<SMALL && p>C(-1)*SMALL){return true;}
00110   else{return false;}
00111   };
00112 */
00113 
00114 template<class C>
00115 Seq<C> solve2(C a, C b, C c){
00116   Seq<C> r; r<<C(-1)<<C(-1);  
00117   C root1,root2;  
00118   if(is_small(a)){if(!is_small(b)){r[0]=C(-1)*c/b;r[1]=C(-1)*c/b;}}
00119   else{if(sign(b*b-C(4)*a*c) >= 0){
00120       root1=(C(-1)*b+sqrt(b*b-C(4)*a*c))/(C(2)*a);
00121       root2=(C(-1)*b-sqrt(b*b-C(4)*a*c))/(C(2)*a);
00122       r[0]=root1;r[1]=root2;}
00123     }
00124  
00125   return(r);
00126 };/*solve(a*x^2+b*x+c=0)*/
00127 
00128 template<class C>
00129 bool is_unit1(C p){
00130   if(p<C(0) || p>C(1) ){return false;}
00131   else{return true;}
00132 };/*1dim unit test*/
00133 
00134 
00135 template<class C>
00136 bool is_unit2( std::vector<C> p){
00137   if( is_unit1( p[0] ) && is_unit1( p[1] ) ){return true;}
00138   else{return false;}
00139 };/*2dim unit test*/
00140 
00141 
00143 //bezier poly comp. fcts
00144 
00145 int binomial(int n, int p) {
00146    int n1=1;
00147    if(p!=0) {
00148 
00149      if((n-p)<p){ p=n-p;};
00150      int n2=n;
00151      for(int i=1;i<=p;i++){ n1=n1*n2/i; n2--;};
00152     }
00153  
00154     return(n1);
00155 }/*binomials*/
00156 
00157 
00158 template<class C>
00159 polynomial< C ,with<Bernstein> > bbasis(C co, int n, int deg)
00160   {
00161     polynomial< C ,with<Bernstein> > ti(co*C(binomial(n,deg)),deg,0), t("1-x0"), tj(C(1),0,0); 
00162 
00163     for(int i=0; i<n-deg; i++){ mul(tj,t); }; 
00164 
00165     mul(ti, tj);
00166     return(ti);
00167   }/*BB basis polynomials*/
00168 
00169 
00170 template<class C>
00171 void pow( polynomial< C ,with<Bernstein> > & poly, int n)
00172   {
00173     polynomial< C ,with<Bernstein> > t=poly;
00174 
00175     for(int i=1; i<n; i++){ mul(poly, t); }; 
00176   }/*nth power of a bbpoly*/
00177 
00178 
00179 
00180 template<class C>
00181 polynomial< C ,with<Bernstein> >  seq2b( Seq<C>  coeffseq )
00182   { 
00183     int n=coeffseq.size()-1;
00184     polynomial<  C ,with<Bernstein> > pol, pi;
00185 
00186     for(int i=0; i<=n; i++ ){
00187       pi=bbasis(coeffseq[i],n,i); 
00188       add( pol , pi);}
00189 
00190     return(pol);
00191   };/*coeff vector -> bbpoly*/
00192 
00193 
00194 template<class C>
00195 C pint( polynomial<  C ,with<MonomialTensor> >  poly)
00196   {
00197     int n=SIZE;
00198     C res=C(0);     
00199 
00200     for(int i=0; i<n; i++ ){
00201       res += REP[i]/C(i+1) ;}
00202 
00203     return(res);
00204   };/*poly integration on (0,1)*/
00205 
00206     
00207 template<class C>
00208 C min_coeff( polynomial< C ,with<Bernstein> > poly){
00209 
00210   C  min =REP[0];
00211 
00212   for ( unsigned i = 1; i < SIZE; i++ ){
00213     if( min > REP[i] ){ 
00214       min = REP[i];
00215     }
00216 
00217   }
00218   return min;
00219 };/*minimal coeff*/
00220 
00221 
00222 template<class C>
00223 C max_coeff( polynomial< C ,with<Bernstein> > poly){
00224 
00225   C max =REP[0];
00226 
00227   for ( unsigned i = 1; i < SIZE; i++ ){
00228     if( max < REP[i] ){ 
00229       max = REP[i];
00230     }
00231 
00232   }
00233   return max;
00234 };/*max coeff*/
00235 
00236 
00237 
00238 template<class C>
00239 C abs_max_coeff( polynomial< C ,with<Bernstein> > poly){
00240   C min =min_coeff(poly);
00241   C max =max_coeff(poly);
00242 
00243   if( max*max < min*min){ max =C(-1)*min; };
00244  
00245   return max;
00246 };/* max abs coeff*/
00247 
00248 
00249 
00250 template<class C>
00251 Seq<C> corner_values(polynomial< C ,with<Bernstein> > p){
00252   C c00,c10,c01,c11;
00253 
00254   eval( c00, p.rep(),  vec(C(0),C(0)) );
00255   eval( c10, p.rep(),  vec(C(1),C(0)) );
00256   eval( c01, p.rep(),  vec(C(0),C(1)) );
00257   eval( c11, p.rep(),  vec(C(1),C(1)) );
00258   Seq<C> cval; cval<<c00<<c10<<c01<<c11;
00259   return(cval);
00260 
00261 };
00262 
00264 //arc fcts
00265 
00266 template<class C>
00267 std::vector<C> approx(polynomial< C ,with<Bernstein> > poly , std::vector<C> ep1, std::vector<C> ep2, int MTH){
00268   polynomial< C ,with<MonomialTensor> > xt, yt, res, monp, mp("x0-x0^2");
00269   polynomial< C ,with<Bernstein> > bxt, byt; 
00270     C t, I; 
00271     Seq<C> sols;
00272     std::vector<C> movec;
00273    
00274     if (ep2.size()==0 ){movec=ep1;}
00275     else{ 
00276  tensor::assign(monp.rep(),poly.rep());
00277    
00278  Seq<C> endptsx,endptsy;
00279 
00280     endptsx<<ep2[0]<<ep1[0];
00281     endptsy<<ep2[1]<<ep1[1];
00282     bxt=seq2b(endptsx); tensor::assign(xt.rep(),bxt.rep());
00283     byt=seq2b(endptsy); tensor::assign(yt.rep(),byt.rep());
00284        
00285     Seq<polynomial< C ,with<MonomialTensor> > > param; param<<xt<<yt;
00286 
00287     tensor::eval(res, monp.rep(), param, 1);
00288   
00289 
00290    
00291   C c0,c1;
00292   tensor::eval(c0,res.rep(),C(0));
00293   tensor::eval(c1,res.rep(),C(1));
00294   mul(res,mp);
00295 
00296    I=pint(res);
00297    C u=C(15)*I-C(0.75)*(c0+c1);
00298    sols=solve2(c0+c1-C(2)*u,C(2)*(u-c0),c0);
00299  
00300 
00301    if(is_unit1(sols[0]))
00302      {t=sols[0]; movec=vec(ep1[0]*t+ep2[0]*(C(1)-t),ep1[1]*t+ep2[1]*(C(1)-t));}
00303    else if(is_unit1(sols[1]))
00304      {t=sols[1]; movec=vec(ep1[0]*t+ep2[0]*(C(1)-t),ep1[1]*t+ep2[1]*(C(1)-t));}
00305    else{movec=std::vector<C>();}
00306 
00307     }
00308  
00309    return movec;
00310   }; /*approx bivar bbpoly along line*/
00311 
00312 
00313 template<class C>
00314 arc_rep< C >  median( box_rep< C > box, Seq<std::vector<C> > list, int MTH ){
00315   std::vector<C> endp[2], mpts[3];
00316   int s=0;
00317   arc_rep<C> medc;
00318   for(int i=0; i<3; i++){mpts[i]=std::vector<C>();};
00319 
00320   
00321   mpts[0]=approx(box.poly, list[0], list[1], MTH);
00322   mpts[1]=approx(box.poly, list[2], list[3], MTH);
00323  
00324     if( mpts[0].size()!=0 && mpts[1].size()!=0 ){
00325      
00326       std::vector<C> mid, rvec, v; 
00327       mid=v_div(v_plus(mpts[0],mpts[1]),C(2));
00328       rvec=rotl(v_minus(mpts[0],mpts[1])); 
00329        C bval[4]; 
00330     
00331        if(!is_small(rvec[0])){  
00332          bval[0]=rvec[1]*C(-1)*mid[0]/rvec[0]+mid[1];
00333          bval[1]=rvec[1]*(C(1)-mid[0])/rvec[0]+mid[1];}else{ bval[0]=C(-1); bval[1]=C(-1);}
00334 
00335        if(!is_small(rvec[1])){ 
00336          bval[2]=rvec[0]*C(-1)*mid[1]/rvec[1]+mid[0];
00337          bval[3]=rvec[0]*(C(1)-mid[1])/rvec[1]+mid[0];}else{ bval[2]=C(-1); bval[3]=C(-1);}
00338    
00339        if(is_unit1(bval[0]) && s<2){endp[s]= vec(C(0),bval[0]); s++;};
00340        if(is_unit1(bval[1]) && s<2){endp[s]= vec(C(1),bval[1]); s++;};
00341        if(is_unit1(bval[2]) && s<2){endp[s]= vec(bval[2],C(0)); s++;};
00342        if(is_unit1(bval[3]) && s<2){endp[s]= vec(bval[3],C(1)); s++;};
00343        mpts[2]=mpts[1]; 
00344   
00345        if(s==2){ mpts[1]=approx(box.poly, endp[0], endp[1], MTH);}
00346 
00347        if(mpts[1].size()!=0){ medc=arc_rep<C>(mpts);}else{medc=arc_rep<C>();}
00348        //else{ for(int i=0; i<3; i++){mpts[i]= vec(C(-1),C(-1));};}
00349       
00350     }else{ medc=arc_rep<C>(); };
00351 
00352 
00353     //std::cout <<"med: "<<mpts[0]<<" "<<mpts[1]<<" "<<mpts[2]<<std::endl;
00354    
00355      return(medc);
00356      }; /*median arc computation*/
00357 
00358 
00359   template<class C>
00360   void circ_is( std::vector<C> * ispts, arc_rep<C> c1, arc_rep<C> c2){
00361 
00362     Seq<C> eh1= c1.arc_eq(), eh2= c2.arc_eq(), sx, a;    
00363     C Aeh,Ceh; 
00364    if(!is_small(eh1[1]) && !is_small(eh1[2]) && !is_small(eh2[1]) && !is_small(eh2[2])){
00365 
00366     if(is_small(eh1[0]) && is_small(eh2[0])){
00367 
00368       Aeh=(C(-1)*eh2[1])/(eh2[2]); 
00369       Ceh=(C(-1)*eh2[3])/(eh2[2]);
00370       sx[0]=(C(-1)*eh1[2]*Ceh-eh1[3])/(eh1[2]*Aeh+eh1[1]);
00371         
00372           ispts[0]=vec(sx[0],Aeh*sx[0]+Ceh);
00373           ispts[1]=vec(sx[0],Aeh*sx[0]+Ceh);
00374       }
00375     else{
00376       if(!is_small(eh1[0]) && !is_small(eh2[0])){
00377         eh1=eh1/eh1[0];
00378         eh2=eh2/eh2[0];
00379 
00380         Aeh=(eh2[1]-eh1[1])/(eh1[2]-eh2[2]);
00381         Ceh=(eh2[3]-eh1[3])/(eh1[2]-eh2[2]);}   
00382       else{
00383         if(is_small(eh1[0]) && !is_small(eh2[0])){a=eh1; eh1=eh2; eh2=a;};
00384       
00385         eh1=eh1/eh1[0];
00386 
00387         Aeh=(C(-1)*eh2[1])/(eh2[2]); 
00388         Ceh=(C(-1)*eh2[3])/(eh2[2]);};
00389  
00390 
00391 
00392       sx=solve2(C(1)+Aeh*Aeh, C(2)*Aeh*Ceh+eh1[1]+eh1[2]*Aeh, Ceh*Ceh+eh1[2]*Ceh+eh1[3]);
00393          
00394       ispts[0]=vec(sx[0],Aeh*sx[0]+Ceh);
00395       ispts[1]=vec(sx[1],Aeh*sx[1]+Ceh); 
00396     
00397     }
00398    }
00399    else{  ispts[0]=vec(C(-1),C(-1));
00400      ispts[1]=vec(C(-1),C(-1)); 
00401    };
00402 };/*cicrcle intersections (numerical behaviour!)*/
00403 
00404 
00405   template<class C>  
00406  bool is_arc(arc_rep<C> c){
00407     if( c.pts[0].size()!=0 && c.pts[1].size()!=0 && c.pts[2].size()!=0 ){return true;}
00408   else{return false;}
00409 };
00410 
00411 
00412 template<class C> 
00413  bool is_infatarc(std::vector<C> p, arc_rep<C> c1, arc_rep<C> c2){
00414   if(is_arc(c1)&&is_arc(c2)){
00415     if( crossrat(c1.pts[2],c1.pts[1],c1.pts[0],p)[1]*crossrat(c2.pts[2],c2.pts[1],c2.pts[0],p)[1]<C(0))
00416       {return true;}else{return false;}
00417   }
00418   else{return false;}
00419 };
00420 
00421 
00422 template<class C> 
00423 Seq< std::vector<C> > extpts(arc_rep<C> mc1, C r1, arc_rep<C> mc2, C r2){
00424 
00425   arc_rep<C>
00426   c1p=mc1.offset(r1),c1m=mc1.offset(C(-1)*r1),
00427   c2p=mc2.offset(r2),c2m=mc2.offset(C(-1)*r2);
00428   std::vector<C> p[2];
00429   Seq< std::vector<C> > ispts;
00430 
00431   if(is_arc(c1p) && is_arc(c2p)){ circ_is(p,c1p,c2p); if(is_unit2(p[0])){ispts<<p[0];}; if(is_unit2(p[1])){ispts<<p[1];};};
00432   if(is_arc(c1p) && is_arc(c2m)){ circ_is(p,c1p,c2m); if(is_unit2(p[0])){ispts<<p[0];}; if(is_unit2(p[1])){ispts<<p[1];};};
00433   if(is_arc(c1m) && is_arc(c2m)){ circ_is(p,c1m,c2m); if(is_unit2(p[0])){ispts<<p[0];}; if(is_unit2(p[1])){ispts<<p[1];};};
00434   if(is_arc(c1m) && is_arc(c2p)){ circ_is(p,c1m,c2p); if(is_unit2(p[0])){ispts<<p[0];}; if(is_unit2(p[1])){ispts<<p[1];};};
00435  
00436   if(is_arc(c1p) && is_infatarc(c1p.pts[0],c2m,c2p)){ispts<<c1p.pts[0];};
00437   if(is_arc(c1p) && is_infatarc(c1p.pts[2],c2m,c2p)){ispts<<c1p.pts[2];};
00438   if(is_arc(c1m) && is_infatarc(c1m.pts[0],c2m,c2p)){ispts<<c1m.pts[0];};
00439   if(is_arc(c1m) && is_infatarc(c1m.pts[2],c2m,c2p)){ispts<<c1m.pts[2];};
00440 
00441   if(is_arc(c2p) && is_infatarc(c2p.pts[0],c1m,c1p)){ispts<<c2p.pts[0];};
00442   if(is_arc(c2p) && is_infatarc(c2p.pts[2],c1m,c1p)){ispts<<c2p.pts[2];};
00443   if(is_arc(c2m) && is_infatarc(c2m.pts[0],c1m,c1p)){ispts<<c2m.pts[0];};
00444   if(is_arc(c2m) && is_infatarc(c2m.pts[2],c1m,c1p)){ispts<<c2m.pts[2];};
00445  
00446   if(is_arc(c1p) && is_infatarc(c1p.critpt(0),c2m,c2p)){ispts<<c1p.critpt(0);}; 
00447   if(is_arc(c1p) && is_infatarc(c1p.critpt(1),c2m,c2p)){ispts<<c1p.critpt(1);}; 
00448   if(is_arc(c1m) && is_infatarc(c1m.critpt(0),c2m,c2p)){ispts<<c1m.critpt(0);}; 
00449   if(is_arc(c1m) && is_infatarc(c1m.critpt(1),c2m,c2p)){ispts<<c1m.critpt(1);}; 
00450 
00451   if(is_arc(c2p) && is_infatarc(c2p.critpt(0),c1m,c1p)){ispts<<c2p.critpt(0);}; 
00452   if(is_arc(c2p) && is_infatarc(c2p.critpt(1),c1m,c1p)){ispts<<c2p.critpt(1);}; 
00453   if(is_arc(c2m) && is_infatarc(c2m.critpt(0),c1m,c1p)){ispts<<c2m.critpt(0);}; 
00454   if(is_arc(c2m) && is_infatarc(c2m.critpt(1),c1m,c1p)){ispts<<c2m.critpt(1);};
00455 
00456   
00457   Seq< std::vector<C> > cpts; cpts<<vec(C(0),C(0));cpts<<vec(C(0),C(1));cpts<<vec(C(1),C(0));cpts<<vec(C(1),C(1));
00458 
00459   for(unsigned i=0; i<cpts.size(); i++){ if( is_infatarc(cpts[i],c1m,c1p) && 
00460                                               is_infatarc(cpts[i],c2m,c2p) ){ ispts<<cpts[i]; };
00461     }; 
00462  
00463   return ispts;
00464 };
00465 
00466 template<class C> 
00467 domain<C> minmax_box(Seq<std::vector<C> > ispts, domain<C> box){
00468   domain<C> newbox=box;
00469   C minx,maxx,miny,maxy;
00470   if(ispts.size()==0){newbox=domain<C>(int(0));}else{
00471   int k=0;
00472   for(unsigned i=0; i<ispts.size(); i++){
00473       if(k==0){ minx=ispts[i][0]; maxx=ispts[i][0]; miny=ispts[i][1]; maxy=ispts[i][1]; k++;};
00474       if(ispts[i][0]>maxx){maxx=ispts[i][0];};
00475       if(ispts[i][0]<minx){minx=ispts[i][0];};
00476       if(ispts[i][1]>maxy){maxy=ispts[i][1];};
00477       if(ispts[i][1]<miny){miny=ispts[i][1];};
00478   }; 
00479 
00480   Interval<C>  Jx( minx, maxx), Jy( miny, maxy) ;
00481    if((maxx-minx)>C(0) && (maxy-miny)>C(0))
00482      { newbox= domain<C>( box.I[0].m + box.delta()[0]*Jx ,  box.I[1].m + box.delta()[1]*Jy ); };
00483   }
00484   return(newbox);
00485 };/*minmax box for the arc  intersection points and arc end points*/
00486 
00487 
00488 //end of arc_rep fcts
00489