shape_doc 0.1
/Users/mourrain/Devel/mmx/shape/include/shape/cell3d_algebraic_curve.hpp
Go to the documentation of this file.
00001 /*****************************************************************************
00002  * M a t h e m a  g i x
00003  *****************************************************************************
00004  * Cell3d for Algebraic Curve
00005  * 2008-03-20
00006  * Bernard Mourrain & Julien Wintz
00007  *****************************************************************************
00008  *               Copyright (C) 2008 INRIA Sophia-Antipolis
00009  *****************************************************************************
00010  * Comments :
00011  ****************************************************************************/
00012 
00013 # ifndef shape_cell3d_algebraic_curve_hpp
00014 # define shape_cell3d_algebraic_curve_hpp
00015 
00016 # include <realroot/Interval.hpp>
00017 # include <realroot/polynomial_bernstein.hpp>
00018 # include <realroot/Seq.hpp>
00019 # include <shape/cell3d.hpp>
00020 # include <shape/box_face.hpp>
00021 # include <shape/topology.hpp>
00022 # include <shape/algebraic_curve.hpp>
00023 # include <shape/solver_implicit.hpp>
00024 
00025 # define TMPL template<class C, class V>
00026 # define AlgebraicCurve algebraic_curve<C,V>
00027 # define SELF cell3d_algebraic_curve<C,V>
00028 
00029 //====================================================================
00030 namespace mmx { namespace shape {
00031 //====================================================================
00032 
00033 template<class C, class V= default_env>
00034 struct cell3d_algebraic_curve : public cell3d<C,V> {
00035 public:
00036 
00037     typedef topology<C,V>  Topology;
00038     typedef tpl3d<C,V>     Topology3d;
00039     typedef vertex<C,V>    Point;  
00040 
00041     typedef polynomial< double, with<Bernstein> > Polynomial;
00042 
00043     typedef cell3d<C,V>    Cell;  
00044     typedef cell3d<C,V>    Cell3d;
00045     typedef typename  Cell3d::BoundingBox  BoundingBox;
00046 
00047     typedef solver_implicit<C,V> Solver;
00048 
00049     cell3d_algebraic_curve(const SELF&);
00050     cell3d_algebraic_curve(const Seq<Polynomial>&, const BoundingBox& );
00051     cell3d_algebraic_curve(AlgebraicCurve *, const BoundingBox& bx);
00052 
00053     bool is_regular(void);
00054     bool is_active (void) const;
00055 
00056     virtual bool is_intersected (void) {return true;}
00057 
00058     template<class TOPOLOGY>
00059     bool inserted_regular_in(TOPOLOGY*) ;
00060 
00061     template<class TOPOLOGY> 
00062     bool inserted_singular_in(TOPOLOGY*) ;
00063 
00064     virtual bool insert_regular (Topology*) ;
00065     virtual bool insert_singular(Topology*) ;
00066 
00067     virtual void polygonise (Topology3d*) {};
00068 
00069     virtual int  subdivide(SELF*& left, SELF*& right) ;
00070     virtual void subdivide(Cell*& left, Cell*& right, int v, double s);
00071 
00072     int nbeq() const { return m_polynomials.size(); }
00073     Polynomial equation(int i=0) const { return  m_polynomials[i]; }
00074 
00075     struct along {
00076       int m_dir;
00077       along(int i):m_dir(i) {}
00078       bool operator()(Point *p1, Point* p2) {
00079         return (*p1)[m_dir]<(*p2)[m_dir];
00080       }
00081     };
00082 
00083   bool topology_regular(Topology*) { return true;}
00084     //    void check_cluster(Seq<Point*>& , double eps=0.00001);
00085     void check_insert (Point*, Seq<Point*>& , double eps=0.00001);
00086 
00087   public:
00088     Seq<Polynomial>   m_polynomials;
00089     AlgebraicCurve*   m_shape;
00090     int               m_reg;
00091 };
00092   
00093 //====================================================================
00094 TMPL
00095 SELF::cell3d_algebraic_curve(const SELF& c): 
00096   m_polynomials(c.m_polynomials), m_shape(c.m_shape), m_reg(-1)  {};
00097     
00098 TMPL
00099 SELF::cell3d_algebraic_curve(const Seq<Polynomial>& s, const BoundingBox& b): 
00100   Cell3d(b), m_polynomials(s), m_reg(-1)
00101 {
00102 
00103 }
00104   
00105 TMPL
00106 SELF::cell3d_algebraic_curve(AlgebraicCurve* cv, const BoundingBox& b): Cell3d(b), m_reg(-1) {
00107     Seq<mmx::GMP::rational> bx;
00108     bx<<as<mmx::GMP::rational>(b.xmin());
00109     bx<<as<mmx::GMP::rational>(b.xmax());
00110     bx<<as<mmx::GMP::rational>(b.ymin());
00111     bx<<as<mmx::GMP::rational>(b.ymax());
00112     bx<<as<mmx::GMP::rational>(b.zmin());
00113     bx<<as<mmx::GMP::rational>(b.zmax());
00114     
00115     Polynomial tmp;
00116     for(int i=0;i<cv->nbequation();i++) {
00117       tensor::bernstein<mmx::GMP::rational> polq(cv->equation(i).rep(),bx);
00118       let::assign(tmp.rep(),polq);
00119       m_polynomials<<tmp;
00120     }
00121 
00122     Solver::face_point(this->m_boundary, m_polynomials, Solver::north_face, b);
00123     Solver::face_point(this->m_boundary, m_polynomials, Solver::south_face, b);
00124     Solver::face_point(this->m_boundary, m_polynomials, Solver::west_face , b);
00125     Solver::face_point(this->m_boundary, m_polynomials, Solver::east_face , b);
00126     Solver::face_point(this->m_boundary, m_polynomials, Solver::front_face, b);
00127     Solver::face_point(this->m_boundary, m_polynomials, Solver::back_face , b);
00128 
00129     foreach(Point* p, this->m_boundary) std::cout<<"n "<<p->x()<<" "<<p->y()<<" "<<p->z() <<std::endl;
00130 
00131     //    check_cluster(this->m_boundary);
00132     //     Solver::singular(m_singular, m_polynomial, b); 
00133   }
00134 
00135   TMPL bool 
00136   SELF::is_active() const {
00137     //    std::cout<<"Is active "<<m_polynomials[0].rep()<<std::endl;
00138 
00139     if(!has_sign_variation(m_polynomials[0])) 
00140       return false;
00141 
00142     //    std::cout<<"Is active "<<m_polynomials[1]<<std::endl;
00143 
00144     if(!has_sign_variation(m_polynomials[1]))
00145       //m_polynomials[1].begin(),m_polynomials[1].end())) 
00146       return false;
00147 
00148        //    std::cout<<"Is active end"<<std::endl;
00149     
00150     return true; 
00151   }
00152 
00153   TMPL bool 
00154   SELF::is_regular() {
00155     if(this->m_singular.size()>1) return false;
00156 
00157     Polynomial 
00158       tx=diff(equation(0),1)*diff(equation(1),2)-diff(equation(1),1)*diff(equation(0),2);
00159     if(!has_sign_variation(tx)) 
00160       { m_reg=0; return true; }
00161     
00162     Polynomial 
00163         ty=diff(equation(0),0)*diff(equation(1),2)-diff(equation(1),0)*diff(equation(0),2);
00164     if(!has_sign_variation(ty)) 
00165       { m_reg=1; return true; }
00166     
00167     Polynomial 
00168       tz=diff(equation(0),0)*diff(equation(1),1)-diff(equation(1),0)*diff(equation(0),1);
00169     if(!has_sign_variation(tz)) 
00170       { m_reg=2; return true; }
00171 
00172     //    int n=this->m_boundary.size();
00173     //    if(n > 2) 
00174     return false;
00175     //    else {
00176     //      return true;
00177     //    }
00178   }
00179   //--------------------------------------------------------------------
00180   TMPL int
00181   SELF::subdivide(SELF*& Left, SELF*& Right) {
00182     int v; double s;
00183     this->split_position(v,s);
00184     this->subdivide((Cell*&)Left,(Cell*&)Right,v,s);
00185     return v;
00186   }
00187   //--------------------------------------------------------------------
00188   TMPL void
00189   SELF::subdivide(Cell*& Left, Cell*& Right, int v, double c) {
00190 
00191     SELF * left, * right;
00192    //  if (this->m_boundary.size()>2){
00193 //       std::cout<<"             split cell with "<<this->m_boundary.size()<<" points"<<std::endl;
00194 //       foreach(Point* p, this->m_boundary)
00195 //      std::cout<<" "<<p->x()<<" "<<p->y()<<" "<<p->z()<<std::endl;
00196 //     }
00197     if(v==0){
00198       c=(this->xmin()+this->xmax())/2;
00199       left = new SELF(m_polynomials, BoundingBox(this->xmin(),c, this->ymin(),this->ymax(), this->zmin(),this->zmax()));
00200       right= new SELF(m_polynomials, BoundingBox(c,this->xmax(), this->ymin(),this->ymax(), this->zmin(),this->zmax()));
00201     } else if(v==1) {
00202       c=(this->ymin()+this->ymax())/2;
00203       left = new SELF(m_polynomials, BoundingBox(this->xmin(),this->xmax(), this->ymin(),c, this->zmin(),this->zmax()));
00204       right= new SELF(m_polynomials, BoundingBox(this->xmin(),this->xmax(), c,this->ymax(), this->zmin(),this->zmax()));
00205     } else {
00206       c=(this->zmin()+this->zmax())/2;
00207       left = new SELF(m_polynomials, BoundingBox(this->xmin(),this->xmax(), this->ymin(),this->ymax(), this->zmin(),c));
00208       right= new SELF(m_polynomials, BoundingBox(this->xmin(),this->xmax(), this->ymin(),this->ymax(), c,this->zmax()));
00209     }
00210 
00211     for(int i=0;i<nbeq();i++) {
00212       tensor::split(left->m_polynomials[i], right->m_polynomials[i], v);
00213     }
00214 
00215     if(v==0) {
00216       foreach(Point* p, this->m_boundary) {
00217         if (Solver::east_face.is_valid(*p,left->boundingBox())) 
00218           left->m_boundary << p ;
00219         if (Solver::west_face.is_valid(*p,right->boundingBox())) 
00220           right->m_boundary << p ;
00221       }
00222     } else if (v==1) {
00223       foreach(Point* p, this->m_boundary) {
00224         if (Solver::north_face.is_valid(*p,left->boundingBox())) 
00225           left->m_boundary << p ;
00226         if (Solver::south_face.is_valid(*p,right->boundingBox())) 
00227           right->m_boundary << p ;
00228       }
00229     } else {
00230       foreach(Point* p, this->m_boundary) {
00231         if (Solver::front_face.is_valid(*p,left->boundingBox())) 
00232           left->m_boundary << p ;
00233         if (Solver::back_face.is_valid(*p,right->boundingBox())) 
00234           right->m_boundary << p ;
00235       }
00236     }
00237 
00238  
00239 
00240     Seq<Point*> tmp;
00241     // Points on vertical faces of back subcells
00242     if(v==0){
00243       Solver::face_point(tmp, left->m_polynomials, Solver::east_face, left->boundingBox());   
00244       foreach(Point *p, tmp){
00245         check_insert(p, left->m_boundary);
00246         check_insert(p, right->m_boundary);
00247       }
00248     } else if(v==1) {
00249       Solver::face_point(tmp, left->m_polynomials, Solver::north_face, left->boundingBox());   
00250       foreach(Point *p, tmp){
00251         check_insert(p, left->m_boundary);
00252         check_insert(p, right->m_boundary);
00253       }
00254     } else {
00255       Solver::face_point(tmp, left->m_polynomials, Solver::front_face, left->boundingBox());   
00256       foreach(Point *p, tmp){
00257         check_insert(p, left->m_boundary);
00258         check_insert(p, right->m_boundary);
00259       }
00260     }
00261 //  if (tmp.size()>0){
00262 //       std::cout<<"      insert  "<<tmp.size()<<" points"<<std::endl;
00263 //       foreach(Point* p, tmp)
00264 //      std::cout<<"            "<<p->x()<<" "<<p->y()<<" "<<p->z()<<std::endl;
00265 //     }
00266 //     if (left->m_boundary.size()>2){
00267 //       std::cout<<"["<<left->xmin()<<" "<<left->xmax()<<" "<<left->ymin()<<" "<<left->ymax()<<" "<<left->zmin()<<" "<<left->zmax()<<"]"<<std::endl;
00268 //       std::cout<<"      left cell with "<<left->m_boundary.size()<<" points"<<std::endl;
00269 //       foreach(Point* p, left->m_boundary)
00270 //      std::cout<<"            "<<p->x()<<" "<<p->y()<<" "<<p->z()<<std::endl;
00271 //     }
00272 //     if (right->m_boundary.size()>2){
00273 //       std::cout<<"      right cell with "<<right->m_boundary.size()<<" points"<<std::endl;
00274 //       std::cout<<"["<<right->xmin()<<" "<<right->xmax()<<" "<<right->ymin()<<" "<<right->ymax()<<" "<<right->zmin()<<" "<<right->zmax()<<"]"<<std::endl;
00275 //       foreach(Point* p, right->m_boundary)
00276 //      std::cout<<"            "<<p->x()<<" "<<p->y()<<" "<<p->z()<<std::endl;
00277 //     }
00278     //    left ->m_boundary<<tmp;
00279     //    right->m_boundary<<tmp;
00280 
00281    
00282     Left=left; Right=right;
00283   }
00284 
00285   //--------------------------------------------------------------------
00286   TMPL template<class TOPOLOGY> bool SELF::inserted_regular_in(TOPOLOGY* t) {
00287 
00288     typedef typename TOPOLOGY::Edge Edge; 
00289     if(this->m_boundary.size()==0) return true;
00290 
00291 //     if(this->m_boundary.size()==1) { 
00292 //       std::cout<<"cell with 1 boundary point with reg "<<m_reg<<std::endl;      //      return false;
00293 //     }
00294     if(this->m_boundary.size()==2) {
00295       t->insert(this->m_boundary[0]); 
00296       t->insert(this->m_boundary[1]); 
00297       t->insert(new Edge(this->m_boundary[0],this->m_boundary[1])); 
00298     } else {
00299       //      std::cout<<"cell with "<<this->m_boundary.size()<<" boundary points with reg "<<m_reg<<std::endl;
00300       BoundingBox bx=*this;
00301       //      std::cout<<"["<<bx.xmin()<<" "<<bx.xmax()<<" "<<bx.ymin()<<" "<<bx.ymax()<<" "<<bx.zmin()<<" "<<bx.zmax()<<"]"<<std::endl;
00302 
00303       std::sort(this->m_boundary.begin(), this->m_boundary.end(), along(m_reg) );
00304 
00305       foreach(Point* p, this->m_boundary) t->insert(p);
00306       
00307       for(unsigned i=0;i<this->m_boundary.size();i++) {
00308         unsigned j=i+1, i0=i;
00309         //      std::cout<<"i0 "<<i<<" "<<j<<std::endl;
00310         for(j=i+1; j<this->m_boundary.size() 
00311               && (this->m_boundary[i0] == this->m_boundary[j]);i++, j++) ;
00312         if(j<this->m_boundary.size())
00313           t->insert(new Edge( this->m_boundary[i0], this->m_boundary[j])); 
00314         //      std::cout<<"i0 "<<i<<" "<<j<<std::endl;
00315       }
00316     }
00317 
00318     return true; 
00319   }
00320 //--------------------------------------------------------------------
00321 TMPL bool SELF::insert_regular(Topology* t) {
00322   return this->inserted_regular_in<Topology>(t);
00323 }
00324 //--------------------------------------------------------------------
00325 //this insert_singular is used for detecting the singularities in the computed topology from tpl3d
00326 TMPL template<class TOPOLOGY> bool SELF::inserted_singular_in(TOPOLOGY* t) { 
00327   if(this->m_boundary.size()>0) { 
00328     t->insert((BoundingBox *)this);
00329     foreach(Point* p, this->m_boundary)
00330       t->insert(p);
00331   }       
00332   return true; 
00333 } 
00334 //--------------------------------------------------------------------
00335 TMPL bool SELF::insert_singular(Topology* t) { 
00336   return this->inserted_singular_in<Topology>(t);
00337 }
00338 //--------------------------------------------------------------------
00339 //  TMPL void
00340 //   SELF::check_cluster(Seq<Point*>& l, double eps) {
00341 //     //    Seq<Point*> res;
00342 //     for(unsigned i=0; i<l.size(); i++) {
00343 //       unsigned j=0;
00344 //       for(j=0; j<i && distance(*l[j],*l[i])>eps;j++) ;
00345 //       if(j<i) l[j]=l[i];
00346 //     }
00347 //   } 
00348 
00349   TMPL void
00350   SELF::check_insert(Point* p, Seq<Point*>& l, double eps) {
00351     //    l<<p; return ;
00352     unsigned i=0;
00353     for(i=0; i<l.size() && distance(*l[i],*p)>eps; i++) ;
00354     if(i==l.size()) l<<p;
00355   }
00356 
00357 
00358 } ; // namespace shape
00359 } ; // namespace mmx
00360 
00361 # undef TMPL
00362 # undef Point
00363 # undef Cell
00364 # undef AlgebraicCurve 
00365 # undef SELF
00366 # undef Solver 
00367 # endif // SHAPE_IMPLICITCELL_H