00001
00002
00003
00004 #ifndef BFACE_H_HAS_BEEN_INCLUDED
00005 #define BFACE_H_HAS_BEEN_INCLUDED
00006
00007 #include "bvert.H"
00008
00009
00010 class EdgeStrip;
00011 class Patch;
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 class Bface : public Bsimplex {
00029 public:
00030
00031
00032
00033 enum {
00034 BAD_BIT = Bsimplex::NEXT_AVAILABLE_BIT,
00035 VALID_NORMAL_BIT,
00036 FRONT_FACING_BIT,
00037 SECONDARY_BIT,
00038 NEXT_AVAILABLE_BIT
00039 };
00040
00041
00042 Bface(Bvert*, Bvert*, Bvert*, Bedge*, Bedge*, Bedge*);
00043 virtual ~Bface();
00044
00045
00046
00047 Bvert *v1() const { return _v1; }
00048 Bvert *v2() const { return _v2; }
00049 Bvert *v3() const { return _v3; }
00050 Bvert *v(int i) const { return (i>0&&i<4)?(&_v1)[i-1]:0; }
00051
00052
00053 Bedge *e1() const { return _e1; }
00054 Bedge *e2() const { return _e2; }
00055 Bedge *e3() const { return _e3; }
00056 Bedge *e(int i) const { return (i>0&&i<4)?(&_e1)[i-1]:0; }
00057
00058
00059 CWvec& norm() const {
00060 if (!is_set(VALID_NORMAL_BIT))
00061 ((Bface*)this)->set_normal();
00062 return _norm;
00063 }
00064
00065
00066
00067
00068 CWvec& vert_normal(CBvert* v, Wvec& n) const;
00069 Wvec vert_normal(CBvert* v) const {
00070 Wvec n;
00071 return vert_normal(v, n);
00072 }
00073
00074
00075 int front_facing() const;
00076
00077 bool zx_mark() const;
00078 bool zx_query() const;
00079
00080 Patch* patch() const { return _patch; }
00081
00082
00083
00084 void orient_strip(Bvert* a) { _orient = a; }
00085 Bvert* orient_strip() const { return _orient; }
00086
00087
00088
00089 int vindex(CBvert* v) const {
00090 return (v==_v1) ? 1 : (v==_v2) ? 2 : (v==_v3) ? 3 : -1;
00091 }
00092
00093
00094 bool contains(CBvert* v) const { return (v==_v1 || v==_v2 || v==_v3); }
00095 bool contains(CBedge* e) const { return (e==_e1 || e==_e2 || e==_e3); }
00096 bool contains(CBsimplex* s) const {
00097 if (s->dim()==1) return contains( (CBedge*)s );
00098 if (s->dim()==0) return contains( (CBvert*)s );
00099 return 0;
00100 }
00101 bool contains(CWpt& pt, double threshold=0) const ;
00102
00103 Bvert* other_vertex(CBvert* u, CBvert* v) const {
00104 return (!(contains(u) && contains(v)) ? 0 :
00105 (u==_v1) ? ((v==_v2) ? _v3 : (v==_v3) ? _v2 : 0) :
00106 (u==_v2) ? ((v==_v1) ? _v3 : (v==_v3) ? _v1 : 0) :
00107 (u==_v3) ? ((v==_v1) ? _v2 : (v==_v2) ? _v1 : 0) :
00108 0);
00109 }
00110 Bvert* other_vertex(CBedge* e) const {
00111 return e ? other_vertex(e->v1(), e->v2()) : (Bvert*)0;
00112 }
00113 Bvert* next_vert_ccw(CBvert* u) const {
00114 return (u==_v1) ? _v2 : (u==_v2) ? _v3 : (u==_v3) ? _v1 : 0;
00115 }
00116
00117
00118
00119 Bvert* leading_vert_ccw(CBedge* e) const {
00120 return (
00121 e ? ((next_vert_ccw(e->v1()) == e->v2()) ? e->v1() : e->v2()) : 0
00122 );
00123 }
00124
00125 Bedge* next_edge_ccw(CBedge* u) const {
00126 return (u==_e1) ? _e2 : (u==_e2) ? _e3 : (u==_e3) ? _e1 : 0;
00127 }
00128 Bedge* edge_from_vert(CBvert* u) const {
00129 return (u==_v1) ? _e1 : (u==_v2) ? _e2 : (u==_v3) ? _e3 : 0;
00130 }
00131 Bedge* edge_before_vert(CBvert* u) const {
00132 return (u==_v1) ? _e3 : (u==_v2) ? _e1 : (u==_v3) ? _e2 : 0;
00133 }
00134 Bface* next_face_ccw(CBvert* u) const {
00135 return edge_before_vert(u)->other_face(this);
00136 }
00137
00138
00139 Bface* nbr(int i) const {
00140 Bedge* ei = e(i);
00141 return ei ? ei->other_face(this) : 0;
00142 }
00143
00144
00145 Bedge* shared_edge(CBface* f) const {
00146 return ((_e1->other_face(this) == f) ? _e1 :
00147 (_e2->other_face(this) == f) ? _e2 :
00148 (_e3->other_face(this) == f) ? _e3 :
00149 0);
00150 }
00151
00152 Bedge* opposite_edge(CBvert* a) const {
00153 return ((a == _v1) ? _e2 :
00154 (a == _v2) ? _e3 :
00155 (a == _v3) ? _e1 : 0
00156 );
00157 }
00158 Bface* opposite_face(CBvert* a) const {
00159 Bedge* e = opposite_edge(a);
00160 return e ? e->other_face(this) : 0;
00161 }
00162 Bface* next_strip_face() const {
00163 CBedge* e = opposite_edge(orient_strip());
00164 return (e && e->is_crossable()) ? e->other_face(this) : 0;
00165 }
00166 Bedge* other_edge(CBvert* v, CBedge* e) const {
00167 return ((_e1 != e && _e1->contains(v)) ? _e1 :
00168 (_e2 != e && _e2->contains(v)) ? _e2 :
00169 (_e3 != e && _e3->contains(v)) ? _e3 :
00170 0);
00171 }
00172
00173 int orientation(CBedge* e) const {
00174 return (contains(e) ? (next_vert_ccw(e->v1()) == e->v2() ? 1 : -1) : 0);
00175 }
00176
00177
00178
00179
00180 bool is_bad() const { return is_set(BAD_BIT); }
00181
00182
00183
00184 bool is_primary() const { return is_clear(SECONDARY_BIT); }
00185 bool is_secondary() const { return !is_primary(); }
00186
00187 ushort layer() const { return _layer; }
00188 virtual void set_layer(ushort l) { _layer = l; }
00189
00190
00191
00192
00193
00194 virtual void make_primary();
00195 virtual void make_secondary();
00196
00197
00198 double area() const {
00199 if (!is_set(VALID_NORMAL_BIT))
00200 ((Bface*)this)->set_normal();
00201 return _area;
00202 }
00203 double volume_el() const {
00204 CWpt& a = _v1->loc();
00205 CWpt& b = _v2->loc();
00206 CWpt& c = _v3->loc();
00207
00208 double nx = (b[1] - a[1])*(c[2] - a[2]) - (c[1] - a[1])*(b[2] - a[2]);
00209 return (nx * (a[0] + b[0] + c[0]) / 6.0);
00210 }
00211 double angle(CBvert* v) const {
00212 if (!contains(v))
00213 return 0;
00214 Bvert* a = next_vert_ccw(v);
00215 Bvert* b = next_vert_ccw(a);
00216 return (v->loc() - a->loc()).angle(v->loc() - b->loc());
00217 }
00218
00219 Wpt centroid() const { return (_v1->loc()+_v2->loc()+_v3->loc())/3;}
00220 NDCZpt ndc_centroid() const { return (_v1->ndc()+_v2->ndc()+_v3->ndc())/3;}
00221 Wplane plane() const { return Wplane(_v1->loc(), norm()); }
00222
00223 double signed_area(CWpt& a, CWpt& b, CWpt& c) const {
00224 return 0.5 * (cross(b-a,c-a) * norm());
00225 }
00226 double signed_area(CNDCpt& a, CNDCpt& b, CNDCpt& c) const {
00227 return 0.5 * det(b-a,c-a);
00228 }
00229
00230 double ndc_area() const {
00231 NDCpt a = _v1->ndc();
00232 NDCpt b = _v2->ndc();
00233 NDCpt c = _v3->ndc();
00234 return fabs(signed_area(a,b,c));
00235 }
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245 int num_weak_edges() const {
00246 return (
00247 (_e1->is_weak() ? 1 : 0) +
00248 (_e2->is_weak() ? 1 : 0) +
00249 (_e3->is_weak() ? 1 : 0)
00250 );
00251 }
00252 bool is_quad() const { return (num_weak_edges() == 1); }
00253 Bedge* weak_edge() const {
00254 return (_e1->is_weak() ? _e1 :
00255 _e2->is_weak() ? _e2 :
00256 _e3->is_weak() ? _e3 : 0
00257 );
00258 }
00259
00260
00261 Bface* quad_partner() const {
00262 return is_quad() ? weak_edge()->other_face(this) : (Bface*)0;
00263 }
00264
00265
00266
00267 Bface* quad_rep() const {
00268 return min((Bface*)this, quad_partner());
00269 }
00270
00271
00272 bool is_quad_rep() const { return is_quad() && quad_rep() == this; }
00273
00274 Bvert* quad_vert() const {
00275 return is_quad() ? weak_edge()->opposite_vert(this) : (Bvert*)0;
00276 }
00277 Bvert* quad_opposite_vert(CBvert* v) const {
00278 Bedge* e = weak_edge();
00279 if (!e) return 0;
00280 if (e->contains(v))
00281 return e->other_vertex(v);
00282 if (contains(v))
00283 return e->opposite_vert(this);
00284 Bface* f = quad_partner();
00285 return f && f->contains(v) ? e->opposite_vert(f) : 0;
00286 }
00287
00288
00289 Bedge* opposite_quad_edge(CBedge* e) const {
00290 if (is_quad()) {
00291 Bvert* u1=other_vertex(e->v1(), e->v2());
00292 Bvert* u2=quad_vert();
00293 return u1->lookup_edge(u2);
00294 }
00295 else
00296 return 0;
00297 }
00298
00299
00300 Bface* other_quad_face(CBedge *e) const {
00301
00302
00303 if (!e) return 0;
00304
00305
00306
00307 if ((this!=e->f1())&&(this!=e->f2()))
00308 {
00309 return e->other_face(this->quad_partner());
00310 }
00311
00312 return e->other_face(this);
00313 }
00314
00315
00316 double quad_area() const {
00317 return area() + quad_partner()->area();
00318 }
00319 double quad_ndc_area() const {
00320 return ndc_area() + quad_partner()->ndc_area();
00321 }
00322 Wpt quad_centroid() const {
00323 return (_v1->loc() + _v2->loc() +
00324 _v3->loc() + quad_vert()->loc())*0.25;
00325 }
00326 NDCZpt ndc_quad_centroid() const {
00327 return (_v1->ndc() + _v2->ndc() +
00328 _v3->ndc() + quad_vert()->ndc())*0.25;
00329 }
00330 Wvec quad_norm() const {
00331 return (norm() + quad_partner()->norm()).normalized();
00332 }
00333
00334 Wvec qnorm() const { return is_quad() ? quad_norm() : norm(); }
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 bool get_quad_verts(Bvert*& a, Bvert*& b, Bvert*& c, Bvert*& d) const;
00351 bool get_quad_verts(Bvert_list& verts) const;
00352 bool get_quad_pts(Wpt& a, Wpt& b, Wpt& c, Wpt& d) const;
00353
00354 bool get_quad_edges(Bedge*& ab, Bedge*& bc, Bedge*& cd, Bedge*& da) const;
00355 bool get_quad_edges(Bedge_list& edges) const;
00356
00357
00358
00359
00360 Wvec quad_tan1() const;
00361 Wvec quad_tan2() const;
00362
00363
00364
00365
00366 double quad_dim1() const;
00367 double quad_dim2() const;
00368
00369
00370 double quad_avg_dim() const { return (quad_dim1() + quad_dim2())/2; }
00371 double quad_max_dim() const { return max(quad_dim1(), quad_dim2()); }
00372 double quad_min_dim() const { return min(quad_dim1(), quad_dim2()); }
00373
00374
00375
00376 UVpt quad_bc_to_uv(CWvec& bc) const;
00377
00378
00379
00380 Wpt quad_uv2loc(CUVpt& uv) const;
00381
00382
00383
00384
00385
00386
00387
00388
00389 UVpt &tex_coord(int vert_index) const {
00390
00391
00392 assert (vert_index > 0 || vert_index < 4);
00393 return (_tc?(_tc):(((Bface*)this)->_tc = new UVpt[3]))[vert_index - 1];
00394 }
00395 UVpt &tex_coord(CBvert* v) const { return tex_coord(vindex(v)); }
00396
00397
00398 void set_tex_coords(CUVpt& a, CUVpt& b, CUVpt& c) {
00399 tex_coord(1) = a; tex_coord(2) = b; tex_coord(3) = c;
00400 }
00401
00402 UVpt* tc_array() const { return _tc; }
00403
00404
00405
00406 virtual void project_barycentric(CWpt& p, Wvec& ret) const {
00407 double u = signed_area(p, _v2->loc(), _v3->loc()) / area();
00408 double v = signed_area(_v1->loc(), p, _v3->loc()) / area();
00409 ret.set(u, v, 1 - u - v);
00410 }
00411
00412
00413 void project_barycentric_ndc(CNDCpt& p, Wvec& ret) const {
00414 NDCpt a = _v1->ndc(), b = _v2->ndc(), c = _v3->ndc();
00415 double A = signed_area(a, b, c);
00416 double u = signed_area(p, b, c) / A;
00417 double v = signed_area(a, p, c) / A;
00418 ret.set(u, v, 1 - u - v);
00419 }
00420
00421 virtual void bc2pos(CWvec& bc, Wpt& pos) const {
00422 pos = (bc[0]*_v1->loc()) + (bc[1]*_v2->loc()) + (bc[2]*_v3->loc());
00423 }
00424
00425 virtual void bc2norm_blend(CWvec& bc, Wvec& vec) const {
00426 Wvec v1,v2,v3;
00427 vert_normal(_v1,v1);
00428 vert_normal(_v2,v2);
00429 vert_normal(_v3,v3);
00430 vec = ((bc[0]*v1) +
00431 (bc[1]*v2) +
00432 (bc[2]*v3)).normalized();
00433 }
00434
00435 virtual Bsimplex* bc2sim(CWvec& bc) const;
00436
00437
00438 Bvert* bc2vert(CWvec& bc) const {
00439 double max = 0;
00440 int best_v;
00441 for (int i=0; i<3; i++)
00442 if (bc[i] >= max) {
00443 max = bc[i];
00444 best_v = i;
00445 }
00446 return v(best_v+1);
00447 }
00448
00449
00450 Bedge* bc2edge(CWvec& bc) const {
00451 double min = 1;
00452 int best_v;
00453 for (int i=0; i<3; i++)
00454 if (bc[i] <= min) {
00455 min = bc[i];
00456 best_v = i;
00457 }
00458 return opposite_edge(v(best_v+1));
00459 }
00460
00461 Wvec bc2norm(CWvec& bc) const {
00462 Bsimplex* sim = bc2sim(bc);
00463 return (is_vert(sim) ? ((Bvert*)sim)->norm() :
00464 is_edge(sim) ? ((Bedge*)sim)->norm() :
00465 norm()
00466 );
00467 }
00468
00469
00470
00471
00472
00473
00474
00475
00476 virtual bool view_intersect(
00477 CNDCpt&,
00478 Wpt&,
00479 double&,
00480 double&,
00481 Wvec& n
00482 ) const;
00483
00484
00485
00486 Wpt near_pt(CNDCpt& ndc, Wvec& hit_bc) const;
00487
00488
00489 Wpt near_pt(CNDCpt& ndc) const {
00490 Wvec hit_bc;
00491 return near_pt(ndc, hit_bc);
00492 }
00493
00494
00495
00496 bool ray_intersect(CWpt&, CWvec&, Wpt& ret, double& depth) const;
00497 bool ray_intersect(CWline& ray, Wpt& ret, double& depth) const {
00498 return ray_intersect(ray.point(), ray.vector(), ret, depth);
00499 }
00500
00501 bool ray_intersect(CWline& ray, Wvec& bc) const {
00502 Wpt hit; double depth;
00503 if (ray_intersect(ray, hit, depth)) {
00504 project_barycentric(hit, bc);
00505 return 1;
00506 }
00507 return 0;
00508 }
00509
00510
00511 Wpt plane_intersect(CWline& line) const {
00512 return plane().intersect(line);
00513 }
00514 Wpt plane_intersect(CNDCpt& ndc) const {
00515 return plane_intersect(Wline(XYpt(ndc)));
00516 }
00517 Bsimplex* find_intersect_sim(CNDCpt& target, Wpt& hit_pt) const;
00518
00519 bool ndc_contains(CNDCpt &p) {
00520 NDCpt a(_v1->ndc());
00521 NDCpt b(_v2->ndc());
00522 NDCpt c(_v3->ndc());
00523 return (det(b-a, p-a) * det(p-a, c-a) >= 0) &&
00524 (det(c-b, p-b) * det(p-b, a-b) >= 0);
00525 }
00526
00527 Bface* plane_walk(Bedge* cur_edge, CWplane& plane, Bedge*& next_edge) const;
00528
00529
00530
00531
00532
00533 NDCpt nearest_pt_ndc(CNDCpt& p, Wvec &bc, int &is_on_tri) const;
00534 NDCpt nearest_pt_ndc(CNDCpt& p, Wvec &bc) const {
00535 int i; return nearest_pt_ndc(p, bc, i);
00536 }
00537 NDCpt nearest_pt_ndc(CNDCpt& p) const {
00538 Wvec bc; return nearest_pt_ndc(p, bc);
00539 }
00540
00541
00542
00543
00544
00545 virtual Wpt nearest_pt(CWpt& p, Wvec &bc, bool &is_on_tri) const;
00546
00547
00548 virtual int detach();
00549 virtual void reverse();
00550
00551 int redefine(Bvert *v, Bvert *u);
00552 int redefine(Bvert *u, Bvert *nu, Bvert *v, Bvert *nv);
00553
00554
00555
00556
00557
00558 virtual bool redef2(Bvert *a, Bvert *b);
00559
00560
00561
00562
00563 virtual bool redef2(Bedge *a, Bedge *b);
00564
00565
00566
00567 bool check() const;
00568
00569
00570 virtual void geometry_changed();
00571 virtual void normal_changed();
00572
00573
00574 friend ostream &operator <<(ostream &os, CBface &f) {
00575 return os << f.v(1)->index() << " "
00576 << f.v(2)->index() << " "
00577 << f.v(3)->index() << endl;
00578 }
00579 friend STDdstream &operator <<(STDdstream &d, CBface &f) {
00580 return d << f.v(1)->index() << f.v(2)->index() << f.v(3)->index();
00581 }
00582
00583
00584
00585
00586 virtual int dim() const { return 2; }
00587
00588
00589 virtual int index() const;
00590
00591 virtual Bface* get_face() const { return (Bface*)this; }
00592 virtual bool on_face(CBface* f) const { return f == this; }
00593
00594
00595
00596 virtual Bsimplex_list neighbors() const;
00597
00598
00599 bool local_search(Bsimplex *&end, Wvec &final_bc,
00600 CWpt &target, Wpt &reached,
00601 Bsimplex *repeater = 0, int iters = 30);
00602
00603
00604
00605
00606 protected:
00607 friend class Patch;
00608
00609 Bvert* _v1;
00610 Bvert* _v2;
00611 Bvert* _v3;
00612 Bedge* _e1;
00613 Bedge* _e2;
00614 Bedge* _e3;
00615 Wvec _norm;
00616 double _area;
00617 Patch* _patch;
00618 int _patch_index;
00619 Bvert* _orient;
00620 uint _ff_stamp;
00621 uint _zx_stamp;
00622 UVpt* _tc;
00623 ushort _layer;
00624
00625
00626
00627 virtual void set_patch(Patch* p) { _patch = p; }
00628 void set_patch_index(int k) { _patch_index = k; }
00629 int patch_index() const { return _patch_index; }
00630
00631
00632
00633 Bsimplex* ndc_walk(CNDCpt& target, CWvec &bc=Wvec(),
00634 CNDCpt &nearest=NDCpt(),
00635 int is_on_tri=0, bool use_passed_in_params=false) const;
00636
00637
00638 void set_normal() {
00639 set_bit(VALID_NORMAL_BIT,1);
00640 _norm = (cross(_v2->loc()-_v1->loc(),_v3->loc()-_v1->loc())).normalized();
00641 _area = signed_area(_v1->loc(),_v2->loc(),_v3->loc());
00642 }
00643 };
00644
00645
00646
00647
00648
00649
00650 inline Bface*
00651 bface(Bsimplex* sim)
00652 {
00653 return is_face(sim) ? (Bface*)sim : 0;
00654 }
00655
00656 inline Bface*
00657 lookup_face(CBedge* e, CBvert* v)
00658 {
00659 return (e && v) ? e->lookup_face(v) : 0;
00660 }
00661
00662 inline Bface*
00663 lookup_face(CBedge* a, CBedge* b)
00664 {
00665 return (a && b) ? a->lookup_face(b) : 0;
00666 }
00667
00668 inline Bface*
00669 lookup_face(CBvert* a, CBvert* b, CBvert* c)
00670 {
00671 Bedge* e = a ? a->lookup_edge(b) : 0;
00672
00673 return e ? e->lookup_face(c) : 0;
00674 }
00675
00676 inline Bvert*
00677 next_vert_ccw(CBface* f, CBvert* v)
00678 {
00679
00680
00681
00682
00683 return f ? f->next_vert_ccw(v) : 0;
00684 }
00685
00686 inline Bface*
00687 ccw_face(CBedge* e, CBvert* v)
00688 {
00689
00690
00691
00692
00693
00694 Bvert* u = e ? e->other_vertex(v) : 0;
00695
00696 return ((u == 0) ? 0 :
00697 (next_vert_ccw(e->f1(),v) == u) ? e->f1() :
00698 (next_vert_ccw(e->f2(),v) == u) ? e->f2() :
00699 0);
00700 }
00701
00702 inline Bface*
00703 ccw_face(CBedge* e)
00704 {
00705 return e ? ccw_face(e, e->v1()) : 0;
00706 }
00707
00708 inline void
00709 reverse_faces(CARRAY<Bface*>& faces)
00710 {
00711 for (int k=faces.num()-1; k>=0; k--)
00712 faces[k]->reverse();
00713 }
00714
00715
00716
00717 inline Bvert*
00718 closest_vert(Bface* f, CWpt& p)
00719 {
00720 if (!f) return 0;
00721 double d1 = f->v1()->wloc().dist(p);
00722 double d2 = f->v2()->wloc().dist(p);
00723 double d3 = f->v3()->wloc().dist(p);
00724 if (d1 < d2)
00725 return (d3 < d1) ? f->v3() : f->v1();
00726 else
00727 return (d3 < d2) ? f->v3() : f->v2();
00728 }
00729
00730
00731 inline Bvert*
00732 closest_vert(Bface* f, CNDCpt& p)
00733 {
00734 if (!f) return 0;
00735 double d1 = NDCpt(f->v1()->wloc()).dist(p);
00736 double d2 = NDCpt(f->v2()->wloc()).dist(p);
00737 double d3 = NDCpt(f->v3()->wloc()).dist(p);
00738 if (d1 < d2)
00739 return (d3 < d1) ? f->v3() : f->v1();
00740 else
00741 return (d3 < d2) ? f->v3() : f->v2();
00742 }
00743
00744
00745
00746
00747 class FrontFacingBfaceFilter : public SimplexFilter {
00748 public:
00749 virtual bool accept(CBsimplex* s) const {
00750 return is_face(s) && ((Bface*)s)->front_facing();
00751 }
00752 };
00753
00754 class PrimaryFaceFilter : public SimplexFilter {
00755 public:
00756 virtual bool accept(CBsimplex* s) const {
00757 return is_face(s) && ((Bface*)s)->is_primary();
00758 }
00759 };
00760
00761 class SecondaryFaceFilter : public SimplexFilter {
00762 public:
00763 virtual bool accept(CBsimplex* s) const {
00764 return is_face(s) && ((Bface*)s)->is_secondary();
00765 }
00766 };
00767
00768 class QuadFaceFilter : public SimplexFilter {
00769 public:
00770 virtual bool accept(CBsimplex* s) const {
00771 return is_face(s) && ((Bface*)s)->is_quad();
00772 }
00773 };
00774
00775 class QuadRepFaceFilter : public SimplexFilter {
00776 public:
00777 virtual bool accept(CBsimplex* s) const {
00778 return is_face(s) && ((Bface*)s)->is_quad_rep();
00779 }
00780 };
00781
00782
00783
00784
00785 class Bface_list;
00786 typedef const Bface_list CBface_list;
00787 class Bface_list : public SimplexArray<Bface_list,Bface*> {
00788 public:
00789
00790
00791
00792 Bface_list(CARRAY<Bface*>& list) : SimplexArray<Bface_list,Bface*>(list) {}
00793 explicit Bface_list(int n=0) : SimplexArray<Bface_list,Bface*>(n) {}
00794 explicit Bface_list(Bface* f) : SimplexArray<Bface_list,Bface*>(f) {
00795 if (f && f->is_quad())
00796 add(f->quad_partner());
00797 }
00798
00799
00800
00801
00802
00803 Bvert_list get_verts() const;
00804 Bedge_list get_edges() const;
00805
00806
00807
00808
00809 Wvec avg_normal() const;
00810
00811
00812
00813 double max_norm_deviation(CWvec& n) const;
00814
00815
00816
00817 bool is_planar(double max_angle) const {
00818 return(max_norm_deviation(avg_normal()) < max_angle);
00819 }
00820
00821
00822
00823
00824
00825
00826
00827 double volume() const;
00828
00829
00830
00831
00832
00833
00834 bool is_connected() const;
00835
00836
00837
00838 bool is_consistently_oriented() const;
00839
00840
00841
00842 bool is_2_manifold() const;
00843
00844
00845
00846 bool is_disk() const;
00847
00848
00849 void reverse_faces() const {
00850 for (int k=0; k<_num; k++)
00851 _array[k]->reverse();
00852 }
00853
00854
00855
00856 EdgeStrip get_boundary() const;
00857
00858 Bedge_list boundary_edges() const;
00859 Bedge_list interior_edges() const;
00860 Bvert_list interior_verts() const;
00861
00862
00863
00864
00865 Bface_list one_ring_faces() const { return get_verts().one_ring_faces(); }
00866
00867
00868 Bface_list exterior_faces() const;
00869
00870
00871 Bface_list two_ring_faces() const { return one_ring_faces().one_ring_faces();}
00872
00873
00874 Bface_list n_ring_faces(int n) {
00875 Bface_list ret = *this;
00876 for (int i=0; i<n; i++)
00877 ret = ret.one_ring_faces();
00878 return ret;
00879 }
00880
00881
00882
00883 Bface_list quad_complete_faces() const;
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894 static Bface_list reachable_faces(Bface* f, CSimplexFilter& =BedgeFilter());
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907 bool grow_connected(Bface* f, CSimplexFilter& =BedgeFilter());
00908
00909
00910
00911
00912
00913
00914 bool push_layer(bool push_boundary=true) const;
00915
00916
00917 bool can_push_layer() const;
00918
00919
00920 bool unpush_layer(bool unpush_boundary=true) const;
00921
00922
00923 bool can_unpush_layer() const;
00924
00925
00926 void make_primary() const {
00927 for (int i=0; i<_num; i++)
00928 _array[i]->make_primary();
00929 }
00930
00931
00932
00933 void make_secondary() const {
00934 for (int i=0; i<_num; i++)
00935 _array[i]->make_secondary();
00936 }
00937
00938
00939
00940 Bface_list secondary_faces() const{
00941 return filter(BitSetSimplexFilter(Bface::SECONDARY_BIT));
00942 }
00943 Bface_list primary_faces() const{
00944 return filter(BitClearSimplexFilter(Bface::SECONDARY_BIT));
00945 }
00946
00947 bool is_all_primary() const {
00948 return all_satisfy(BitClearSimplexFilter(Bface::SECONDARY_BIT));
00949 }
00950 bool is_all_secondary() const {
00951 return all_satisfy(BitSetSimplexFilter(Bface::SECONDARY_BIT));
00952 }
00953 bool has_any_primary() const {
00954 return any_satisfy(BitClearSimplexFilter(Bface::SECONDARY_BIT));
00955 }
00956 bool has_any_secondary() const {
00957 return any_satisfy(BitSetSimplexFilter(Bface::SECONDARY_BIT));
00958 }
00959 bool num_primary() const {
00960 return num_satisfy(BitClearSimplexFilter(Bface::SECONDARY_BIT))!=0;
00961 }
00962 bool num_secondary() const {
00963 return num_satisfy(BitSetSimplexFilter(Bface::SECONDARY_BIT))!=0;
00964 }
00965
00966 protected:
00967
00968
00969 void clear_vert_flags() const;
00970 void clear_edge_flags() const;
00971
00972
00973
00974 void mark_faces() const;
00975 };
00976
00977
00978
00979
00980 inline Bface_list
00981 Bvert::get_all_faces() const
00982 {
00983 Bface_list ret;
00984 get_all_faces(ret);
00985 return ret;
00986 }
00987
00988 inline Bface_list
00989 Bvert::get_faces() const
00990 {
00991 Bface_list ret;
00992 get_faces(ret);
00993 return ret;
00994 }
00995
00996
00997
00998
00999 inline void
01000 Bedge::clear_flag02()
01001 {
01002
01003
01004
01005 clear_flag();
01006 if (_f1) _f1->clear_flag();
01007 if (_f2) _f2->clear_flag();
01008 if (_adj) _adj->clear_flags();
01009 }
01010
01011 inline int
01012 Bedge::num_quads() const
01013 {
01014 return (
01015 (_f1 && _f1->is_quad() ? 1 : 0) +
01016 (_f2 && _f2->is_quad() ? 1 : 0)
01017 );
01018 }
01019
01020 inline Bface*
01021 Bedge::screen_face(CSimplexFilter& filter) const
01022 {
01023
01024
01025 return (
01026 filter.accept(_f1) ? _f1 :
01027 filter.accept(_f2) ? _f2 :
01028 _adj ? _adj->first_satisfies(filter) : 0
01029 );
01030 }
01031
01032 inline bool
01033 Bedge::is_primary() const
01034 {
01035
01036
01037 return ((_f1 && _f1->is_primary()) || (_f2 && _f2->is_primary()));
01038 }
01039
01040 inline Bvert*
01041 Bedge::opposite_vert(CBface* f) const
01042 {
01043
01044
01045
01046
01047 Bface* g = other_face(f);
01048 return g ? g->other_vertex(_v1,_v2) : 0;
01049 }
01050
01051 inline bool
01052 Bedge::contains(CBface* f) const
01053 {
01054 return (_f1 == f || _f2 == f || (_adj && _adj->contains((Bface*)f)));
01055 }
01056
01057
01058
01059
01060 inline Bface_list
01061 Bedge_list::get_primary_faces() const
01062 {
01063 return get_faces().primary_faces();
01064 }
01065
01066
01067
01068
01069
01070
01071 class PrimaryVertFilter : public SimplexFilter {
01072 public:
01073 virtual bool accept(CBsimplex* s) const {
01074 return is_vert(s) &&
01075 !((Bvert*)s)->get_all_faces().primary_faces().empty();
01076 }
01077 };
01078
01079 #endif // BFACE_H_HAS_BEEN_INCLUDED
01080
01081