shape_doc 0.1
/Users/mourrain/Devel/mmx/shape/include/shape/cell2d_algebraic_curve.hpp
Go to the documentation of this file.
00001 /*****************************************************************************
00002  * M a t h e m a g i x
00003  *****************************************************************************
00004  * cell2d_algebraic_curve
00005  * 2008-03-20
00006  * Julien Wintz & Bernard Mourrain
00007  *****************************************************************************
00008  *               Copyright (C) 2008 INRIA Sophia-Antipolis
00009  *****************************************************************************
00010  * Comments :
00011  ****************************************************************************/
00012 
00013 # ifndef shape_cell2d_algebraic_curve_hpp
00014 # define shape_cell2d_algebraic_curve_hpp
00015 
00016 # include <realroot/Interval.hpp>
00017 # include <realroot/polynomial_bernstein.hpp>
00018 # include <realroot/Seq.hpp>
00019 # include <shape/point.hpp>
00020 # include <shape/solver_implicit.hpp>
00021 # include <shape/cell2d.hpp>
00022 
00023 # include <stack>
00024 # define  STACK std::stack<Point*>
00025 # define TMPL template<class C, class V>
00026 # define TMPL1 template<class V>
00027 # define SELF cell2d_algebraic_curve<C,V>
00028 # define REF REF_OF(V)
00029 
00030 # undef Cell_t
00031 //====================================================================
00032 namespace mmx {
00033 namespace shape {
00034 //====================================================================
00035 // TMPL struct cell2d_algebraic_curve;
00036 
00037 // TMPL struct with_cell2d_algebraic_curve { 
00038 //   typedef cell2d_algebraic_curve<K> Cell2dAlgebraicCurve; 
00039 // };
00040 //--------------------------------------------------------------------
00045 TMPL struct cell2d_subdivisor
00046 {
00047   //  typedef polynomial< Interval<double>, with<Bernstein> > Polynomial;
00048   //  typedef polynomial< double, with<Bernstein> > Polynomial;
00049   //  typedef polynomial< mmx::GMP::rational, with<Bernstein> > Polynomial;
00050   //  typedef solver_implicit<double,with_idx<double> > Solver;
00051   
00052   template<class CELL> static void 
00053   subdivide(CELL & cl, CELL*&, CELL*&, int v, double s);
00054 };
00055 
00056 //--------------------------------------------------------------------
00057 TMPL
00058 template<class CELL> void 
00059 cell2d_subdivisor<C,V>::subdivide(CELL& cl, CELL*& left, CELL*& right, int v, double s) {
00060 
00061   typedef typename topology<C,V>::Point Point;
00062   typedef solver_implicit<C,V> Solver;
00063 
00064 
00065   double eps =Approximate().eps;
00066   if(v==0) {//direction v=0
00067        left = new CELL(cl);   left ->set_xmax(s);
00068        right= new CELL(cl);   right->set_xmin(s);
00069 
00070        //      left = new CELL(cl.m_polynomial, BoundingBox(cl.xmin(),s, cl.ymin(), cl.ymax(), cl.zmin(), cl.zmax()));
00071        //      right= new CELL(cl.m_polynomial, BoundingBox(s,cl.xmax(), cl.ymin(), cl.ymax(), cl.zmin(), cl.zmax()));
00072 
00073       tensor::split(left->m_polynomial, right->m_polynomial, v);
00074       Solver::edge_point(left->e_intersections, 
00075                          left->m_polynomial, Solver::east_edge, left->boundingBox());   
00076       right->w_intersections=left->e_intersections;
00077       left ->w_intersections=cl.w_intersections;
00078       right->e_intersections=cl.e_intersections;
00079       foreach(Point* p,cl.n_intersections) {
00080           if(p->x() < s) 
00081               left ->n_intersections << p ;
00082           else
00083               right->n_intersections << p ;
00084       }
00085       foreach(Point* p,cl.s_intersections) {
00086           if(p->x() < s) 
00087               left ->s_intersections<< p ;
00088           else
00089               right->s_intersections<< p ;
00090       }
00091 
00092       foreach(Point* p,cl.m_singular) {
00093 
00094         if(p->x() < s+eps) 
00095           left ->m_singular << p ;
00096         //      else 
00097         if(p->x() > s-eps) 
00098           right->m_singular << p ;
00099       }
00100       
00101       /*  Update neighbors  */
00102       cl.connect0(left, right);
00103       left->join0(right);
00104 
00105 
00106     } else {//direction v==1
00107         
00108       left = new CELL(cl);  left->set_ymax(s);
00109       right= new CELL(cl);  right->set_ymin(s);
00110       
00111       //left = new CELL(cl.m_polynomial, BoundingBox(cl.xmin(),cl.xmax(), cl.ymin(), s, cl.zmin(), cl.zmax()));
00112       //right= new CELL(cl.m_polynomial, BoundingBox(cl.xmin(),cl.xmax(), s, cl.ymax(), cl.zmin(), cl.zmax()));
00113       
00114       tensor::split(left->m_polynomial, right->m_polynomial, v);
00115       Solver::edge_point(left->n_intersections, 
00116                          left->m_polynomial, Solver::north_edge, left->boundingBox());   
00117       right->s_intersections=left->n_intersections;
00118       left ->s_intersections=cl.s_intersections;
00119       right->n_intersections=cl.n_intersections;
00120       foreach(Point* p,cl.w_intersections) {
00121           if(p->y() < s) 
00122               left ->w_intersections << p ;
00123           else
00124             right->w_intersections << p ;
00125       }
00126       
00127       foreach(Point* p,cl.e_intersections) {
00128           if(p->y() < s) 
00129               left ->e_intersections << p ;
00130           else
00131               right->e_intersections << p ;
00132       }
00133       
00134       foreach(Point* p,cl.m_singular) {
00135         if(p->y() < s+eps)
00136           left->m_singular << p ;
00137         //      else 
00138         if(p->y() > s-eps)
00139           right->m_singular << p ;
00140       } 
00141         
00142       foreach(Point* p,cl.m_xcritical) {
00143         if(p->y() < s+eps)
00144           left->m_xcritical << p ;
00145         //      else 
00146         if(p->y() > s-eps)
00147           right->m_xcritical << p ;
00148       } 
00149 
00150       foreach(Point* p,cl.m_ycritical) {
00151         if(p->y() < s+eps)
00152           left->m_ycritical << p ;
00153         //      else 
00154         if(p->y() > s-eps)
00155           right->m_ycritical << p ;
00156       } 
00157       
00158       /*  Update neighbors  */
00159       cl.connect1(left, right);
00160       left->join1(right);
00161 
00162     }   
00163     /* disconnect parent */
00164     cl.disconnect( );
00165 
00166 }
00167 //====================================================================
00168 template<class C, class V=default_env>
00169 struct cell2d_algebraic_curve : public cell2d<C,REF> {
00170 public:
00171   typedef topology<C,REF>    Topology;
00172   typedef typename Topology::Point          Point;
00173   //  typedef typename cell2d_algebraic_curve_def<K>::Vertex         Vertex;
00174   //  typedef typename use<cell2d_algebraic_curve_def,V>::Vector      Vector;
00175   typedef point<C,REF> Vector;
00176   typedef typename topology<C,REF>::Edge                          Edge;
00177   typedef cell<C,REF>           Cell;
00178   typedef algebraic_set<C,REF>                    AlgebraicSet;
00179   typedef algebraic_curve<C,REF>                  AlgebraicCurve;
00180   typedef polynomial< Interval<C>, with<Bernstein> > Polynomial;
00181   typedef bounding_box<C,REF>                   BoundingBox;
00182 
00183   typedef solver_implicit<C,V>                  Solver;
00184   typedef topology2d<C,V>                       Topology2d;
00185 
00186   cell2d_algebraic_curve(const Polynomial &, const BoundingBox&, bool inter=true);
00187   cell2d_algebraic_curve(const char*, const BoundingBox&);
00188   cell2d_algebraic_curve(const typename AlgebraicSet::Polynomial& , const BoundingBox&);
00189   cell2d_algebraic_curve(AlgebraicCurve*, const BoundingBox &x);
00190   cell2d_algebraic_curve(const SELF& cl)
00191     : cell2d<C,REF>(cl.boundingBox()), m_polynomial(cl.m_polynomial) {}
00192 
00193   Polynomial equation(void) { return  m_polynomial; }
00194   
00195   bool  is_active (void) ;
00196   bool  is_regular(void) ;
00197   bool  is_intersected(void) {return (this->nb_intersect()>0);};
00198 
00199   virtual Point * pair(Point * p, int & sgn) ;
00200   virtual Point * starting_point( int sgn) ;
00201 
00202   virtual bool insert_regular (Topology*);// = 0;
00203   virtual bool insert_singular(Topology*);// = 0;
00204   virtual void subdivide(Cell*& left, Cell*& right, int v, double s);
00205   Vector gradient(const Point& p);
00206 
00207 public:
00208   Polynomial        m_polynomial;
00209   Seq<Point *>      m_xcritical;
00210   Seq<Point *>      m_ycritical;
00211 //  AlgebraicCurve*   m_shape;
00212 };
00213 
00214 //====================================================================
00215 TMPL inline void 
00216 print(SELF* cv) {
00217   typedef typename SELF::Point Point;
00218   std::cout << "point(s) b: "; 
00219   foreach(Point* p, cv->n_intersections)  
00220     std::cout <<" ["<<p->x()<<" "<<p->y()<<"]";
00221   foreach(Point* p, cv->s_intersections)  
00222     std::cout <<" ["<<p->x()<<" "<<p->y()<<"]";
00223   foreach(Point* p, cv->w_intersections)  
00224     std::cout <<" ["<<p->x()<<" "<<p->y()<<"]";
00225   foreach(Point* p, cv->e_intersections)  
00226     std::cout <<" ["<<p->x()<<" "<<p->y()<<"]";
00227   std::cout<<std::endl;
00228   
00229   std::cout << "Point(s) s: "; 
00230   foreach(Point* p, cv->m_singular)  
00231     std::cout <<" ["<<p->x()<<" "<<p->y()<<"]";
00232   std::cout<<std::endl;
00233 }
00234 //--------------------------------------------------------------------
00235 TMPL
00236 SELF::cell2d_algebraic_curve(const Polynomial& pol, const BoundingBox& bx, bool inter): cell2d<C,REF>(bx), m_polynomial(pol)
00237 {
00238   //std::cout<<"Alegbraic cell: "<<bx<<std::endl;
00239   
00240   if (inter)
00241   {
00242     //std::cout<<"compute inter "<<bx<<std::endl;
00243   Solver::edge_point(this->n_intersections, m_polynomial, Solver::north_edge, bx);
00244   Solver::edge_point(this->s_intersections, m_polynomial, Solver::south_edge, bx);
00245   Solver::edge_point(this->w_intersections, m_polynomial, Solver::west_edge , bx);
00246   Solver::edge_point(this->e_intersections, m_polynomial, Solver::east_edge , bx);
00247   }
00248     //Solver::extremal(this->m_singular, m_polynomial, bx); 
00249 
00250 }
00251 //--------------------------------------------------------------------  
00252 TMPL
00253 SELF::cell2d_algebraic_curve(const typename AlgebraicSet::Polynomial& p, const BoundingBox & b): cell2d<C,REF>(b)
00254 {
00255   //std::cout<<"Alegbraic cell: "<<p<<std::endl;
00256     Seq<mmx::GMP::rational> bx;
00257     bx<<as<mmx::GMP::rational>(b.xmin());
00258     bx<<as<mmx::GMP::rational>(b.xmax());
00259     bx<<as<mmx::GMP::rational>(b.ymin());
00260     bx<<as<mmx::GMP::rational>(b.ymax());
00261     
00262       tensor::bernstein<mmx::GMP::rational> polq(p.rep(),bx);
00263 
00264       let::assign(m_polynomial.rep(),polq);
00265 
00266     Solver::edge_point(this->n_intersections, m_polynomial, Solver::north_edge, b);
00267     Solver::edge_point(this->s_intersections, m_polynomial, Solver::south_edge, b);
00268     Solver::edge_point(this->w_intersections, m_polynomial, Solver::west_edge , b);
00269     Solver::edge_point(this->e_intersections, m_polynomial, Solver::east_edge , b);
00270 
00271     Solver::extremal(this->m_singular, p, b); 
00272 
00273     // foreach(Point* p,this-> s_intersections) 
00274     //   std::cout<<"s_ boundary point: "<<p->x()<<", "<<p->y() <<std::endl;
00275     // foreach(Point* p,this-> e_intersections) 
00276     //   std::cout<<"e_ boundary point: "<<p->x()<<", "<<p->y() <<std::endl;
00277     // foreach(Point* p,this-> n_intersections) 
00278     //   std::cout<<"n_ boundary point: "<<p->x()<<", "<<p->y() <<std::endl;
00279     // foreach(Point* p,this-> w_intersections) 
00280     //   std::cout<<"w_ boundary point: "<<p->x()<<", "<<p->y() <<std::endl;
00281 
00282     // foreach(Point* p,this-> m_singular) 
00283     //   std::cout<<"extremal point: "<<p->x()<<", "<<p->y() <<std::endl;
00284 
00285     //std::cout<<"Found "<<this->nb_intersect()<<" boundary and "<<this->m_singular.size()<<" extremal points" <<std::endl;
00286   }
00287 //--------------------------------------------------------------------
00288 TMPL
00289 SELF::cell2d_algebraic_curve(const char* s, const BoundingBox & b): cell2d<C,REF>(b)
00290 {
00291     Seq<mmx::GMP::rational> bx;
00292     bx<<as<mmx::GMP::rational>(b.xmin());
00293     bx<<as<mmx::GMP::rational>(b.xmax());
00294     bx<<as<mmx::GMP::rational>(b.ymin());
00295     bx<<as<mmx::GMP::rational>(b.ymax());
00296     
00297     typename AlgebraicSet::Polynomial pol(s);
00298        tensor::bernstein<mmx::GMP::rational> polq(s,bx);
00299 
00300        let::assign(m_polynomial.rep(),polq);
00301 
00302     Solver::edge_point(this->n_intersections, m_polynomial, Solver::north_edge, b);
00303     Solver::edge_point(this->s_intersections, m_polynomial, Solver::south_edge, b);
00304     Solver::edge_point(this->w_intersections, m_polynomial, Solver::west_edge , b);
00305     Solver::edge_point(this->e_intersections, m_polynomial, Solver::east_edge , b);
00306 
00307     Solver::extremal(this->m_singular, pol, b); 
00308     foreach(Point* p,this-> m_singular) 
00309       std::cout<<"**extremal point: "<<p->x()<<" "<<p->y() <<std::endl;
00310 }
00311 //--------------------------------------------------------------------  
00312 TMPL
00313 SELF::cell2d_algebraic_curve(AlgebraicCurve* cv, const BoundingBox & b)
00314 {
00315   new (this) SELF(cv->equation(),b );
00316 }
00317 //--------------------------------------------------------------------
00318 TMPL bool 
00319 SELF::is_regular() {
00320 // Assumption: cells with extremal points (dx=dy=0) that do not belong on the curve do not intersect the curve (assumes deep enough subdivision)
00321 
00322     if(this->m_singular.size()>1) return false;
00323 
00324 //    if (0)
00325     if (this->m_singular.size()==0) {
00326       if(!has_sign_variation(m_polynomial)) return true;
00327 
00328       Polynomial dx= diff(m_polynomial,0);
00329       if(!has_sign_variation(dx)) return true;
00330 
00331       Polynomial dy= diff(m_polynomial,1);
00332       if(!has_sign_variation(dy)) return true;
00333 
00334       int n= this->nb_intersect();
00335       return   ( n==2 );
00336       //return   ( n%2==0);
00337       //return   (n == 4 || n == 2 || n == 0 );
00338     }
00339 
00340     //return true;
00341 
00342     //--------------------------------------------------------------------
00343     if(this->m_singular.size()==1) {
00344 //    Polynomial 
00345 //      dxf = diff(m_polynomial,0),
00346 //      dyf = diff(m_polynomial,1);
00347 //       std::cout<< "__________________"<<std::endl;
00348 //       std::cout<< m_polynomial;std::cout<< std::endl;
00349 //       std::cout<< "__________________"<<std::endl;
00350 //       std::cout<< dxf;std::cout<< std::endl;
00351 //       std::cout<< "__________________"<<std::endl;
00352 //       std::cout<< dyf;std::cout<< std::endl;
00353 //       std::cout<< "__________________"<<std::endl;
00354 
00355 //      int d;
00356 //      d = 1-2*topological_degree(dxf,dyf);
00357 //      d = 0;
00358       return false; //(d==ni);
00359     }    
00360     
00361     return true;
00362 }
00363 //--------------------------------------------------------------------
00364 TMPL bool 
00365 SELF::is_active() {
00366 
00367     return (has_sign_variation(this->m_polynomial));
00368 
00369 //   if(this->m_singular.size()>0) 
00370 //       return true;
00371 //     return (this->nb_intersect()>0);
00372 }
00373 //--------------------------------------------------------------------
00374 TMPL bool 
00375 SELF::insert_regular(Topology* t) {
00376     Topology2d* s= dynamic_cast<Topology2d*>(t);
00377     Seq<Point*> l;
00378     int ni, sgn(1);
00379     Point *p,*q;
00380     l= this->intersections();
00381     ni=l.size();
00382 
00383     std::cout<<"alg. curve, inserting regular "<< *this <<std::endl;
00384     foreach( Point* e, l)
00385       std::cout<<"("<< e->x()<<", "<<e->y()<<")"<<std::endl;
00386 
00387     //assert(ni%2==0);
00388 
00389     if(this->m_singular.size()==0) 
00390     {
00391       foreach(Point* v, l)
00392         s->insert(v);
00393 
00394 
00395       while (l.size()>0)
00396       {
00397         //std::cout<<"L = "<< l <<std::endl;      
00398         p= l[0];
00399         q= this->pair(p,sgn);
00400         l.erase(0);
00401         //std::cout<<"erased "<< p <<" "<<std::endl;int k=l.search(q);
00402         l.erase( l.search(q) );
00403         //std::cout<<"erased "<< q <<" ~"<<k<<std::endl;
00404         s->insert(p,q);
00405         //std::cout<<"edge "<<0<<" "<<q<<std::endl;
00406         //std::cout<<"l.size()="<<l.size() <<std::endl;
00407       }
00408     }
00409     else
00410     {
00411       //std::cout<<"Singular:"<<std::endl;    
00412       //std::cout<<this<<std::endl;    
00413       t->insert((BoundingBox*)this,false);
00414       
00415       Point *c=this->m_singular[0];
00416       s->m_specials<<c;
00417       s->insert(c);
00418       foreach(Point* p, this->n_intersections) s->insert(new Edge(p,c));
00419       foreach(Point* p, this->e_intersections) s->insert(new Edge(p,c));
00420       foreach(Point* p, this->s_intersections) s->insert(new Edge(p,c));
00421       foreach(Point* p, this->w_intersections) s->insert(new Edge(p,c));
00422     }
00423 
00424     //std::cout<<"ok "<<std::endl;
00425 
00426     return true;
00427 
00428 }
00429 //--------------------------------------------------------------------
00430 TMPL bool 
00431 SELF::insert_singular(Topology* t) {
00432 
00433 //  std::cout<<"Singular!!"<<std::endl;    
00434 
00435     //Mark singular box with a cross
00436     //t->insert((BoundingBox*)this,true);return true;
00437     
00438     Topology2d* s = dynamic_cast<Topology2d*>(t);
00439     int sgn(1);
00440 
00441     Seq<Point*> l;
00442     foreach(Point* p, this->n_intersections) {
00443         s->insert(p); l<<p;  
00444     }
00445     foreach(Point* p, this->e_intersections) {
00446       s->insert(p); l<<p;
00447     }
00448     foreach(Point* p, this->s_intersections) {
00449       s->insert(p); l<<p;
00450     }
00451     foreach(Point* p, this->w_intersections) {
00452       s->insert(p); l<<p;
00453     }
00454     int ni=l.size();
00455     
00456     if(this->m_singular.size()==1) {
00457 
00458         //std::cout<<"Singular:"<<std::endl;    
00459         //std::cout<<this<<std::endl;    
00460         //t->insert((BoundingBox*)this,false);
00461         
00462 
00463       Point *c=this->m_singular[0];
00464       s->m_specials<<c;
00465       s->insert(c);
00466       foreach(Point* p, this->n_intersections) s->insert(new Edge(p,c));
00467       foreach(Point* p, this->e_intersections) s->insert(new Edge(p,c));
00468       foreach(Point* p, this->s_intersections) s->insert(new Edge(p,c));
00469       foreach(Point* p, this->w_intersections) s->insert(new Edge(p,c));
00470       return true;
00471     }
00472     else   // no singular points in the cell
00473     {
00474         if(ni==2) { // 2 points on the boundary
00475             s->insert(l[0],l[1]);
00476             return true;
00477         }
00478         else // more than one branch in the cell
00479         {
00480             Point *p,*q;
00481             while (l.size()>0)
00482             {
00483                 p= l[0];
00484                 q= this->pair(p,sgn);
00485                 l.erase(0);
00486                 l.erase( l.search(q) );
00487                 s->insert(p,q);
00488             }
00489         }
00490     }
00491     
00492     //std::cout<<"singular cell with "<<ni<<" bpts "<<this->m_singular.size()<<" epts"<<std::endl;    
00493 
00494     return true;
00495   }
00496 
00497 //--------------------------------------------------------------------
00498 TMPL void
00499 SELF::subdivide(Cell*& Left, Cell*& Right, int v, double s) {
00500   cell2d_subdivisor<C,V>::subdivide( *this,(SELF*&)Left,(SELF*&)Right,v,s);
00501 }
00502 //--------------------------------------------------------------------
00503 TMPL  typename SELF::Vector
00504 SELF::gradient(const Point& p) {
00505   Polynomial 
00506     dx= diff(m_polynomial,0),
00507     dy= diff(m_polynomial,1);
00508   double 
00509     u0= (p[0]-this->xmin())/(this->xmax()-this->xmin()),
00510     u1= (p[1]-this->ymin())/(this->ymax()-this->ymin());
00511   Vector v;
00512   v[0] = dx(u0,u1);
00513   v[1] = dy(u0,u1);
00514   return v;
00515 }
00516 
00517 //--------------------------------------------------------------------
00518 TMPL typename SELF::Point*
00519 SELF::starting_point(int sgn) {
00520 
00521 //  std::cout<<"startingPoint.AlgCurve"<<std::endl;
00522 
00523   Seq<Point*> l, all;
00524       unsigned a;
00525       all = this->intersections();
00526 
00527       // std::cout<<this<<" , "<<a<<std::endl;
00528       // foreach(Point*p,all)
00529       //   std::cout<<p->x()<<" "<<p->y()<<" "<<p->z()<<std::endl;
00530 
00531 
00532        // if (l.size()==4) // two duplicate corners
00533        // {
00534        //   all<< l[1];
00535        //   all<< l[0];
00536        // }
00537        // else
00538        //   all=l;
00539 
00540 
00541       a   = all.size();
00542       if (a==1) return all[0];
00543 
00544       int ev(0);
00545       int u ;//position of p
00546       unsigned
00547           s=this->s_intersections.size() ,// ~0
00548           e=this->e_intersections.size() ,// ~1
00549           //n=this->n_intersections.size() ,// ~2
00550           w=this->w_intersections.size() ;// ~3
00551 
00552       u= ( 0<s   ? 0 :
00553          ( 0<s+e ? 1 :
00554          ( 0<a-w ? 2 :
00555                    3 )));
00556 
00557       int * sz = this->m_polynomial.rep().szs();
00558       int * st = this->m_polynomial.rep().str();
00559 
00560           switch (u){
00561           case 0:
00562               ev= (this->m_polynomial[0] >0 ? 1:-1);
00563          break;
00564           case 1:
00565               ev= (this->m_polynomial[(sz[0]-1)*st[0]] >0 ? 1:-1);      
00566          break;
00567           case 2:
00568               ev= (this->m_polynomial[sz[0]*sz[1]-1]>0 ? 1:-1);
00569           break;
00570           case 3:
00571               ev= (this->m_polynomial[(sz[1]-1)*st[1]] >0 ? 1:-1);
00572           break;
00573           }
00574 
00575           if    (ev*sgn>0)  {  
00576               return all[0]; 
00577           }
00578           else              {  
00579               return all[1];
00580           }
00581 }
00582 
00583 //--------------------------------------------------------------------
00584 TMPL typename SELF::Point*
00585 SELF::pair( typename SELF::Point* p, int & sgn) {
00586      // Pair: returns a neighboring point on the component (p,sgn)
00587      // The candidates are the 2 neighbor intersections of p in *this
00588 
00589       Seq<Point*> all;
00590       int a;
00591       all= this->intersections();
00592       a   = all.size();
00593       if (a==2)// regular cell with a single branch
00594          { return (all[0]==p ? all[1]: all[0]);  }
00595       if (a==1)
00596       { std::cout<<"Only 1 intersection point in "<< *this <<" (i.e."<<*all[0] <<")"<<std::endl;
00597 
00598 //  if  ( abs( l[0]->x()-this->xmin()<EPSILON) && 
00599 //        abs( l[0]->y()-this->ymin()<EPSILON) )
00600 
00601 
00602           return (p); }
00603 
00604 
00605       int
00606           s=this->s_intersections.size() ,// ~0
00607           e=this->e_intersections.size() ,// ~1
00608           //n=this->n_intersections.size() ,// ~2
00609           w=this->w_intersections.size() ;// ~3
00610       int j,k,i= all.search(p);        
00611     
00612       //if (this->is_regular() )    { 
00613       if (this->m_singular.size()==0  )    { 
00614 
00615 
00616      Vector grq, grp = this->gradient(*p);       
00617         foreach(Point* q, all)
00618             if ( q != p) 
00619             {
00620                 grq = this->gradient(*q);
00621                 if(grp[0]*grq[0]>0  && grp[1]*grq[1]>0 )
00622                     return (q);
00623             }
00624 
00625         //box has 2 or more "identical" branches
00626 
00627         //p is part of critical branch
00628 
00629        std::cout<<"...maybe pair Trouble"<< this<<std::endl; 
00630 
00631         for (int v=0;v<a;v++)
00632             for (int w=v+1;w<a;v++)
00633             {
00634                 grp= this->gradient(*all[v]);
00635                 grq= this->gradient(*all[w]);
00636                 if( grp[0]*grq[0]>0  && grp[1]*grq[1]>0 )
00637                 {
00638                     for (int u=0; u<a;u++)
00639                         if ( u!=v && u!=w && all[u]!=p )
00640                             return (all[u]);
00641                 }                
00642             }
00643         
00644         std::cout<<"empty BOX:("<<this->m_singular.size()<<",a="<<a<<")"<<this <<std::endl;         
00645         foreach(Point*v,all) {
00646             Vector gr= this->gradient(*v);
00647             //std::cout<<"("<<v->x()<<","<<v->y()<<"): ";
00648             std::cout<<(gr[0]>0?1:-1)<<","<<(gr[1]>0?1:-1) <<std::endl;
00649         }
00650         
00651         //look non-tangent direction
00652         foreach(Point* q, all)
00653             if ( q != p) 
00654             {
00655                 grq = this->gradient(*q);
00656                 if( abs(grp[0]) < 0.017)
00657                 { if (grp[1]*grq[1]>0)
00658                         return (q);
00659                 }
00660                 else if ( abs(grp[1])< 0.01)
00661                 { if (grp[0]*grq[0]>0)
00662                         return (q);
00663                 }
00664             }
00665 
00666         std::cout<<"...pair Trouble"<< this<<std::endl; 
00667 
00668 
00669 
00670      // foreach(Point* q, all)
00671      //     if ( q != p) 
00672      //     {
00673                   return (all[0]);
00674      //     }
00675     }
00676        else {//singular box
00677 
00678            //std::cout<< "SBOX: " <<this <<std::endl;
00679            //std::cout<< "      " <<all <<std::endl;
00680            //for (unsigned y=0;y<4;y++)
00681            //std::cout<<y <<": ("<<all[y]->x()<<","<<all[y]->y()<<")"<<std::endl;
00682 
00683       // Cell with 1 self-intersection
00684       int ev(0);
00685       int u, v;//side of p, ln resp.
00686       j= ( i!=0   ? i-1 : a-1 );
00687       k= ( i!=a-1 ? i+1 : 0   );
00688 
00689       //std::cout<<"j,i,k (left,p,right)="<<j <<" "<<i << " "<<k<< std::endl; 
00690 
00691       Point *ln= all[j], 
00692             *rn= all[k] ;
00693 
00694       //std::cout<<"i= "<< i<<", j=" <<j<< std::endl; 
00695       // std::cout<<"("<<a<<")"<<s<<", "<<e<<", "<<n<<", "<<w<< std::endl; 
00696 
00697       u= ( i<s   ? 0 :
00698          ( i<s+e ? 1 :
00699          ( i<a-w ? 2 :
00700                    3 )));
00701       v= ( j<s   ? 0 :
00702          ( j<s+e ? 1 :
00703          ( j<a-w ? 2 :
00704                    3 )));
00705 
00706       int * sz = this->m_polynomial.rep().szs();
00707       int * st = this->m_polynomial.rep().str();
00708 
00709           switch (u){
00710           case 0:
00711               ev= (this->m_polynomial[0] >0 ? 1:-1);
00712               if (v==0 && j%2==0) // p, ln on the same face
00713                   ev*=-1;
00714          break;
00715           case 1:
00716               ev= (this->m_polynomial[(sz[0]-1)*st[0]] >0 ? 1:-1);      
00717               if (v==1 && (j-s)%2==0) // p, ln on the same face
00718                   ev*=-1;
00719           break;
00720           case 2:
00721               ev= (this->m_polynomial[sz[0]*sz[1]-1]>0 ? 1:-1);
00722               if (v==2 && (j-s-e)%2==0) // p, ln on the same face
00723                   ev*=-1;
00724           break;
00725           case 3:
00726               ev= (this->m_polynomial[(sz[1]-1)*st[1]] >0 ? 1:-1);
00727               if (v==3 && (j-a+w)%2==0) // p, ln on the same face
00728                   ev*=-1;
00729           break;
00730           }
00731 
00732       // std::cout<<"Cell"<<this <<"("<<(sgn==1 ? "+": "-")<<")" <<std::endl;
00733       // std::cout<<"u= "<< u<<", v=" <<v<<", ev=" <<ev << std::endl; 
00734       // std::cout<<"ln= "<< ln->x()<<","<<ln->y() << std::endl; 
00735       // std::cout<<"p = "<< p->x()<<","<<p->y() << std::endl; 
00736       // std::cout<<"rn= "<< rn->x()<<","<<rn->y() << std::endl; 
00737       // if    (ev*sgn>0)  std::cout<<"result is ln"<< std::endl;
00738       // else              std::cout<<"result is rn"<< std::endl;
00739 
00740 
00741 
00742       if    (ev*sgn>0)  return ln;
00743       else              return rn;
00744       }
00745 }
00746 
00747 //====================================================================
00748 } ; // namespace shape
00749 } ; // namespace mmx
00750 # undef Solver
00751 # undef SELF
00752 # undef REF
00753 # undef TMPL
00754 # undef STACK
00755 # endif // shape_cell2d_algebraic_curve_hpp