shape_doc 0.1
/Users/mourrain/Devel/mmx/shape/include/shape/solver_implicit.hpp
Go to the documentation of this file.
00001 /*****************************************************************************
00002  * M a t h e m a  g i x
00003  *****************************************************************************
00004  * solver_implicit
00005  * 2008-11-09
00006  * Bernard Mourrain
00007  *****************************************************************************
00008  *               Copyright (C) 2008 INRIA Sophia-Antipolis
00009  *****************************************************************************
00010  * Comments :
00011  ****************************************************************************/
00012 #ifndef shape_implicit_solver_hpp
00013 #define shape_implicit_solver_hpp
00014 //===========================================================================
00015 # include <realroot/Interval.hpp>
00016 # include <realroot/polynomial_bernstein.hpp>
00017 # include <realroot/GMP.hpp>
00018 # include <realroot/solver_uv_sleeve.hpp>
00019 # include <realroot/solver_mv_bernstein.hpp>
00020 # include <shape/point.hpp>
00021 # include <shape/bounding_box.hpp>
00022 # include <shape/box_face.hpp>
00023 # include <shape/topological_degree.hpp>
00024 
00025 # define TMPL template<class C, class V>
00026 # define SELF solver_implicit<C,V>
00027 
00028 //====================================================================
00029 namespace mmx { namespace shape {
00030 //====================================================================
00031 
00032 inline double lower(double x){return x;}
00033 inline double upper(double x){return x;}
00034 
00035 template<class S1, class S2>
00036 point<double>* point_on_edge(const bounding_box<double>& bx, double u, const S1& s1, const S2& s2)  
00037 {
00038   typedef point<double> Point;
00039   double p[3];
00040   p[S1::var] = S1::eval(bx);
00041   p[S2::var] = S2::eval(bx);
00042   int v= 3-S1::var-S2::var;
00043   p[v]= lower(bx,v)*(1-u) + upper(bx,v)*u;
00044   
00045   return new Point(p[0],p[1],p[2]);
00046   //    delete p;
00047 }
00048 //--------------------------------------------------------------------
00049 TMPL struct solver_implicit {
00050 
00051   typedef REF_OF(V) Ref;
00052   typedef vertex<C,V> Point; 
00053   typedef bounding_box<C,Ref>     BoundingBox;
00054   typedef box_face<C,Ref>           BoxFace;
00055     
00056   static  BoxFace north_edge;
00057   static  BoxFace south_edge;
00058   static  BoxFace west_edge;
00059   static  BoxFace east_edge;
00060   static  BoxFace front_edge;
00061   static  BoxFace back_edge;
00062 
00063   static  BoxFace north_back_edge;
00064   static  BoxFace south_back_edge;
00065   static  BoxFace west_back_edge;
00066   static  BoxFace east_back_edge;
00067   
00068   static  BoxFace north_front_edge;
00069   static  BoxFace south_front_edge;
00070   static  BoxFace west_front_edge;
00071   static  BoxFace east_front_edge;
00072   
00073   static  BoxFace north_west_edge;
00074   static  BoxFace south_west_edge;
00075   static  BoxFace north_east_edge;
00076   static  BoxFace south_east_edge;
00077 
00078   static  BoxFace north_face;
00079   static  BoxFace south_face;
00080   static  BoxFace west_face;
00081   static  BoxFace east_face;
00082   static  BoxFace front_face;
00083   static  BoxFace back_face;
00084   
00085   static inline Point* new_point(double a, double b, double c) {
00086     return new Point(a,b,c);
00087   }
00088   
00089   //--------------------------------------------------------------------
00090   template<class MultivariateDenseBernstein> static
00091   void edge_point(Seq<Point *>& lp, 
00092                   const MultivariateDenseBernstein & p, 
00093                   const BoxFace & E,  
00094                   const BoundingBox & bx) {
00095       MultivariateDenseBernstein f;
00096 
00097       tensor::face(f,p,E.cvar(0),E.side(0));
00098 
00099       polynomial<double, with<Bernstein> > dw(1,f.size()-1), up(1,f.size()-1);
00100       for(unsigned i=0; i<f.size();i++) {
00101         up[i]= upper(f[i]); 
00102         dw[i]= lower(f[i]);
00103       }
00104 
00105       double 
00106         U = E.lower(bx),
00107         V = E.upper(bx);
00108 
00109       Seq<double> sol;
00110       solver< double, Sleeve<Approximate> >::solve(sol,dw,up,U,V);
00111 
00112       // std::cout<<"****U= "<<U<<std::endl;
00113       // std::cout<<"****V= "<<V<<std::endl;
00114       // std::cout<<"***dw= "<<dw<<std::endl;
00115       // std::cout<<"***up= "<<up<<std::endl;
00116       // std::cout<<"******Sols : "<<sol.size()<<std::endl;
00117 
00118       Approximate approx;
00119       std::vector<double> pt(3);
00120       for(unsigned i=0;i<sol.size(); i++) 
00121         if(E.is_valid(bx, sol[i], approx.eps)) {
00122           lp<< E.new_point(bx,sol[i]);
00123         }
00124     }
00125   //--------------------------------------------------------------------
00126   template<class MultivariateDenseBernstein> static
00127   int edge_sign_var(const MultivariateDenseBernstein & p, 
00128                     const BoxFace & E) {
00129       MultivariateDenseBernstein f;
00130       tensor::face(f,p,E.cvar(0),E.side(0));
00131       return sign_variation(f.begin(), f.end());
00132 
00133   }
00134   //--------------------------------------------------------------------
00135   template<class MultivariateDenseBernstein> static
00136   void face_point(Seq<Point *>& sol, 
00137                   const Seq<MultivariateDenseBernstein>& eqs, 
00138                   const BoxFace& F,
00139                   const BoundingBox& bx) {
00140       
00141       typedef polynomial< double, with<Bernstein> > Polynomial;
00142 
00143       Polynomial f, p;
00144       Seq<Polynomial> sys;
00145       for(unsigned i=0;i< eqs.size(); i++) {
00146         let::assign(p.rep(), eqs[i].rep());
00147         tensor::face(f.rep(), p.rep(), F.cvar(0), F.side(0));
00148         sys<<f;
00149       }
00150 
00151       solver<double, ProjRd<SBD_RDRDL> > slv;
00152       std::vector<double> res; 
00153       slv.solve_bernstein(res,sys);
00154       Approximate approx;
00155 
00156       for(int i=0;i<(int)res.size()-1;i+=2) {
00157 
00158 //      if (res[i]<approx.eps) res[i]=0;
00159 //      else if (res[i]>1-approx.eps) res[i]=1;
00160 
00161 //      if (res[i+1]<approx.eps) res[i+1]=0;
00162 //      else if (res[i+1]>1-approx.eps) res[i+1]=1;
00163 
00164         Point * p = F.new_point(bx, res[i], res[i+1]);
00165         if (F.is_valid(*p, bx))  sol<< p;
00166         //      else delete p;
00167       }
00168     }
00169   //--------------------------------------------------------------------
00170   template<class Polynomial>
00171   static void intersection(Seq<Point* >& sol, 
00172                            const Polynomial& f1, 
00173                            const Polynomial& f2, const BoundingBox & bx) {
00174 
00175       typedef polynomial< double, with<Bernstein> > MultivariateDenseBernstein;
00176       MultivariateDenseBernstein p1, p2;
00177 
00178       
00179       let::assign(p1.rep(), f1.rep() );
00180       let::assign(p2.rep(), f2.rep() );
00181       
00182       Seq<MultivariateDenseBernstein> sys;
00183       sys<<p1<<p2;
00184 
00185       solver<double, ProjRd<SBD_RDRDL> > slv;
00186       std::vector<double> res; 
00187       slv.solve_bernstein(res,sys);
00188 
00189       double x_sc= (bx.xmax()-bx.xmin()), y_sc= (bx.ymax()-bx.ymin());
00190       for(unsigned i=0;i<res.size();i+=2)
00191         {
00192           sol << new_point(bx.xmin()+res[i]*x_sc, bx.ymin()+res[i+1]*y_sc, 0.0);
00193         }
00194     }
00195   //--------------------------------------------------------------------
00196   template<class Polynomial>
00197   static void extremal(Seq<Point* >& sol, 
00198                        const Polynomial& pol, const BoundingBox& b) {
00199     
00200       typedef polynomial< double, with<Bernstein> >  MultivariateDenseBernstein;
00201 
00202       // typedef Polynomial MultivariateDenseBernstein;
00203 
00204 
00205       typedef polynomial< GMP::rational, with<Bernstein> > MultivariateDenseBernsteinQ;
00206       
00207       Seq<mmx::GMP::rational> bx;
00208       bx<<as<mmx::GMP::rational>(b.xmin());
00209       bx<<as<mmx::GMP::rational>(b.xmax());
00210       bx<<as<mmx::GMP::rational>(b.ymin());
00211       bx<<as<mmx::GMP::rational>(b.ymax());
00212 
00213 
00214       //tensor::bernstein<mmx::GMP::rational> P(pol.rep(),bx);
00215       //typename Polynomial::Scalar mx = as<typename Polynomial::Scalar>(array::max_abs(P));
00216       //Polynomial Pol=pol/mx, dxpol = diff(Pol,0), dypol = diff(Pol,1);
00217 
00218       Polynomial dxpol = diff(pol,0), dypol = diff(pol,1);
00219       tensor::bernstein<mmx::GMP::rational>
00220          dxP(dxpol.rep(),bx),dyP(dypol.rep(),bx);
00221       
00222       MultivariateDenseBernstein dxp,dyp;
00223       let::assign(dxp.rep(), dxP);
00224       let::assign(dyp.rep(), dyP);
00225 
00226       Seq<MultivariateDenseBernstein> sys;
00227       //      Seq<MultivariateDenseBernsteinQ> sys;
00228       sys<<dxp<<dyp;
00229 
00230       solver<double, ProjRd<SBD_RDRDL> > slv;
00231 
00232       std::vector<double> res; 
00233       slv.solve_bernstein(res,sys);
00234 
00235       double x_sc= (b.xmax()-b.xmin()), y_sc= (b.ymax()-b.ymin());
00236       for(unsigned i=0;i<res.size();i+=2) {
00237         sol << new_point(b.xmin()+res[i]*x_sc, b.ymin()+res[i+1]*y_sc, 0.0);
00238       }
00239     }
00240   //--------------------------------------------------------------------
00241   template<class Polynomial>
00242   static void singular(Seq<Point* >& sol, 
00243                        const Polynomial& pol, const BoundingBox& b) {
00244 
00245       typedef polynomial< double, with<Bernstein> >        MultivariateDenseBernstein;
00246       typedef polynomial< GMP::rational, with<Bernstein> > MultivariateDenseBernsteinQ;
00247       
00248       Seq<mmx::GMP::rational> bx;
00249       bx<<as<mmx::GMP::rational>(b.xmin());
00250       bx<<as<mmx::GMP::rational>(b.xmax());
00251       bx<<as<mmx::GMP::rational>(b.ymin());
00252       bx<<as<mmx::GMP::rational>(b.ymax());
00253 
00254       Polynomial dxpol = diff(pol,0), dypol = diff(pol,1);
00255       tensor::bernstein<mmx::GMP::rational>
00256          P(pol.rep(),bx), dxP(dxpol.rep(),bx),dyP(dypol.rep(),bx);
00257       
00258       MultivariateDenseBernstein p,dxp,dyp;
00259       let::assign(p.rep()  , P);
00260       let::assign(dxp.rep(), dxP);
00261       let::assign(dyp.rep(), dyP);
00262 
00263       Seq<MultivariateDenseBernstein> sys;
00264       sys<<p<<dxp<<dyp;
00265 
00266       solver<double, ProjRd<SBD_RDRDL> > slv;
00267       //      solver<ring<double,Bernstein>, ProjRd<SBD_RDRDL> >::eps=1e-10;
00268 
00269       std::vector<double> res; 
00270       slv.solve_bernstein(res,sys);
00271 
00272       double x_sc= (b.xmax()-b.xmin()), y_sc= (b.ymax()-b.ymin());
00273       for(unsigned i=0;i<res.size();i+=2) {
00274         sol << new_point(b.xmin()+res[i]*x_sc, b.ymin()+res[i+1]*y_sc, 0.0);
00275       }
00276     }
00277 
00278   //--------------------------------------------------------------------
00279   template<class MultivariateDenseBernstein> static
00280   void common_edge_point(Seq<Point *>& lp, 
00281                          const MultivariateDenseBernstein & p, 
00282                          const BoxFace & E,  
00283                          const BoundingBox & bx1, 
00284                          const BoundingBox & bx2 ) {
00285       MultivariateDenseBernstein f;
00286 
00287       tensor::face(f,p,E.cvar(0),E.side(0));
00288 
00289       polynomial<double, with<Bernstein> > dw(1,f.size()-1), up(1,f.size()-1);
00290       for(unsigned i=0; i<f.size();i++) {
00291         up[i]= upper(f[i]); 
00292         dw[i]= lower(f[i]);
00293            //up[i]=dw[i]=f[i];
00294       }
00295 
00296       double 
00297         U = std::max( E.lower(bx1), E.lower(bx2) ) ,
00298         V = std::min( E.upper(bx1), E.upper(bx2) ) ;
00299 
00300       Seq<double> sol;
00301 
00302       solver< double, Sleeve<Approximate> >::solve(sol,dw,up,U,V);
00303 
00304       sol.sort();// sort from smaller to bigger
00305 
00306       Approximate approx;
00307       for(unsigned i=0;i<sol.size(); i++) 
00308           {
00309             lp<< E.new_point(bx1,sol[i]);
00310           }  
00311     }
00312 };
00313 //====================================================================
00314 # define REF REF_OF(V)
00315 TMPL box_face<C,REF> SELF::north_face(1,1);
00316 TMPL box_face<C,REF> SELF::south_face(1,0);
00317 TMPL box_face<C,REF> SELF::west_face (0,0);
00318 TMPL box_face<C,REF> SELF::east_face (0,1);
00319 TMPL box_face<C,REF> SELF::front_face(2,1);
00320 TMPL box_face<C,REF> SELF::back_face(2,0);
00321 
00322 // 2D box  edges;
00323 TMPL box_face<C,REF> SELF::north_edge(1,1,2,0);
00324 TMPL box_face<C,REF> SELF::south_edge(1,0,2,0);
00325 TMPL box_face<C,REF> SELF::west_edge(0,0,2,0);
00326 TMPL box_face<C,REF> SELF::east_edge(0,1,2,0);
00327   
00328 TMPL box_face<C,REF> SELF::front_edge(2,1,0,0);
00329 TMPL box_face<C,REF> SELF::back_edge (2,0,0,0);
00330   
00331   // 3D box  edges;
00332 TMPL box_face<C,REF> SELF::north_back_edge (1,1,2,0);
00333 TMPL box_face<C,REF> SELF::south_back_edge (1,0,2,0);
00334 TMPL box_face<C,REF> SELF::west_back_edge  (0,0,2,0);
00335 TMPL box_face<C,REF> SELF::east_back_edge  (0,1,2,0);
00336   
00337 TMPL box_face<C,REF> SELF::north_front_edge(1,1,2,1);
00338 TMPL box_face<C,REF> SELF::south_front_edge(1,0,2,1);
00339 TMPL box_face<C,REF> SELF::west_front_edge (0,0,2,1);
00340 TMPL box_face<C,REF> SELF::east_front_edge (0,1,2,1);
00341   
00342 TMPL box_face<C,REF> SELF::north_west_edge (0,0,1,1);
00343 TMPL box_face<C,REF> SELF::south_west_edge (0,0,1,0);
00344 TMPL box_face<C,REF> SELF::north_east_edge (0,1,1,1);
00345 TMPL box_face<C,REF> SELF::south_east_edge (0,1,1,0);
00346   
00347 //===========================================================================
00348 } //namespace shape
00349 } //namespace mmx
00350 
00351 # undef TMPL
00352 # undef SELF
00353 # undef REF
00354 # undef BoxFace
00355 # endif //shape_implicit_solver