00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 # ifndef shape_bcell2d_algebraic_curve_hpp
00013 # define shape_bcell2d_algebraic_curve_hpp
00014
00015 # include <realroot/Interval.hpp>
00016 # include <realroot/ring_bernstein_tensor.hpp>
00017 # include <realroot/Seq.hpp>
00018 # include <shape/point.hpp>
00019 # include <shape/solver_implicit.hpp>
00020 # include <shape/bcell2d.hpp>
00021 # include <shape/algebraic_curve.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 bcell2d_algebraic_curve<C,V>
00028 # define REF REF_OF(V)
00029
00030 # undef Cell_t
00031
00032 namespace mmx { namespace shape {
00033
00038 TMPL struct bcell2d_subdivisor
00039 {
00040
00041
00042
00043
00044
00045 template<class CELL> static void
00046 subdivide(CELL & cl, CELL*&, CELL*&, int v, double s);
00047 };
00048
00049
00050 TMPL
00051 template<class CELL> void
00052 bcell2d_subdivisor<C,V>::subdivide(CELL& cl, CELL*& left, CELL*& right, int v, double s) {
00053
00054 typedef typename topology<C,V>::Point Point;
00055 typedef solver_implicit<C,V> Solver;
00056
00057
00058 double eps =Approximate().eps;
00059 if(v==0) {
00060 left = new CELL(cl); left ->set_xmax(s);
00061 right= new CELL(cl); right->set_xmin(s);
00062
00063 tensor::split(left->m_polynomial, right->m_polynomial, v);
00064 if (left->e_intersections.size() == 0)
00065 Solver::edge_point(left->e_intersections,
00066 left->m_polynomial, Solver::east_edge, left->boundingBox());
00067 right->w_intersections=left->e_intersections;
00068 left ->w_intersections=cl.w_intersections;
00069 right->e_intersections=cl.e_intersections;
00070 foreach(Point* p,cl.n_intersections) {
00071 if (p->x() == s) {
00072 left ->n_intersections<< p ;
00073 right->n_intersections<< p ;
00074 } else if(p->x() < s)
00075 left ->n_intersections << p ;
00076 else
00077 right->n_intersections << p ;
00078 }
00079
00080 foreach(Point* p,cl.s_intersections) {
00081 if (p->x() == s) {
00082 left ->s_intersections<< p ;
00083 right->s_intersections<< p ;
00084 } else if(p->x() < s)
00085 left ->s_intersections<< p ;
00086 else
00087 right->s_intersections<< p ;
00088 }
00089
00090 foreach(Point* p,cl.m_singular) {
00091
00092 if(p->x() < s+eps)
00093 left ->m_singular << p ;
00094
00095 if(p->x() > s-eps)
00096 right->m_singular << p ;
00097 }
00098
00099
00100 cl.connect0(left, right);
00101 left->join0(right);
00102
00103
00104 } else {
00105
00106 left = new CELL(cl); left->set_ymax(s);
00107 right= new CELL(cl); right->set_ymin(s);
00108
00109
00110 tensor::split(left->m_polynomial, right->m_polynomial, v);
00111 if (left->n_intersections.size() ==0)
00112 Solver::edge_point(left->n_intersections,
00113 left->m_polynomial, Solver::north_edge, left->boundingBox());
00114 right->s_intersections=left->n_intersections;
00115 left ->s_intersections=cl.s_intersections;
00116 right->n_intersections=cl.n_intersections;
00117 foreach(Point* p,cl.w_intersections) {
00118 if(p->y() == s) {
00119 left ->w_intersections << p ;
00120 right->w_intersections << p ;
00121 } else 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 right->e_intersections << p ;
00131 } else if(p->y() < s)
00132 left ->e_intersections << p ;
00133 else
00134 right->e_intersections << p ;
00135 }
00136
00137 foreach(Point* p,cl.m_singular) {
00138 if(p->y() < s+eps)
00139 left->m_singular << p ;
00140
00141 if(p->y() > s-eps)
00142 right->m_singular << p ;
00143 }
00144
00145 foreach(Point* p,cl.m_xcritical) {
00146 if(p->y() < s+eps)
00147 left->m_xcritical << p ;
00148
00149 if(p->y() > s-eps)
00150 right->m_xcritical << p ;
00151 }
00152
00153 foreach(Point* p,cl.m_ycritical) {
00154 if(p->y() < s+eps)
00155 left->m_ycritical << p ;
00156
00157 if(p->y() > s-eps)
00158 right->m_ycritical << p ;
00159 }
00160
00161
00162 cl.connect1(left, right);
00163 left->join1(right);
00164
00165 }
00166
00167 cl.disconnect( );
00168
00169 }
00170
00171 TMPL class mesher2d;
00172
00173 template<class C, class V=default_env>
00174 class bcell2d_algebraic_curve : public bcell2d<C,REF> {
00175 public:
00176 typedef C Scalar;
00177 typedef topology<C,REF> Topology;
00178 typedef typename Topology::Point Point;
00179 typedef Seq<Point*> Points;
00180
00181
00182 typedef typename use<point_def,C,V>::Point Vector;
00183 typedef typename topology<C,REF>::Edge Edge;
00184 typedef bcell<C,REF> Cell;
00185 typedef algebraic_set<C,REF> AlgebraicSet;
00186 typedef algebraic_curve<C,REF> AlgebraicCurve;
00187 typedef polynomial< Interval<C>, with<Bernstein> > Polynomial;
00188 typedef bounding_box<C,REF> BoundingBox;
00189
00190 typedef solver_implicit<C,V> Solver;
00191 typedef mesher2d<C,V> Mesher2d;
00192
00193 bcell2d_algebraic_curve(const Polynomial &, const BoundingBox&, bool inter=true);
00194 bcell2d_algebraic_curve(const char*, const BoundingBox&);
00195 bcell2d_algebraic_curve(const typename AlgebraicSet::Polynomial& , const BoundingBox&);
00196 bcell2d_algebraic_curve(AlgebraicCurve*, const BoundingBox &x);
00197 bcell2d_algebraic_curve(const SELF& cl)
00198 : bcell2d<C,REF>(cl.boundingBox()), m_polynomial(cl.m_polynomial) {}
00199
00200 Polynomial equation(void) { return m_polynomial; }
00201
00202 bool is_active (void) ;
00203 bool is_regular(void) ;
00204 bool is_intersected(void) { return (this->nb_intersect()>0); };
00205
00206 virtual Point * pair(Point * p, int & sgn);
00207 virtual Point * starting_point( int sgn) ;
00208
00209 virtual bool insert_regular (Topology*);
00210 virtual bool insert_singular(Topology*);
00211 virtual void subdivide(Cell*& left, Cell*& right, int v, double s);
00212 Vector gradient(const Point& p);
00213
00214 public:
00215 Polynomial m_polynomial;
00216 Seq<Point *> m_xcritical;
00217 Seq<Point *> m_ycritical;
00218 Seq<Point *> m_boundary;
00219
00220 };
00221
00222
00223 TMPL inline void
00224 print(SELF* cv) {
00225 typedef typename SELF::Point Point;
00226 std::cout <<"\nBox : ["<<cv->xmin()<<","<<cv->xmax()<<"] *"
00227 <<" ["<<cv->ymin()<<","<<cv->ymax()<<"]";
00228 std::cout <<"\npoint(s) s: ";
00229 foreach(Point* p, cv->s_intersections)
00230 std::cout <<" ["<<p->x()<<" "<<p->y()<<"]";
00231 std::cout << "\npoint(s) e: ";
00232 foreach(Point* p, cv->e_intersections)
00233 std::cout <<" ["<<p->x()<<" "<<p->y()<<"]";
00234 std::cout << "\npoint(s) n: ";
00235 foreach(Point* p, cv->n_intersections)
00236 std::cout <<" ["<<p->x()<<" "<<p->y()<<"]";
00237 std::cout << "\npoint(s) w: ";
00238 foreach(Point* p, cv->w_intersections)
00239 std::cout <<" ["<<p->x()<<" "<<p->y()<<"]";
00240
00241 std::cout<<std::endl;
00242
00243 std::cout << "Point(s) sing: ";
00244 foreach(Point* p, cv->m_singular)
00245 std::cout <<" ["<<p->x()<<" "<<p->y()<<"]";
00246 std::cout<<std::endl;
00247 }
00248
00249 TMPL
00250 SELF::bcell2d_algebraic_curve(const Polynomial& pol, const BoundingBox& bx, bool inter): bcell2d<C,REF>(bx), m_polynomial(pol)
00251 {
00252
00253 if (inter)
00254 {
00255
00256 Solver::edge_point(this->n_intersections, m_polynomial, Solver::north_edge, bx);
00257 Solver::edge_point(this->s_intersections, m_polynomial, Solver::south_edge, bx);
00258 Solver::edge_point(this->w_intersections, m_polynomial, Solver::west_edge , bx);
00259 Solver::edge_point(this->e_intersections, m_polynomial, Solver::east_edge , bx);
00260 }
00261
00262
00263 }
00264
00265 TMPL
00266 SELF::bcell2d_algebraic_curve(const typename AlgebraicSet::Polynomial& p, const BoundingBox & b): bcell2d<C,REF>(b)
00267 {
00268
00269 Seq<mmx::GMP::rational> bx;
00270 bx<<as<mmx::GMP::rational>(b.xmin());
00271 bx<<as<mmx::GMP::rational>(b.xmax());
00272 bx<<as<mmx::GMP::rational>(b.ymin());
00273 bx<<as<mmx::GMP::rational>(b.ymax());
00274
00275 tensor::bernstein<mmx::GMP::rational> polq(p.rep(),bx);
00276
00277 let::assign(m_polynomial.rep(),polq);
00278
00279 Solver::edge_point(this->n_intersections, m_polynomial, Solver::north_edge, b);
00280 Solver::edge_point(this->s_intersections, m_polynomial, Solver::south_edge, b);
00281 Solver::edge_point(this->w_intersections, m_polynomial, Solver::west_edge , b);
00282 Solver::edge_point(this->e_intersections, m_polynomial, Solver::east_edge , b);
00283
00284 Solver::extremal(this->m_singular, p, b);
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 }
00300
00301
00302 TMPL
00303 SELF::bcell2d_algebraic_curve(const char* s, const BoundingBox & b): bcell2d<C,REF>(b)
00304 {
00305 Seq<mmx::GMP::rational> bx;
00306 bx<<as<mmx::GMP::rational>(b.xmin());
00307 bx<<as<mmx::GMP::rational>(b.xmax());
00308 bx<<as<mmx::GMP::rational>(b.ymin());
00309 bx<<as<mmx::GMP::rational>(b.ymax());
00310
00311 typename AlgebraicSet::Polynomial pol(s);
00312 tensor::bernstein<mmx::GMP::rational> polq(s,bx);
00313
00314 let::assign(m_polynomial.rep(),polq);
00315
00316 Solver::edge_point(this->s_intersections, m_polynomial, Solver::south_edge, b);
00317 Solver::edge_point(this->e_intersections, m_polynomial, Solver::east_edge , b);
00318 Solver::edge_point(this->n_intersections, m_polynomial, Solver::north_edge, b);
00319 Solver::edge_point(this->w_intersections, m_polynomial, Solver::west_edge , b);
00320
00321 Solver::extremal(this->m_singular, pol, b);
00322 foreach(Point* p,this-> m_singular)
00323 std::cout<<"**extremal point: "<<p->x()<<" "<<p->y() <<std::endl;
00324 }
00325
00326
00327 TMPL
00328 SELF::bcell2d_algebraic_curve(AlgebraicCurve* cv, const BoundingBox & b)
00329 {
00330 new (this) SELF(cv->equation(),b );
00331 }
00332
00333
00334 TMPL bool
00335 SELF::is_regular() {
00336
00337
00338 if(this->m_singular.size()>1) return false;
00339
00340
00341 if (this->m_singular.size()==0) {
00342 if(!has_sign_variation(m_polynomial)) return true;
00343
00344 Polynomial dx= diff(m_polynomial,0);
00345 if(!has_sign_variation(dx)) return true;
00346
00347 Polynomial dy= diff(m_polynomial,1);
00348 if(!has_sign_variation(dy)) return true;
00349
00350 int n= this->nb_intersect();
00351 return ( n==2 );
00352
00353
00354 }
00355
00356
00357
00358
00359 if(this->m_singular.size()==1) {
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374 return false;
00375 }
00376
00377 return true;
00378 }
00379
00380
00381 TMPL bool
00382 SELF::is_active() {
00383
00384 return (has_sign_variation(this->m_polynomial));
00385
00386
00387
00388
00389 }
00390
00391
00392 TMPL bool
00393 SELF::insert_regular(Topology* t) {
00394
00395
00396 int sgn(1);
00397 Point *p,*q;
00398
00399
00400
00401 Scalar eps = 1e-10;
00402
00403
00404 foreach(Point* pt, this->s_intersections) {
00405 m_boundary<<pt;
00406 }
00407
00408 if(this->s_intersections.size()>0) q=this->s_intersections.rep().back(); else q=NULL;
00409 foreach(Point* pt, this->e_intersections) {
00410 if(q && pt->dist2(*q) < eps) {
00411 q=pt;
00412 } else {
00413 m_boundary<<pt;
00414 }
00415 }
00416
00417 if(this->e_intersections.size()>0) q=this->e_intersections.rep().back(); else q=NULL;
00418 foreach(Point* pt, this->n_intersections.reversed()) {
00419 if(q && pt->dist2(*q) < eps) {
00420 q=pt;
00421 } else {
00422 m_boundary<<pt;
00423 }
00424 }
00425
00426 if(this->n_intersections.size()>0) q=this->n_intersections.rep().front(); else q=NULL;
00427 foreach(Point* pt, this->w_intersections.reversed()) {
00428 if(q && pt->dist2(*q) < eps) {
00429 q=pt;
00430 } else {
00431 m_boundary<<pt;
00432 }
00433 }
00434
00435
00436
00437 Seq<Point*> l=m_boundary;
00438
00439
00440
00441
00442
00443
00444
00445 if (l.size()==1 || l.size()==3) {
00446
00447 }
00448 if(this->m_singular.size()==0)
00449 {
00450 foreach(Point* v, l) t->insert(v);
00451
00452 if (l.size() ==2)
00453 t->insert_edge(l[0],l[1]);
00454 else {
00455 while (l.size()>1)
00456 {
00457
00458 p= l[0];
00459 q= this->pair(p,sgn);
00460 l.erase(0);
00461
00462 l.erase( l.search(q) );
00463
00464 t->insert_edge(p,q);
00465
00466
00467 }
00468 if (l.size()>0) {
00469
00470 print(this);
00471 std::cout<< "Warning: point "<<*(l[0])<<" not used"<< std::endl;
00472 }
00473 }
00474 }
00475 else
00476 {
00477 std::cout<<"Singular:"<<std::endl;
00478
00479 t->insert((BoundingBox*)this,false);
00480
00481 Point *c=this->m_singular[0];
00482
00483 t->insert(c);
00484 foreach(Point* p, this->n_intersections) t->insert_edge(p,c);
00485 foreach(Point* p, this->e_intersections) t->insert_edge(p,c);
00486 foreach(Point* p, this->s_intersections) t->insert_edge(p,c);
00487 foreach(Point* p, this->w_intersections) t->insert_edge(p,c);
00488 }
00489
00490
00491
00492 return true;
00493
00494 }
00495
00496 TMPL bool
00497 SELF::insert_singular(Topology* t) {
00498
00499
00500
00501
00502
00503
00504
00505
00506 int sgn(1);
00507
00508 Seq<Point*> l;
00509 foreach(Point* p, this->n_intersections) {
00510 t->insert(p); l<<p;
00511
00512 }
00513 foreach(Point* p, this->e_intersections) {
00514 t->insert(p); l<<p;
00515
00516 }
00517 foreach(Point* p, this->s_intersections) {
00518 t->insert(p); l<<p;
00519
00520 }
00521 foreach(Point* p, this->w_intersections) {
00522 t->insert(p); l<<p;
00523
00524 }
00525 int ni=l.size();
00526
00527 if(this->m_singular.size()==1) {
00528
00529
00530
00531
00532
00533 Point *c=this->m_singular[0];
00534
00535
00536 t->insert(c);
00537 foreach(Point* p, this->n_intersections) t->insert_edge(p,c);
00538 foreach(Point* p, this->e_intersections) t->insert_edge(p,c);
00539 foreach(Point* p, this->s_intersections) t->insert_edge(p,c);
00540 foreach(Point* p, this->w_intersections) t->insert_edge(p,c);
00541 return true;
00542 }
00543 else
00544 {
00545 if(ni==2) {
00546 t->insert_edge(l[0],l[1]);
00547 return true;
00548 }
00549 else
00550 {
00551 Point *p,*q;
00552 while (l.size()>0)
00553 {
00554 p= l[0];
00555 q= this->pair(p,sgn);
00556 l.erase(0);
00557 l.erase( l.search(q) );
00558 t->insert_edge(p,q);
00559 }
00560 }
00561 }
00562
00563
00564
00565 return true;
00566 }
00567
00568
00569 TMPL void
00570 SELF::subdivide(Cell*& Left, Cell*& Right, int v, double s) {
00571 bcell2d_subdivisor<C,V>::subdivide( *this,(SELF*&)Left,(SELF*&)Right,v,s);
00572 }
00573
00574 TMPL typename SELF::Vector
00575 SELF::gradient(const Point& p) {
00576 Polynomial
00577 dx= diff(m_polynomial,0),
00578 dy= diff(m_polynomial,1);
00579 double
00580 u0= (p[0]-this->xmin())/(this->xmax()-this->xmin()),
00581 u1= (p[1]-this->ymin())/(this->ymax()-this->ymin());
00582 Vector v;
00583 v[0] = dx(u0,u1);
00584 v[1] = dy(u0,u1);
00585 return v;
00586 }
00587
00588
00589 TMPL typename SELF::Point*
00590 SELF::starting_point(int sgn) {
00591
00592
00593
00594 Seq<Point*> l, all;
00595 unsigned a;
00596 all = this->intersections();
00597
00598
00599
00600
00601
00602 a = all.size();
00603 if (a==1) return all[0];
00604
00605 int ev(0);
00606 int u ;
00607
00608 unsigned
00609 s=this->s_intersections.size() ,
00610 e=this->e_intersections.size() ,
00611
00612 w=this->w_intersections.size() ;
00613
00614 u= ( 0<s ? 0 :
00615 ( 0<s+e ? 1 :
00616 ( 0<a-w ? 2 :
00617 3 )));
00618
00619 int * sz = this->m_polynomial.rep().szs();
00620 int * st = this->m_polynomial.rep().str();
00621
00622 switch (u){
00623 case 0:
00624 ev= (this->m_polynomial[0] >0 ? 1:-1);
00625 break;
00626 case 1:
00627 ev= (this->m_polynomial[(sz[0]-1)*st[0]] >0 ? 1:-1);
00628 break;
00629 case 2:
00630 ev= (this->m_polynomial[sz[0]*sz[1]-1]>0 ? 1:-1);
00631 break;
00632 case 3:
00633 ev= (this->m_polynomial[(sz[1]-1)*st[1]] >0 ? 1:-1);
00634 break;
00635 }
00636
00637 if (ev*sgn>0) {
00638 return all[0];
00639 }
00640 else {
00641 return all[1];
00642 }
00643 }
00644
00645
00646 TMPL typename SELF::Point*
00647 SELF::pair( typename SELF::Point* p, int & sgn) {
00648
00649
00650
00651 Seq<Point*> all;
00652 int a;
00653 all= this->intersections();
00654 a = all.size();
00655 if (a==2)
00656 { return (all[0]==p ? all[1]: all[0]); }
00657 if (a==1)
00658 {
00659 std::cout<<"Only 1 intersection point in "<< *this <<" (i.e."<<*all[0] <<")"<<std::endl;
00660 return (p);
00661 }
00662
00663 int
00664 s=this->s_intersections.size() ,
00665 e=this->e_intersections.size() ,
00666
00667 w=this->w_intersections.size() ;
00668
00669 int j,k,i= all.search(p);
00670
00671
00672 if (this->m_singular.size()==0 ) {
00673
00674 Vector grq, grp = this->gradient(*p);
00675 foreach(Point* q, all)
00676 if ( q != p)
00677 {
00678 grq = this->gradient(*q);
00679 if(grp[0]*grq[0]>0 && grp[1]*grq[1]>0 ) return (q);
00680 }
00681
00682
00683
00684
00685
00686 std::cout<<"...maybe pair Trouble (1)"<< this<<std::endl;
00687
00688 for (int v=0;v<a;v++)
00689 for (int w=v+1;w<a;v++)
00690 {
00691 grp= this->gradient(*all[v]);
00692 grq= this->gradient(*all[w]);
00693 if( grp[0]*grq[0]>0 && grp[1]*grq[1]>0 )
00694 {
00695 for (int u=0; u<a;u++)
00696 if ( u!=v && u!=w && all[u]!=p )
00697 return (all[u]);
00698 }
00699 }
00700
00701 std::cout<<"empty BOX:("<<this->m_singular.size()<<",a="<<a<<")"<<this <<std::endl;
00702 foreach(Point*v,all) {
00703 Vector gr= this->gradient(*v);
00704
00705 std::cout<<(gr[0]>0?1:-1)<<","<<(gr[1]>0?1:-1) <<std::endl;
00706 }
00707
00708
00709 foreach(Point* q, all)
00710 if ( q != p)
00711 {
00712 grq = this->gradient(*q);
00713 if( abs(grp[0]) < 0.017)
00714 { if (grp[1]*grq[1]>0)
00715 return (q);
00716 }
00717 else if ( abs(grp[1])< 0.01)
00718 { if (grp[0]*grq[0]>0)
00719 return (q);
00720 }
00721 }
00722
00723 std::cout<<"...pair Trouble (2)"<< this<<std::endl;
00724
00725 return (all[0]);
00726
00727 }
00728 else {
00729
00730
00731
00732
00733
00734
00735
00736 int ev(0);
00737 int u, v;
00738 j= ( i!=0 ? i-1 : a-1 );
00739 k= ( i!=a-1 ? i+1 : 0 );
00740
00741
00742
00743 Point *ln= all[j],
00744 *rn= all[k] ;
00745
00746
00747
00748
00749 u= ( i<s ? 0 :
00750 ( i<s+e ? 1 :
00751 ( i<a-w ? 2 :
00752 3 )));
00753 v= ( j<s ? 0 :
00754 ( j<s+e ? 1 :
00755 ( j<a-w ? 2 :
00756 3 )));
00757
00758 int * sz = this->m_polynomial.rep().szs();
00759 int * st = this->m_polynomial.rep().str();
00760
00761 switch (u){
00762 case 0:
00763 ev= (this->m_polynomial[0] >0 ? 1:-1);
00764 if (v==0 && j%2==0)
00765 ev*=-1;
00766 break;
00767 case 1:
00768 ev= (this->m_polynomial[(sz[0]-1)*st[0]] >0 ? 1:-1);
00769 if (v==1 && (j-s)%2==0)
00770 ev*=-1;
00771 break;
00772 case 2:
00773 ev= (this->m_polynomial[sz[0]*sz[1]-1]>0 ? 1:-1);
00774 if (v==2 && (j-s-e)%2==0)
00775 ev*=-1;
00776 break;
00777 case 3:
00778 ev= (this->m_polynomial[(sz[1]-1)*st[1]] >0 ? 1:-1);
00779 if (v==3 && (j-a+w)%2==0)
00780 ev*=-1;
00781 break;
00782 }
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794 if (ev*sgn>0) return ln;
00795 else return rn;
00796 }
00797 }
00798
00799
00800 } ;
00801 } ;
00802 # undef Solver
00803 # undef SELF
00804 # undef REF
00805 # undef TMPL
00806 # undef STACK
00807 # endif // shape_cell2d_algebraic_curve_hpp