00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 # ifndef shape_cell3d_algebraic_surface_hpp
00014 # define shape_cell3d_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/cell3d.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 cell3d_algebraic_surface<C,V>
00029 # undef Topology
00030
00031 namespace mmx { namespace shape {
00032
00033
00034
00035
00036
00037
00038
00039 struct cell3d_algebraic_surface_def {};
00040
00041 template<> struct use<cell3d_algebraic_surface_def>
00042
00043
00044 {
00045 typedef Interval< double > Scalar;
00046 typedef polynomial< double, with<Bernstein> > Polynomial;
00047
00048
00049
00050 };
00051
00052
00053 template<class C, class V=default_env>
00054 struct cell3d_algebraic_surface : public cell3d<C,V> {
00055 public:
00056
00057 typedef REF_OF(V) Ref;
00058 typedef tpl3d<C,V> Topology3d;
00059 typedef topology<C,V> Topology;
00060
00061 typedef typename use<mesh3d_def,C,V>::Point Point;
00062 typedef typename Topology::Edge Edge;
00063 typedef typename Topology::Face Face;
00064
00065 typedef cell3d<C,V> Cell;
00066 typedef cell3d<C,V> CellBase;
00067 typedef cell3d<C,V> Cell3d;
00068
00069 typedef bounding_box<C,V> BoundingBox;
00070
00071 typedef algebraic_surface<C,V> AlgebraicSurface;
00072
00073 typedef typename use<cell3d_algebraic_surface_def,C,V>::Polynomial Polynomial;
00074
00075
00076
00077
00078 typedef solver_implicit<C,V> Solver;
00079
00080 cell3d_algebraic_surface(const SELF&);
00081 cell3d_algebraic_surface(const Polynomial&, const BoundingBox& );
00082 cell3d_algebraic_surface(char*, const BoundingBox& );
00083
00084 cell3d_algebraic_surface(const AlgebraicSurface&, const BoundingBox&);
00085 cell3d_algebraic_surface(AlgebraicSurface *, const BoundingBox&);
00086
00087 virtual bool is_regular(void);
00088 virtual bool is_active (void) const;
00089
00090 template<class CELL>
00091 void split (CELL*& left, CELL*& right, int v, double s);
00092 virtual void subdivide(Cell*& left, Cell*& right, int v, double s);
00093
00094 int mc_index(void) const ;
00095 bool edge_point(Point**, int ) const ;
00096
00097 C value(const C& x, const C& y, const C& z) const;
00098 C center_value() const { return m_polynomial(0.5,0.5,0.5); }
00099 C lower_bound() const {return min_value<C>(m_polynomial.begin(), m_polynomial.end());}
00100 C upper_bound() const {return max_value<C>(m_polynomial.begin(), m_polynomial.end());}
00101
00102 double vertex_eval(unsigned sx, unsigned sy, unsigned sz) const;
00103 const Polynomial& equation() const {return m_polynomial;}
00104 Polynomial get_polynomial() const {return m_polynomial;}
00105
00106 void point(Point& r, const Point& A, const Point& B) const;
00107 public:
00108 Polynomial m_polynomial;
00109 Point* m_center;
00110 C m_center_value;
00111 int m_idx;
00112
00113
00114 };
00115
00116
00117 TMPL
00118 SELF::cell3d_algebraic_surface(const SELF& s)
00119 : Cell3d((BoundingBox)s), m_polynomial(s.equation()), m_center(0)
00120 {
00121
00122 }
00123
00124 TMPL
00125 SELF::cell3d_algebraic_surface(const Polynomial& pol, const BoundingBox& bx)
00126 : Cell3d(bx), m_polynomial(pol), m_center(0)
00127 {
00128
00129 }
00130
00131 TMPL
00132 SELF::cell3d_algebraic_surface(char* pol, const BoundingBox& bx)
00133 : Cell3d(bx), m_polynomial(pol), m_center(0)
00134 {
00135 }
00136
00137 TMPL
00138 SELF::cell3d_algebraic_surface(const AlgebraicSurface& sf, const BoundingBox& b): Cell3d(b), m_center(0)
00139 {
00140 Seq<mmx::GMP::rational> bx;
00141 bx<<as<mmx::GMP::rational>(b.xmin());
00142 bx<<as<mmx::GMP::rational>(b.xmax());
00143 bx<<as<mmx::GMP::rational>(b.ymin());
00144 bx<<as<mmx::GMP::rational>(b.ymax());
00145 bx<<as<mmx::GMP::rational>(b.zmin());
00146 bx<<as<mmx::GMP::rational>(b.zmax());
00147
00148 Polynomial tmp;
00149 tensor::bernstein<mmx::GMP::rational> polq(sf.equation().rep(),bx);
00150 let::assign(tmp.rep(),polq);
00151 m_polynomial=tmp;
00152
00153 }
00154
00155 TMPL bool
00156 SELF::is_active() const {
00157 return has_sign_variation(m_polynomial.begin(),m_polynomial.end());
00158 }
00159
00160 TMPL bool
00161 SELF::is_regular() {
00162 Polynomial dxf, dyf, dzf;
00163 Polynomial fp0, fp1;
00164 Polynomial bk, ft;
00165
00166
00167 tensor::face(bk, m_polynomial, 2, 0);
00168 if(Solver::edge_sign_var(bk, Solver::north_back_edge) >1) return false;
00169 if(Solver::edge_sign_var(bk, Solver::south_back_edge) >1) return false;
00170 if(Solver::edge_sign_var(bk, Solver::east_back_edge ) >1) return false;
00171 if(Solver::edge_sign_var(bk, Solver::west_back_edge ) >1) return false;
00172
00173
00174 tensor::face(ft, m_polynomial, 2, 1);
00175 if(Solver::edge_sign_var(ft, Solver::north_front_edge) >1) return false;
00176 if(Solver::edge_sign_var(ft, Solver::south_front_edge) >1) return false;
00177 if(Solver::edge_sign_var(ft, Solver::east_front_edge ) >1) return false;
00178 if(Solver::edge_sign_var(ft, Solver::west_front_edge ) >1) return false;
00179
00180 tensor::face(ft, equation(), 1, 1);
00181 if(Solver::edge_sign_var(ft, Solver::north_west_edge) >1) return false;
00182 if(Solver::edge_sign_var(ft, Solver::north_east_edge) >1) return false;
00183
00184 tensor::face(bk, equation(), 1, 0);
00185 if(Solver::edge_sign_var(bk, Solver::south_west_edge) >1) return false;
00186 if(Solver::edge_sign_var(bk, Solver::south_east_edge) >1) return false;
00187
00188 tensor::diff(dxf.rep(),m_polynomial.rep(),0);
00189 tensor::diff(dyf.rep(),m_polynomial.rep(),1);
00190 tensor::diff(dzf.rep(),m_polynomial.rep(),2);
00191
00192 if(!has_sign_variation(dxf.begin(),dxf.end())) {
00193
00194 this->m_idx=0;
00195 return true;
00196
00197 tensor::face(fp0, dyf, 0, 0);
00198 tensor::face(fp1, dyf, 0, 1);
00199 if(!has_sign_variation(fp0.begin(),fp0.end()) &&
00200 !has_sign_variation(fp1.begin(),fp1.end()) ) return true;
00201
00202 tensor::face(fp0, dzf, 0, 0);
00203 tensor::face(fp1, dzf, 0, 1);
00204 if(!has_sign_variation(fp0.begin(),fp0.end()) &&
00205 !has_sign_variation(fp1.begin(),fp1.end())) return true;
00206
00207 return false;
00208 }
00209
00210
00211 if(!has_sign_variation(dyf.begin(),dyf.end())) {
00212 this->m_idx=1;
00213 return true;
00214 }
00215
00216
00217 if(!has_sign_variation(dzf.begin(),dzf.end())) {
00218 this->m_idx=2;
00219 return true;
00220 }
00221
00222 return false;
00223 }
00224
00225 TMPL template<class CELL> void
00226 SELF::split(CELL*& left, CELL*& right, int v, double c) {
00227
00228
00229 if(v==0) {
00230 left = new CELL(m_polynomial, BoundingBox(this->xmin(),c, this->ymin(), this->ymax(), this->zmin(), this->zmax()));
00231 right= new CELL(m_polynomial, BoundingBox(c,this->xmax(), this->ymin(), this->ymax(), this->zmin(), this->zmax()));
00232 } else if (v==1) {
00233 left = new CELL(m_polynomial, BoundingBox(this->xmin(),this->xmax(), this->ymin(), c, this->zmin(), this->zmax()));
00234 right= new CELL(m_polynomial, BoundingBox(this->xmin(),this->xmax(), c, this->ymax(), this->zmin(), this->zmax()));
00235 } else {
00236 left = new CELL(m_polynomial, BoundingBox(this->xmin(),this->xmax(),this->ymin(),this->ymax(), this->zmin(), c));
00237 right= new CELL(m_polynomial, BoundingBox(this->xmin(),this->xmax(),this->ymin(),this->ymax(), c, this->zmax()));
00238 }
00239
00240
00241 tensor::split(left->m_polynomial, right->m_polynomial, v);
00242 }
00243
00244
00245 TMPL void
00246 SELF::subdivide(Cell*& Left, Cell*& Right, int v, double c) {
00247 SELF * left=0, * right=0;
00248 this->split(left,right,v,c);
00249 Left=left; Right=right;
00250 }
00251
00252
00253 TMPL C
00254 SELF::value(const C& x, const C& y, const C& z) const {
00255 return m_polynomial((x-this->xmin())/(this->xmax()-this->xmin()),
00256 (y-this->ymin())/(this->ymax()-this->ymin()),
00257 (z-this->zmin())/(this->zmax()-this->zmin()));
00258 }
00259
00260 TMPL double
00261 SELF::vertex_eval(unsigned sx, unsigned sy, unsigned sz) const {
00262
00263 int s=0;
00264 s+= sx*(m_polynomial.rep().env.sz(0)-1)*m_polynomial.rep().env.st(0);
00265 s+= sy*(m_polynomial.rep().env.sz(1)-1)*m_polynomial.rep().env.st(1);
00266 s+= sz*(m_polynomial.rep().env.sz(2)-1)*m_polynomial.rep().env.st(2);
00267 return m_polynomial[s];
00268 }
00269
00270
00271 TMPL int
00272 SELF::mc_index() const {
00273
00274 double isolevel = 0;
00275 int CubeIndex=0;
00276
00277 if (vertex_eval(0,1,0) <= isolevel) CubeIndex |= 1;
00278 if (vertex_eval(1,1,0) <= isolevel) CubeIndex |= 2;
00279 if (vertex_eval(1,0,0) <= isolevel) CubeIndex |= 4;
00280 if (vertex_eval(0,0,0) <= isolevel) CubeIndex |= 8;
00281 if (vertex_eval(0,1,1) <= isolevel) CubeIndex |= 16;
00282 if (vertex_eval(1,1,1) <= isolevel) CubeIndex |= 32;
00283 if (vertex_eval(1,0,1) <= isolevel) CubeIndex |= 64;
00284 if (vertex_eval(0,0,1) <= isolevel) CubeIndex |= 128;
00285
00286 return CubeIndex;
00287 }
00288
00289
00290 TMPL void
00291 SELF::point (Point& R, const Point& A, const Point& B) const {
00292
00293 Point U0((A.x()-this->xmin())/(this->xmax()-this->xmin()),
00294 (A.y()-this->ymin())/(this->ymax()-this->ymin()),
00295 (A.z()-this->zmin())/(this->zmax()-this->zmin())),
00296 U1((B.x()-this->xmin())/(this->xmax()-this->xmin()),
00297 (B.y()-this->ymin())/(this->ymax()-this->ymin()),
00298 (B.z()-this->zmin())/(this->zmax()-this->zmin()));
00299
00300 C f0 = this->m_polynomial(U0.x(), U0.y(), U0.z()),
00301 f1 = this->m_polynomial(U1.x(), U1.y(), U1.z());
00302
00303 Point M;
00304 if (abs(f0) < 0.00001) {
00305 M=U0;
00306 } else if (abs(f1) < 0.00001) {
00307 M=U1;
00308 } else if (abs(f1-f0) < 0.00001) {
00309 M=U0;
00310 } else {
00311
00312 C mu = - f0 / (f1 - f0);
00313
00314 M.x() = U0.x() + mu * (U1.x() - U0.x());
00315 M.y() = U0.y() + mu * (U1.y() - U0.y());
00316 M.z() = U0.z() + mu * (U1.z() - U0.z());
00317
00318 C fm = this->m_polynomial(M.x(),M.y(),M.z());
00319
00320 for(int i=0;i<10;i++) {
00321 if(f0*fm<0) {
00322 U1 = M; f1 = fm;
00323 } else {
00324 U0 = M; f0 = fm;
00325 }
00326 mu = - f0 / (f1 - f0);
00327 M.x() = U0.x() + mu * (U1.x() - U0.x());
00328 M.y() = U0.y() + mu * (U1.y() - U0.y());
00329 M.z() = U0.z() + mu * (U1.z() - U0.z());
00330
00331 fm = this->m_polynomial(M.x(),M.y(),M.z());
00332 }
00333 }
00334
00335 R.x()=this->xmin()+ M.x()*(this->xmax()-this->xmin());
00336 R.y()=this->ymin()+ M.y()*(this->ymax()-this->ymin());
00337 R.z()=this->zmin()+ M.z()*(this->zmax()-this->zmin());
00338
00339 }
00340
00341 TMPL bool
00342 SELF::edge_point(Point** CELL, int cube_index) const {
00343
00344 BoundingBox* bx = (BoundingBox*)this;
00345 Seq<Point*> F;
00346 Polynomial bk, ft;
00347
00348 tensor::face(bk, equation(), 2, 0);
00349 if (cube_index & 1) {
00350 Solver::edge_point(F, bk, Solver::north_back_edge, *bx);
00351 if(F.size()==0) {
00352 std::cout<<"Problem in MC0"<<std::endl;
00353 return false;
00354 } else
00355 CELL[0] = F[0];
00356 F.resize(0);
00357 }
00358 if (cube_index & 2) {
00359 Solver::edge_point(F, bk, Solver::east_back_edge , *bx);
00360 if(F.size()==0) {
00361 std::cout<<"Problem in MC1"<<std::endl;
00362 return false;
00363 } else
00364 CELL[1] = F[0];
00365 F.resize(0);
00366 }
00367 if (cube_index & 4) {
00368 Solver::edge_point(F, bk, Solver::south_back_edge, *bx);
00369 if(F.size()==0) {
00370 std::cout<<"Problem in MC2"<<std::endl;
00371 return false;
00372 } else
00373 CELL[2] = F[0];
00374 F.resize(0);
00375 }
00376 if (cube_index & 8) {
00377 Solver::edge_point(F, bk, Solver::west_back_edge , *bx);
00378 if(F.size()==0) {
00379 std::cout<<"Problem in MC3"<<std::endl;
00380 } else
00381 CELL[3] = F[0];
00382 F.resize(0);
00383 }
00384
00385 tensor::face(ft,equation(), 2, 1);
00386
00387 if (cube_index & 16) {
00388 Solver::edge_point(F, ft, Solver::north_front_edge, *bx);
00389 if(F.size()==0) {
00390 std::cout<<"Problem in MC4 "<<std::endl;
00391 return false;
00392 } else
00393 CELL[4] = F[0];
00394 F.resize(0);
00395 }
00396
00397 if (cube_index & 32) {
00398 Solver::edge_point(F, ft, Solver::east_front_edge , *bx);
00399 if(F.size()==0) {
00400 std::cout<<"Problem in MC5"<<std::endl;
00401 return false;
00402 } else
00403 CELL[5] = F[0];
00404 F.resize(0);
00405 }
00406
00407 if (cube_index & 64) {
00408 Solver::edge_point(F, ft, Solver::south_front_edge, *bx);
00409 if(F.size()==0) {
00410 std::cout<<"Problem in MC6"<<std::endl;
00411 return false;
00412 } else
00413 CELL[6] = F[0];
00414 F.resize(0);
00415 }
00416
00417 if (cube_index & 128) {
00418 Solver::edge_point(F, ft, Solver::west_front_edge , *bx);
00419 if(F.size()==0) {
00420 std::cout<<"Problem in MC7"<<std::endl;
00421 return false;
00422 } else
00423 CELL[7] = F[0];
00424 F.resize(0);
00425 }
00426
00427 tensor::face(ft, equation(), 1, 1);
00428 if (cube_index & 256) {
00429 Solver::edge_point(F, ft, Solver::north_west_edge, *bx);
00430 if(F.size()==0) {
00431 std::cout<<"Problem in MC8"<<std::endl;
00432 return false;
00433 } else
00434 CELL[8] = F[0];
00435 F.resize(0);
00436 }
00437
00438 if (cube_index & 512) {
00439 Solver::edge_point(F, ft, Solver::north_east_edge, *bx);
00440 if(F.size()==0) {
00441 std::cout<<"Problem in MC9"<<std::endl;
00442 return false;
00443 } else
00444 CELL[9] = F[0];
00445 F.resize(0);
00446 }
00447
00448 tensor::face(bk, equation(), 1, 0);
00449
00450 if (cube_index & 1024) {
00451 Solver::edge_point(F, bk, Solver::south_east_edge, *bx);
00452 if(F.size()==0) {
00453 std::cout<<"Problem in MC10"<<std::endl;
00454 return false;
00455 } else
00456 CELL[10] = F[0];
00457 F.resize(0);
00458 }
00459
00460 if (cube_index & 2048) {
00461 Solver::edge_point(F, bk, Solver::south_west_edge, *bx);
00462 if(F.size()==0) {
00463 std::cout<<"Problem in MC11"<<std::endl;
00464 return false;
00465 } else
00466 CELL[11] = F[0];
00467 F.resize(0);
00468 }
00469
00470 return true;
00471 }
00472
00473
00474 } ;
00475 } ;
00476 # undef TMPL
00477 # undef TMPL1
00478 # undef Point
00479 # undef Edge
00480 # undef AlgebraicSurface
00481 # undef SELF
00482 # endif // SHAPE_IMPLICITCELL_H