00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 # ifndef shape_bcell3d_algebraic_surface_hpp
00014 # define shape_bcell3d_algebraic_surface_hpp
00015
00016 # include <realroot/Interval.hpp>
00017 # include <realroot/ring_bernstein_tensor.hpp>
00018 # include <realroot/sign_variation.hpp>
00019 # include <realroot/Seq.hpp>
00020 # include <shape/bounding_box.hpp>
00021 # include <shape/algebraic_surface.hpp>
00022 # include <shape/bcell3d.hpp>
00023 # include <shape/solver_implicit.hpp>
00024 # include <shape/marching_cube.hpp>
00025
00026 # define TMPL template<class C, class V>
00027 # define TMPL1 template<class C>
00028 # define SELF bcell3d_algebraic_surface<C,V>
00029 # undef Topology
00030
00031 namespace mmx { namespace shape {
00032
00033
00034
00035
00036
00037
00038 TMPL class topology;
00039 TMPL class tpl3d;
00040 TMPL class bcell3d_algebraic_surface;
00041
00042
00043 struct bcell3d_algebraic_surface_def {};
00044
00045 template<> struct use<bcell3d_algebraic_surface_def>
00046
00047
00048 {
00049 typedef Interval< double > Scalar;
00050 typedef polynomial< double, with<Bernstein> > Polynomial;
00051
00052
00053
00054 };
00055
00056
00057 template<class C, class V=default_env>
00058 class bcell3d_algebraic_surface : public bcell3d<C,V> {
00059 public:
00060
00061 typedef REF_OF(V) Ref;
00062 typedef tpl3d<C,V> Topology3d;
00063 typedef topology<C,REF_OF(V)> Topology;
00064
00065 typedef typename Topology::Point Point;
00066 typedef typename Topology::Edge Edge;
00067 typedef typename Topology::Face Face;
00068
00069 typedef bcell3d<C,V> Cell;
00070 typedef cell3d<C,V> CellBase;
00071 typedef bcell3d<C,V> Cell3d;
00072
00073 typedef bounding_box<C,Ref> BoundingBox;
00074
00075 typedef algebraic_surface<C,Ref> AlgebraicSurface;
00076
00077 typedef typename use<bcell3d_algebraic_surface_def,C,V>::Polynomial Polynomial;
00078
00079
00080
00081
00082 typedef solver_implicit<C,V> Solver;
00083
00084 bcell3d_algebraic_surface(const SELF&);
00085 bcell3d_algebraic_surface(const Polynomial&, const BoundingBox& );
00086 bcell3d_algebraic_surface(char*, const BoundingBox& );
00087
00088 bcell3d_algebraic_surface(const AlgebraicSurface&, const BoundingBox&);
00089 bcell3d_algebraic_surface(AlgebraicSurface *, const BoundingBox&);
00090
00091 virtual bool is_regular(void);
00092 virtual bool is_active (void) const;
00093
00094 virtual bool is_intersected (void) {return true;}
00095
00096 virtual bool insert_regular (Topology*) ;
00097 virtual bool insert_singular(Topology*) ;
00098
00099 virtual void polygonise (Topology3d*) ;
00100
00101 virtual bool topology_regular(Topology*) ;
00102
00103 template<class CELL>
00104 void split (CELL*& left, CELL*& right, int v, double s);
00105 virtual void subdivide(CellBase*& left, CellBase*& right, int v, double s);
00106
00107 int mc_index(void) const ;
00108 bool edge_point(Point**, int ) const ;
00109
00110 Point center() const { return Point((this->xmin()+this->xmax())/2, (this->ymin()+this->ymax())/2,
00111 (this->zmin()+this->zmax())/2); }
00112
00113 C center_value() { return m_polynomial(0.5,0.5,0.5); }
00114
00115 void insert(Point* p) { m_points<< p; }
00116 void insert(Face* p) { m_faces<< p; }
00117
00118 double vertex_eval(unsigned sx, unsigned sy, unsigned sz) const;
00119 const Polynomial& equation() const {return m_polynomial;}
00120 Polynomial get_polynomial() const {return m_polynomial;}
00121
00122 public:
00123 Polynomial m_polynomial;
00124 Point* m_center;
00125 C m_center_value;
00126 int m_idx;
00127
00128 Seq<Point*> m_points;
00129 Seq<Face*> m_faces;
00130
00131 private:
00132 void resolve_conflict(Seq<Cell3d*> &neighb, double side, int cc);
00133 };
00134
00135
00136 TMPL
00137 SELF::bcell3d_algebraic_surface(const SELF& s)
00138 : Cell3d((BoundingBox)s), m_polynomial(s.equation()), m_center(0)
00139 {
00140
00141 }
00142
00143 TMPL
00144 SELF::bcell3d_algebraic_surface(const Polynomial& pol, const BoundingBox& bx)
00145 : Cell3d(bx), m_polynomial(pol), m_center(0)
00146 {
00147
00148 }
00149
00150 TMPL
00151 SELF::bcell3d_algebraic_surface(char* pol, const BoundingBox& bx)
00152 : Cell3d(bx), m_polynomial(pol), m_center(0)
00153 {
00154 }
00155
00156 TMPL
00157 SELF::bcell3d_algebraic_surface(const AlgebraicSurface& sf, const BoundingBox& b): Cell3d(b), m_center(0)
00158 {
00159 Seq<mmx::GMP::rational> bx;
00160 bx<<as<mmx::GMP::rational>(b.xmin());
00161 bx<<as<mmx::GMP::rational>(b.xmax());
00162 bx<<as<mmx::GMP::rational>(b.ymin());
00163 bx<<as<mmx::GMP::rational>(b.ymax());
00164 bx<<as<mmx::GMP::rational>(b.zmin());
00165 bx<<as<mmx::GMP::rational>(b.zmax());
00166
00167 Polynomial tmp;
00168 tensor::bernstein<mmx::GMP::rational> polq(sf.equation().rep(),bx);
00169 let::assign(tmp.rep(),polq);
00170 m_polynomial=tmp;
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199 }
00200
00201 TMPL bool
00202 SELF::is_active() const {
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 return has_sign_variation(m_polynomial.begin(),m_polynomial.end());
00235 }
00236
00237 TMPL bool
00238 SELF::is_regular() {
00239 Polynomial dxf, dyf, dzf;
00240 Polynomial fp0, fp1;
00241 Polynomial bk, ft;
00242
00243
00244 tensor::face(bk, m_polynomial, 2, 0);
00245 if(Solver::edge_sign_var(bk, Solver::north_back_edge) >1) return false;
00246 if(Solver::edge_sign_var(bk, Solver::south_back_edge) >1) return false;
00247 if(Solver::edge_sign_var(bk, Solver::east_back_edge ) >1) return false;
00248 if(Solver::edge_sign_var(bk, Solver::west_back_edge ) >1) return false;
00249
00250
00251 tensor::face(ft, m_polynomial, 2, 1);
00252 if(Solver::edge_sign_var(ft, Solver::north_front_edge) >1) return false;
00253 if(Solver::edge_sign_var(ft, Solver::south_front_edge) >1) return false;
00254 if(Solver::edge_sign_var(ft, Solver::east_front_edge ) >1) return false;
00255 if(Solver::edge_sign_var(ft, Solver::west_front_edge ) >1) return false;
00256
00257 tensor::face(ft, equation(), 1, 1);
00258 if(Solver::edge_sign_var(ft, Solver::north_west_edge) >1) return false;
00259 if(Solver::edge_sign_var(ft, Solver::north_east_edge) >1) return false;
00260
00261 tensor::face(bk, equation(), 1, 0);
00262 if(Solver::edge_sign_var(bk, Solver::south_west_edge) >1) return false;
00263 if(Solver::edge_sign_var(bk, Solver::south_east_edge) >1) return false;
00264
00265 tensor::diff(dxf.rep(),m_polynomial.rep(),0);
00266 tensor::diff(dyf.rep(),m_polynomial.rep(),1);
00267 tensor::diff(dzf.rep(),m_polynomial.rep(),2);
00268
00269 if(!has_sign_variation(dxf.begin(),dxf.end())) {
00270
00271 this->m_idx=0;
00272 return true;
00273
00274 tensor::face(fp0, dyf, 0, 0);
00275 tensor::face(fp1, dyf, 0, 1);
00276 if(!has_sign_variation(fp0.begin(),fp0.end()) &&
00277 !has_sign_variation(fp1.begin(),fp1.end()) ) return true;
00278
00279 tensor::face(fp0, dzf, 0, 0);
00280 tensor::face(fp1, dzf, 0, 1);
00281 if(!has_sign_variation(fp0.begin(),fp0.end()) &&
00282 !has_sign_variation(fp1.begin(),fp1.end())) return true;
00283
00284 return false;
00285 }
00286
00287
00288 if(!has_sign_variation(dyf.begin(),dyf.end())) {
00289 this->m_idx=1;
00290 return true;
00291
00292
00293
00294
00295
00296
00297
00298 }
00299
00300
00301 if(!has_sign_variation(dzf.begin(),dzf.end())) {
00302 this->m_idx=2;
00303 return true;
00304 }
00305
00306 return false;
00307 }
00308
00309 TMPL template<class CELL> void
00310 SELF::split(CELL*& left, CELL*& right, int v, double c) {
00311
00312
00313 if(v==0) {
00314 left = new CELL(m_polynomial, BoundingBox(this->xmin(),c, this->ymin(), this->ymax(), this->zmin(), this->zmax()));
00315 right= new CELL(m_polynomial, BoundingBox(c,this->xmax(), this->ymin(), this->ymax(), this->zmin(), this->zmax()));
00316
00317 this->connect0(left, right);
00318 left->join0(right);
00319 } else if (v==1) {
00320 left = new CELL(m_polynomial, BoundingBox(this->xmin(),this->xmax(), this->ymin(), c, this->zmin(), this->zmax()));
00321 right= new CELL(m_polynomial, BoundingBox(this->xmin(),this->xmax(), c, this->ymax(), this->zmin(), this->zmax()));
00322
00323 this->connect1(left, right);
00324 left->join1(right);
00325 } else {
00326 left = new CELL(m_polynomial, BoundingBox(this->xmin(),this->xmax(),this->ymin(),this->ymax(), this->zmin(), c));
00327 right= new CELL(m_polynomial, BoundingBox(this->xmin(),this->xmax(),this->ymin(),this->ymax(), c, this->zmax()));
00328
00329 this->connect2(left, right);
00330 left->join2(right);
00331 }
00332
00333
00334 tensor::split(left->m_polynomial, right->m_polynomial, v);
00335
00336 }
00337
00338
00339 TMPL void
00340 SELF::subdivide(CellBase*& Left, CellBase*& Right, int v, double c) {
00341 SELF * left=0, * right=0;
00342 this->split(left,right,v,c);
00343 Left=left; Right=right;
00344 }
00345
00346
00347 TMPL bool
00348 SELF::insert_regular(Topology* t) {
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 return true;
00361 }
00362
00363 TMPL void
00364 SELF::polygonise(Topology3d* t) {
00365 marching_cube::polygonise(*t, *this);
00366 }
00367
00368 TMPL bool
00369 SELF::insert_singular(Topology* ) {
00370 return true;
00371 }
00372
00373 TMPL bool
00374 SELF::topology_regular(Topology* t) {
00375
00376 Topology3d* tpl3d= dynamic_cast<Topology3d*>(t);
00377
00378 if(this->w_neighbors.size()>1)
00379 resolve_conflict(this->w_neighbors, this->xmin(),0 );
00380
00381 if(this->e_neighbors.size()>1)
00382 resolve_conflict(this->e_neighbors, this->xmax(),0 );
00383
00384
00385
00386
00387
00388 if(this->n_neighbors.size()>1)
00389 resolve_conflict(this->n_neighbors, this->ymax(),1 );
00390
00391 if(this->s_neighbors.size()>1)
00392 resolve_conflict(this->s_neighbors, this->ymin(),1 );
00393
00394 if(this->f_neighbors.size()>1)
00395 resolve_conflict(this->f_neighbors, this->zmax(),2 );
00396
00397 if(this->b_neighbors.size()>1)
00398 resolve_conflict(this->b_neighbors, this->zmin(),2 );
00399
00400
00401 foreach(Point* p, this->m_points) tpl3d->insert(p);
00402 foreach(Face* f, this->m_faces)
00403 {
00404 tpl3d->insert(f);
00405
00406 }
00407
00408 return true;
00409 }
00410
00411
00412 TMPL void
00413 SELF::resolve_conflict(Seq<Cell3d*> &neighb, double side, int cc)
00414 {
00415
00416 typedef Cell3d Cell3dRef;
00417 Seq<Point*> tmp;
00418 Seq<Edge*> edges;
00419 bool ccw;
00420
00421
00422 foreach(Face* f1, this->m_faces)
00423 {
00424 ccw= f1->is_ccw();
00425 tmp.clear();
00426 foreach(Point *p, *f1)
00427 if ( (*p)[cc]==side )
00428 tmp<<p;
00429 if ( tmp.size()==2 )
00430 {
00431 Edge * tt=new Edge(tmp[0],tmp[1]);
00432 edges.clear();
00433 foreach(Cell3dRef* cl, neighb)
00434 if(dynamic_cast<SELF*>(cl)->m_faces.size()>0)
00435 {
00436 foreach(Face* f0,dynamic_cast<SELF*>(cl)->m_faces)
00437 {
00438 tmp.clear();
00439 foreach(Point *p, *f0)
00440
00441 if ( (*p)[cc] == side )
00442 tmp<<p;
00443 if ( tmp.size()==2 )
00444 {
00445 edges<< new Edge( tmp[0],tmp[1]);
00446 }
00447 }
00448 }
00449 if ( edges.size()>0 )
00450 {
00451 std::cout<<"Found big edge on plane "<<cc<<", "<<side<<std::endl;
00452 std::cout<<"adding "<<edges.size() << " edges." <<std::endl;
00453 }
00454 foreach( Edge* e, edges)
00455 {
00456 Face * ff=
00457 new Face(
00458 e->destination(),
00459 e->source(),
00460 f1->not_on(tt) );
00461 if ( ff->is_ccw()!=ccw )
00462 ff->reverse();
00463 this->m_faces << ff;
00464 }
00465 m_faces.erase( m_faces.search(f1) );
00466 }
00467 }
00468 }
00469
00470
00471 TMPL double
00472 SELF::vertex_eval(unsigned sx, unsigned sy, unsigned sz) const {
00473
00474 int s=0;
00475 s+= sx*(m_polynomial.rep().env.sz(0)-1)*m_polynomial.rep().env.st(0);
00476 s+= sy*(m_polynomial.rep().env.sz(1)-1)*m_polynomial.rep().env.st(1);
00477 s+= sz*(m_polynomial.rep().env.sz(2)-1)*m_polynomial.rep().env.st(2);
00478 return m_polynomial[s];
00479 }
00480
00481
00482 TMPL int
00483 SELF::mc_index() const {
00484
00485 double isolevel = 0;
00486 int CubeIndex=0;
00487
00488 if (vertex_eval(0,1,0) <= isolevel) CubeIndex |= 1;
00489 if (vertex_eval(1,1,0) <= isolevel) CubeIndex |= 2;
00490 if (vertex_eval(1,0,0) <= isolevel) CubeIndex |= 4;
00491 if (vertex_eval(0,0,0) <= isolevel) CubeIndex |= 8;
00492 if (vertex_eval(0,1,1) <= isolevel) CubeIndex |= 16;
00493 if (vertex_eval(1,1,1) <= isolevel) CubeIndex |= 32;
00494 if (vertex_eval(1,0,1) <= isolevel) CubeIndex |= 64;
00495 if (vertex_eval(0,0,1) <= isolevel) CubeIndex |= 128;
00496
00497 return CubeIndex;
00498 }
00499
00500 TMPL bool
00501 SELF::edge_point(Point** CELL, int cube_index) const {
00502
00503 BoundingBox* bx = (BoundingBox*)this;
00504 Seq<Point*> F;
00505 Polynomial bk, ft;
00506
00507 tensor::face(bk, equation(), 2, 0);
00508 if (cube_index & 1) {
00509 Solver::edge_point(F, bk, Solver::north_back_edge, *bx);
00510 if(F.size()==0) {
00511 std::cout<<"Problem in MC0"<<std::endl;
00512 return false;
00513 } else
00514 CELL[0] = F[0];
00515 F.resize(0);
00516 }
00517 if (cube_index & 2) {
00518 Solver::edge_point(F, bk, Solver::east_back_edge , *bx);
00519 if(F.size()==0) {
00520 std::cout<<"Problem in MC1"<<std::endl;
00521 return false;
00522 } else
00523 CELL[1] = F[0];
00524 F.resize(0);
00525 }
00526 if (cube_index & 4) {
00527 Solver::edge_point(F, bk, Solver::south_back_edge, *bx);
00528 if(F.size()==0) {
00529 std::cout<<"Problem in MC2"<<std::endl;
00530 return false;
00531 } else
00532 CELL[2] = F[0];
00533 F.resize(0);
00534 }
00535 if (cube_index & 8) {
00536 Solver::edge_point(F, bk, Solver::west_back_edge , *bx);
00537 if(F.size()==0) {
00538 std::cout<<"Problem in MC3"<<std::endl;
00539 } else
00540 CELL[3] = F[0];
00541 F.resize(0);
00542 }
00543
00544 tensor::face(ft,equation(), 2, 1);
00545
00546 if (cube_index & 16) {
00547 Solver::edge_point(F, ft, Solver::north_front_edge, *bx);
00548 if(F.size()==0) {
00549 std::cout<<"Problem in MC4 "<<std::endl;
00550 return false;
00551 } else
00552 CELL[4] = F[0];
00553 F.resize(0);
00554 }
00555
00556 if (cube_index & 32) {
00557 Solver::edge_point(F, ft, Solver::east_front_edge , *bx);
00558 if(F.size()==0) {
00559 std::cout<<"Problem in MC5"<<std::endl;
00560 return false;
00561 } else
00562 CELL[5] = F[0];
00563 F.resize(0);
00564 }
00565
00566 if (cube_index & 64) {
00567 Solver::edge_point(F, ft, Solver::south_front_edge, *bx);
00568 if(F.size()==0) {
00569 std::cout<<"Problem in MC6"<<std::endl;
00570 return false;
00571 } else
00572 CELL[6] = F[0];
00573 F.resize(0);
00574 }
00575
00576 if (cube_index & 128) {
00577 Solver::edge_point(F, ft, Solver::west_front_edge , *bx);
00578 if(F.size()==0) {
00579 std::cout<<"Problem in MC7"<<std::endl;
00580 return false;
00581 } else
00582 CELL[7] = F[0];
00583 F.resize(0);
00584 }
00585
00586 tensor::face(ft, equation(), 1, 1);
00587 if (cube_index & 256) {
00588 Solver::edge_point(F, ft, Solver::north_west_edge, *bx);
00589 if(F.size()==0) {
00590 std::cout<<"Problem in MC8"<<std::endl;
00591 return false;
00592 } else
00593 CELL[8] = F[0];
00594 F.resize(0);
00595 }
00596
00597 if (cube_index & 512) {
00598 Solver::edge_point(F, ft, Solver::north_east_edge, *bx);
00599 if(F.size()==0) {
00600 std::cout<<"Problem in MC9"<<std::endl;
00601 return false;
00602 } else
00603 CELL[9] = F[0];
00604 F.resize(0);
00605 }
00606
00607 tensor::face(bk, equation(), 1, 0);
00608
00609 if (cube_index & 1024) {
00610 Solver::edge_point(F, bk, Solver::south_east_edge, *bx);
00611 if(F.size()==0) {
00612 std::cout<<"Problem in MC10"<<std::endl;
00613 return false;
00614 } else
00615 CELL[10] = F[0];
00616 F.resize(0);
00617 }
00618
00619 if (cube_index & 2048) {
00620 Solver::edge_point(F, bk, Solver::south_west_edge, *bx);
00621 if(F.size()==0) {
00622 std::cout<<"Problem in MC11"<<std::endl;
00623 return false;
00624 } else
00625 CELL[11] = F[0];
00626 F.resize(0);
00627 }
00628
00629 return true;
00630 }
00631
00632
00633 } ;
00634 } ;
00635 # undef TMPL
00636 # undef TMPL1
00637 # undef Point
00638 # undef Edge
00639 # undef AlgebraicSurface
00640 # undef SELF
00641 # endif // SHAPE_IMPLICITCELL_H