00001
00002
00003
00004 #include "mesh/patch.H"
00005 #include "mesh/mi.H"
00006 #include "mesh/uv_data.H"
00007 #include "std/config.H"
00008
00009 using namespace mlib;
00010
00011 Bface::Bface(Bvert* u, Bvert* v, Bvert* w,
00012 Bedge* e, Bedge* f, Bedge* g) :
00013 _v1(u), _v2(v), _v3(w),
00014 _e1(e), _e2(f), _e3(g),
00015 _area(0),
00016 _patch(0),
00017 _patch_index(-1),
00018 _orient(0),
00019 _ff_stamp(0),
00020 _zx_stamp(0),
00021 _tc(0),
00022 _layer(0)
00023 {
00024 *_e1 += this;
00025 *_e2 += this;
00026 *_e3 += this;
00027
00028 geometry_changed();
00029 }
00030
00031 Bface::~Bface()
00032 {
00033
00034 if (is_selected()) {
00035 MeshGlobal::deselect(this);
00036 }
00037
00038
00039 detach();
00040
00041
00042 if (_patch && _patch_index >= 0)
00043 _patch->remove(this);
00044 }
00045
00046 int
00047 Bface::index() const
00048 {
00049
00050
00051 if (!_mesh) return -1;
00052 return _mesh->faces().get_index((Bface*)this);
00053 }
00054
00055 void
00056 Bface::normal_changed()
00057 {
00058
00059
00060
00061 assert(0);
00062 }
00063
00064 void
00065 Bface::geometry_changed()
00066 {
00067
00068
00069
00070 _ff_stamp = 0;
00071 clear_bit(VALID_NORMAL_BIT);
00072
00073 _v1->normal_changed();
00074 _v2->normal_changed();
00075 _v3->normal_changed();
00076
00077 _e1->normal_changed();
00078 _e2->normal_changed();
00079 _e3->normal_changed();
00080
00081 Bsimplex::geometry_changed();
00082 }
00083
00084 bool
00085 Bface::zx_mark() const
00086 {
00087 bool ret = ( _zx_stamp == VIEW::stamp() );
00088 ((Bface*)this)->_zx_stamp = VIEW::stamp();
00089 return ret;
00090 }
00091
00092 bool
00093 Bface::zx_query() const
00094 {
00095 if ( _zx_stamp == VIEW::stamp() ) return true ;
00096 return false;
00097 }
00098
00099 int
00100 Bface::front_facing() const
00101 {
00102
00103
00104 static bool ignore_xf = Config::get_var_bool("SILS_IGNORE_MESH_XFORM",false);
00105
00106 if (_ff_stamp != VIEW::stamp()) {
00107 ((Bface*)this)->_ff_stamp = VIEW::stamp();
00108 int b = ((
00109 (ignore_xf ?
00110 VIEW::peek_cam()->data()->from() :
00111 _mesh->eye_local()
00112 ) - _v1->loc()) * norm()) > 0;
00113 ((Bface*)this)->set_bit(FRONT_FACING_BIT,b);
00114 }
00115 return is_set(FRONT_FACING_BIT);
00116 }
00117
00118 Bsimplex*
00119 Bface::find_intersect_sim(
00120 CNDCpt& target_pt,
00121 Wpt& hit_pt) const
00122 {
00123 Bsimplex* ret = ndc_walk(target_pt);
00124 if (is_face(ret))
00125 hit_pt =
00126 ((Bface*)ret)->plane_intersect(_mesh->inv_xform()*Wline(target_pt));
00127 else if(is_edge(ret))
00128 hit_pt =
00129 ((Bedge*)ret)->line().intersect(_mesh->inv_xform()*Wline(target_pt));
00130 else if (is_vert(ret))
00131 hit_pt = ((Bvert*)ret)->loc();
00132
00133 return ret;
00134 }
00135
00136
00137 bool
00138 Bface::contains(CWpt& pt,double threshold) const
00139 {
00140
00141
00142 const double dist_threshold=0.00001;
00143 if (plane().dist(pt) > dist_threshold)
00144 return false;
00145
00146 Wvec vec1 = (pt-v1()->loc()).normalized();
00147 Wvec vec2 = (pt-v2()->loc()).normalized();
00148 Wvec vec3 = (pt-v3()->loc()).normalized();
00149 Wvec ab = (v2()->loc()-v1()->loc()).normalized();
00150 Wvec bc = (v3()->loc()-v2()->loc()).normalized();
00151 Wvec ca = (v1()->loc()-v3()->loc()).normalized();
00152
00153 Wvec c1 = cross(ab,vec1).normalized();
00154 Wvec c2 = cross(bc,vec2).normalized();
00155 Wvec c3 = cross(ca,vec3).normalized();
00156
00157 Wvec n = cross(ab,bc).normalized();
00158
00159 if(c1*n<-threshold) return false;
00160 if(c2*n<-threshold) return false;
00161 if(c3*n<-threshold) return false;
00162
00163 return true;
00164 }
00165
00166
00167
00168
00169 Bsimplex*
00170 Bface::ndc_walk(
00171 CNDCpt& target,
00172 CWvec &passed_bc,
00173 CNDCpt &nearest,
00174 int is_on_tri,
00175 bool use_passed_in_params) const
00176 {
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189 NDCpt y (nearest);
00190 Wvec bc(passed_bc);
00191
00192 if (!use_passed_in_params) {
00193 y = nearest_pt_ndc(target, bc, is_on_tri);
00194 }
00195 Bsimplex* sim = bc2sim(bc);
00196
00197 if (is_on_tri) {
00198
00199
00200
00201 return sim;
00202 }
00203
00204 if (is_edge(sim)) {
00205 Bedge* e = (Bedge*)sim;
00206 Bface* f = e->is_sil() ? (Bface*)0 : e->other_face(this);
00207 if (f) {
00208 Wvec new_bc;
00209 int new_on_tri;
00210 NDCpt new_best = f->nearest_pt_ndc(target, new_bc, new_on_tri);
00211 if (new_best.dist_sqrd(target) < y.dist_sqrd(target))
00212 return f->ndc_walk(target, new_bc, new_best, new_on_tri, true);
00213 else
00214 return 0;
00215 } else {
00216 return 0;
00217 }
00218 }
00219
00220
00221 assert(is_vert(sim));
00222 Bvert* v = (Bvert*)sim;
00223 if (v->degree(SilEdgeFilter()) > 0)
00224 return 0;
00225
00226 Bface_list nbrs(16);
00227 ((Bvert*)sim)->get_faces(nbrs);
00228 double dist_sqrd = 1e50;
00229 Bface* best = 0;
00230 Wvec best_bc;
00231 NDCpt best_nearest;
00232 int best_on_tri = 0;
00233 Wvec curr_bc;
00234 NDCpt curr_nearest;
00235 int curr_on_tri=0;
00236
00237 for (int k = 0; k < nbrs.num(); k++) {
00238 if (nbrs[k] != this) {
00239 curr_nearest = nbrs[k]->nearest_pt_ndc(target, curr_bc, curr_on_tri);
00240 if (curr_nearest.dist_sqrd(target) < dist_sqrd ) {
00241 dist_sqrd = curr_nearest.dist_sqrd(target);
00242 best_bc = curr_bc;
00243 best_on_tri = curr_on_tri;
00244 best_nearest = curr_nearest;
00245 best = nbrs[k];
00246 }
00247 }
00248 }
00249
00250 if (dist_sqrd < y.dist_sqrd(target)) {
00251 return best->ndc_walk(target, best_bc, best_nearest, best_on_tri, true);
00252 }
00253
00254 return 0;
00255 }
00256
00257 Bface*
00258 Bface::plane_walk(Bedge* cur_edge, CWplane& plane, Bedge*& next_edge) const
00259 {
00260 int i;
00261 assert(cur_edge == 0 || cur_edge->which_side(plane) == 0);
00262
00263 for (i=1; i<4; i++)
00264 if (e(i) != cur_edge && e(i)->which_side(plane)==0)
00265 break;
00266
00267 if (i==4)
00268 return 0;
00269
00270 assert(e(i)->which_side(plane)==0);
00271
00272 next_edge = e(i);
00273 return e(i)->other_face(this);
00274 }
00275
00276 bool
00277 Bface::ray_intersect(
00278 CWpt& p,
00279 CWvec& r,
00280 Wpt& hit,
00281 double& depth) const
00282 {
00283
00284 CWpt &a=_v1->loc();
00285 CWpt &b=_v2->loc();
00286 CWpt &c=_v3->loc();
00287
00288
00289
00290 double dot = r * norm();
00291 if(fabs(dot) < 1e-16)
00292 return 0;
00293
00294
00295 double t = ((a - p) * norm()) / dot;
00296
00297
00298 Wpt d = p + (r * t);
00299
00300
00301 Wvec da = d-a;
00302 Wvec ba = b-a;
00303 Wvec db = d-b;
00304 if ((cross(da,ba) * cross(da,c-a) <= 0) &&
00305 (cross(db,ba) * cross(db,c-b) > 0)) {
00306 hit = d;
00307 depth = (hit - p).length();
00308 return 1;
00309 }
00310 return 0;
00311 }
00312
00313 bool
00314 Bface::view_intersect(
00315 CNDCpt& p,
00316 Wpt& nearpt,
00317 double& dist,
00318 double& d2d,
00319 Wvec& n
00320 ) const
00321 {
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 Wpt eye = XYpt(p);
00333
00334
00335 Wline ray = _mesh->inv_xform()*Wline(p);
00336 Wpt hit;
00337
00338
00339 double d;
00340 if (ray_intersect(ray, hit, d)) {
00341
00342 nearpt = _mesh->xform()*hit;
00343 dist = nearpt.dist(eye);
00344 d2d = PIXEL(nearpt).dist(PIXEL(p));
00345 n = (_mesh->inv_xform().transpose()*norm()).normalized();
00346 return true;
00347 }
00348
00349 Wpt hit1, hit2, hit3;
00350 double d1 = DBL_MAX, d2 = DBL_MAX, d3 = DBL_MAX;
00351 Wvec n1, n2, n3;
00352 _e1->view_intersect(p, hit1, d, d1, n1);
00353 _e2->view_intersect(p, hit2, d, d2, n2);
00354 _e3->view_intersect(p, hit3, d, d3, n3);
00355
00356
00357 if (d1 > d2) {
00358 swap(d1, d2);
00359 swap(hit1, hit2);
00360 swap(n1, n2);
00361 }
00362 if (d1 > d3) {
00363 swap(d1, d3);
00364 swap(hit1, hit3);
00365 swap(n1, n3);
00366 }
00367 nearpt = _mesh->xform()*hit1;
00368 dist = nearpt.dist(eye);
00369 d2d = PIXEL(nearpt).dist(PIXEL(p));
00370 n = n1;
00371 return true;
00372 }
00373
00374 inline Wpt
00375 pt_near_seg(CWpt& a, CWpt& b, CWpt& p, double& t)
00376 {
00377
00378 Wvec v = (b - a);
00379 double vv = v*v;
00380 t = (vv < gEpsZeroMath) ? 0 : clamp(((p - a)*v)/vv,0.0,1.0);
00381 return (a + v*t);
00382 }
00383
00384 inline NDCpt
00385 pt_near_seg_ndc(CNDCpt& a, CNDCpt& b, CNDCpt& p, double& t)
00386 {
00387
00388 NDCvec v = (b - a);
00389 double vv = v*v;
00390 t = (vv < gEpsZeroMath) ? 0 : clamp(((p - a)*v)/vv,0.0,1.0);
00391 return (a + v*t);
00392 }
00393
00394 inline void
00395 get_other_face(CBedge* e, CBface* f, Bsimplex_list& ret)
00396 {
00397 assert(e && f && f->contains(e));
00398 if (e->is_weak())
00399 return;
00400 Bface* g = e->other_face(f);
00401 if (!g)
00402 return;
00403 ret += g;
00404 g = g->quad_partner();
00405 if (g)
00406 ret += g;
00407 }
00408
00409 inline Bsimplex_list
00410 bfa_to_bsa(CBface_list& faces)
00411 {
00412 Bsimplex_list ret(faces.num());
00413 for (int i=0; i<faces.num(); i++)
00414 ret += faces[i];
00415 return ret;
00416 }
00417
00418 Bsimplex_list
00419 Bface::neighbors() const
00420 {
00421
00422
00423
00424
00425
00426
00427 return bfa_to_bsa(Bface_list((Bface*)this).one_ring_faces());
00428
00429 Bsimplex_list ret(9);
00430 ret += _v1;
00431 ret += _v2;
00432 ret += _v3;
00433 ret += _e1;
00434 ret += _e2;
00435 ret += _e3;
00436 get_other_face(_e1, this, ret);
00437 get_other_face(_e2, this, ret);
00438 get_other_face(_e3, this, ret);
00439 return ret;
00440 }
00441
00442 Bsimplex*
00443 Bface::bc2sim(CWvec& bc) const
00444 {
00445 return (
00446 (bc[0]==1) ? (Bsimplex*)_v1 :
00447 (bc[1]==1) ? (Bsimplex*)_v2 :
00448 (bc[2]==1) ? (Bsimplex*)_v3 :
00449 (bc[0]==0) ? (Bsimplex*)_e2 :
00450 (bc[1]==0) ? (Bsimplex*)_e3 :
00451 (bc[2]==0) ? (Bsimplex*)_e1 :
00452 (Bsimplex*)this
00453 );
00454 }
00455
00456 bool
00457 Bface::local_search(
00458 Bsimplex *&end,
00459 Wvec &final_bc,
00460 CWpt &target,
00461 Wpt &reached,
00462 Bsimplex *repeater,
00463 int iters)
00464 {
00465
00466
00467
00468
00469 if (iters <= 0)
00470 return 0;
00471
00472 Wvec bc;
00473 bool is_on_tri = 0;
00474 Wpt nearpt = nearest_pt(target, bc, is_on_tri);
00475 Bsimplex* sim = bc2sim(bc);
00476
00477 if (!is_on_tri) {
00478
00479 if (sim == repeater)
00480 return 0;
00481
00482 if (sim != this) {
00483 if (is_edge(sim)) {
00484 Bedge* e = (Bedge*)sim;
00485
00486
00487 if (!e->is_border()) {
00488
00489
00490 int good_path = e->other_face(this)->local_search(
00491 end, final_bc, target, reached, sim, iters-1);
00492 if (good_path == 1)
00493 return 1;
00494 else if (good_path == -1)
00495 return repeater ? true : false;
00496 }
00497
00498 else {
00499 return repeater ? true : false;
00500 }
00501 } else {
00502
00503 Bface_list near_faces(16);
00504 assert(is_vert(sim));
00505 ((Bvert*)sim)->get_faces(near_faces);
00506 for (int k = near_faces.num()-1; k>=0; k--) {
00507 if (near_faces[k] != this) {
00508 int good_path = near_faces[k]->local_search(
00509 end, final_bc, target, reached, sim, iters-1);
00510 if (good_path == 1)
00511 return 1;
00512 else if (good_path==-1)
00513 return repeater ? true : false;
00514 }
00515 }
00516 }
00517 }
00518 }
00519
00520 reached = nearpt;
00521 end = this;
00522 final_bc = bc;
00523
00524 return 1;
00525 }
00526
00527 inline void
00528 snap(Wvec& bc)
00529 {
00530
00531
00532
00533
00534
00535
00536
00537 if (fabs(bc[0]) < gEpsZeroMath) bc[0] = 0;
00538 if (fabs(bc[1]) < gEpsZeroMath) bc[1] = 0;
00539 if (fabs(bc[2]) < gEpsZeroMath) bc[2] = 0;
00540
00541 double sum = bc[0] + bc[1] + bc[2];
00542
00543 bc /= sum;
00544 }
00545
00546 Wpt
00547 Bface::nearest_pt(CWpt& p, Wvec &bc, bool &is_on_tri) const
00548 {
00549
00550
00551
00552
00553 project_barycentric(p, bc);
00554
00555
00556
00557 snap(bc);
00558
00559 Wpt ret;
00560 if (bc[0] < 0 || bc[1] < 0 || bc[2] < 0) {
00561
00562
00563 is_on_tri = 0;
00564 double t1, t2, t3;
00565 CWpt& a = _v1->loc();
00566 CWpt& b = _v2->loc();
00567 CWpt& c = _v3->loc();
00568 Wpt p1 = pt_near_seg(a,b,p,t1);
00569 Wpt p2 = pt_near_seg(b,c,p,t2);
00570 Wpt p3 = pt_near_seg(c,a,p,t3);
00571 double d1 = (p1 - p).length_sqrd();
00572 double d2 = (p2 - p).length_sqrd();
00573 double d3 = (p3 - p).length_sqrd();
00574
00575 if (d1 < d2) {
00576 if (d1 < d3) {
00577 bc.set(1-t1,t1,0);
00578 return p1;
00579 }
00580 bc.set(t3,0,1-t3);
00581 return p3;
00582 }
00583 if (d2 < d3) {
00584 bc.set(0,1-t2,t2);
00585 return p2;
00586 }
00587 bc.set(t3,0,1-t3);
00588 return p3;
00589 }
00590
00591 is_on_tri = 1;
00592 bc2pos(bc, ret);
00593
00594 return ret;
00595 }
00596
00597 inline double
00598 signed_area_ndc(CNDCpt& a, CNDCpt& b, CNDCpt& c)
00599 {
00600 return 0.5 * det(b-a,c-a);
00601 }
00602
00603 NDCpt
00604 Bface::nearest_pt_ndc(CNDCpt& p, Wvec &bc, int &is_on_tri) const
00605 {
00606
00607
00608
00609
00610
00611 NDCpt a = _v1->ndc();
00612 NDCpt b = _v2->ndc();
00613 NDCpt c = _v3->ndc();
00614 double A = signed_area_ndc(a, b, c);
00615 double u = signed_area_ndc(p, b, c) / A;
00616 double v = signed_area_ndc(a, p, c) / A;
00617 bc.set(u, v, 1 - u - v);
00618
00619
00620
00621 snap(bc);
00622
00623 if (bc[0] < 0 || bc[1] < 0 || bc[2] < 0) {
00624
00625
00626 is_on_tri = 0;
00627 double t1, t2, t3;
00628
00629 NDCpt p1 = pt_near_seg_ndc(a,b,p,t1);
00630 NDCpt p2 = pt_near_seg_ndc(b,c,p,t2);
00631 NDCpt p3 = pt_near_seg_ndc(c,a,p,t3);
00632
00633 double d1 = p.dist_sqrd(p1);
00634 double d2 = p.dist_sqrd(p2);
00635 double d3 = p.dist_sqrd(p3);
00636
00637 if (d1 < d2) {
00638 if (d1 < d3) {
00639 bc.set(1-t1,t1,0);
00640 return p1;
00641 }
00642 bc.set(t3,0,1-t3);
00643 return p3;
00644 }
00645 if (d2 < d3) {
00646 bc.set(0,1-t2,t2);
00647 return p2;
00648 }
00649 bc.set(t3,0,1-t3);
00650 return p3;
00651 }
00652
00653 is_on_tri = 1;
00654 return (a*bc[0]) + (b*bc[1]) + (c*bc[2]);
00655 }
00656
00657
00658
00659 Wpt
00660 Bface::near_pt(CNDCpt& ndc, Wvec& hit_bc) const
00661 {
00662
00663 return Bsimplex::nearest_pt(plane_intersect(nearest_pt_ndc(ndc)), hit_bc);
00664 }
00665
00666 int
00667 Bface::detach()
00668 {
00669
00670 int ret = 1;
00671
00672 if (_e1) ret = (*_e1 -= this) && ret;
00673 if (_e2) ret = (*_e2 -= this) && ret;
00674 if (_e3) ret = (*_e3 -= this) && ret;
00675
00676 _e1 = _e2 = _e3 = 0;
00677
00678 return ret;
00679 }
00680
00681 void
00682 Bface::reverse()
00683 {
00684
00685 swap(_v2,_v3);
00686 swap(_e1,_e3);
00687 if (_tc)
00688 swap(tex_coord(2),tex_coord(3));
00689
00690
00691 if (_patch)
00692 _patch->triangulation_changed();
00693 _orient = 0;
00694
00695 geometry_changed();
00696 }
00697
00698 void
00699 Bface::make_primary()
00700 {
00701 clear_bit(SECONDARY_BIT);
00702 geometry_changed();
00703 }
00704
00705 void
00706 Bface::make_secondary()
00707 {
00708 set_bit(SECONDARY_BIT, 1);
00709 geometry_changed();
00710 }
00711
00712 bool
00713 Bface::check() const
00714 {
00715 if (!(_v1 && _v2 && _v3 && _e1 && _e2 && _e3))
00716 return false;
00717
00718 return ((_v1->lookup_edge(_v2) ==_e1) &&
00719 (_v2->lookup_edge(_v3) ==_e2) &&
00720 (_v3->lookup_edge(_v1) ==_e3));
00721 }
00722
00723 bool
00724 Bface::redef2(Bedge *a, Bedge *b)
00725 {
00726 static bool debug = Config::get_var_bool("DEBUG_MESH_OPS",false);
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736 if (!contains(a)) {
00737 err_adv(debug, "Bface::redef2: error: face doesn't contain a");
00738 return false;
00739 }
00740 if (contains(b)) {
00741 err_adv(debug, "Bface::redef2: error: face already contains b");
00742 return false;
00743 }
00744
00745 *a -= this;
00746
00747 if (a == _e1) _e1 = b;
00748 else if (a == _e2) _e2 = b;
00749 else if (a == _e3) _e3 = b;
00750 else assert(0);
00751
00752 *b += this;
00753
00754 geometry_changed();
00755
00756 return true;
00757 }
00758
00759 bool
00760 Bface::redef2(Bvert *a, Bvert *b)
00761 {
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773 static bool debug = Config::get_var_bool("DEBUG_MESH_OPS",false);
00774 if (!contains(a)) {
00775 err_adv(debug, "Bface::redef2: error: vert to be replaced not found");
00776 return false;
00777 }
00778 if (contains(b)) {
00779 err_adv(debug, "Bface::redef2: error: new vert already in face");
00780 return false;
00781 }
00782
00783 if (_v1 == a) _v1 = b;
00784 else if (_v2 == a) _v2 = b;
00785 else if (_v3 == a) _v3 = b;
00786 else assert(0);
00787
00788
00789 if (_patch)
00790 _patch->triangulation_changed();
00791 _orient = 0;
00792
00793
00794
00795 geometry_changed();
00796
00797 return true;
00798 }
00799
00800 int
00801 Bface::redefine(Bvert *v, Bvert *u)
00802 {
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812 static bool debug = Config::get_var_bool("DEBUG_MESH_OPS",false);
00813
00814 if (!contains(v)) {
00815 err_adv(debug, "Bface::redefine: error: old vert not found");
00816 return 0;
00817 }
00818
00819 if (contains(u)) {
00820 err_adv(debug, "Bface::redefine: error: new vert already in face");
00821 return 0;
00822 }
00823
00824 if (_v1 == v) _v1 = u;
00825 else if (_v2 == v) _v2 = u;
00826 else if (_v3 == v) _v3 = u;
00827 else assert(0);
00828
00829 assert(!lookup_face(_v1, _v2, _v3));
00830
00831 Bedge* e1 = _v1->lookup_edge(_v2);
00832 Bedge* e2 = _v2->lookup_edge(_v3);
00833 Bedge* e3 = _v3->lookup_edge(_v1);
00834
00835 if (!(e1 && e2 && e3)) {
00836 err_adv(debug, "Bface::redefine: error: 1 or more edges not defined");
00837 return 0;
00838 }
00839
00840
00841 _e1 = e1;
00842 _e2 = e2;
00843 _e3 = e3;
00844
00845 *_e1 += this;
00846 *_e2 += this;
00847 *_e3 += this;
00848
00849
00850 if (_patch)
00851 _patch->triangulation_changed();
00852 _orient = 0;
00853
00854
00855
00856 geometry_changed();
00857
00858 return 1;
00859 }
00860
00861 int
00862 Bface::redefine(
00863 Bvert *u, Bvert *nu,
00864 Bvert *v, Bvert *nv)
00865 {
00866
00867
00868
00869
00870
00871
00872
00873
00874 if (!contains(u) || !contains(v))
00875 return 0;
00876
00877 if (u == _v1) _v1 = nu;
00878 else if (u == _v2) _v2 = nu;
00879 else if (u == _v3) _v3 = nu;
00880 else return 0;
00881
00882 if (v == _v1) _v1 = nv;
00883 else if (v == _v2) _v2 = nv;
00884 else if (v == _v3) _v3 = nv;
00885 else return 0;
00886
00887 Bedge* e1 = _v1->lookup_edge(_v2);
00888 Bedge* e2 = _v2->lookup_edge(_v3);
00889 Bedge* e3 = _v3->lookup_edge(_v1);
00890
00891 if (!e1 || !e2 || !e3 ||
00892 lookup_face(_v1, _v2, _v3)) {
00893 return 0;
00894 }
00895
00896
00897 _e1 = e1;
00898 _e2 = e2;
00899 _e3 = e3;
00900
00901 *_e1 += this;
00902 *_e2 += this;
00903 *_e3 += this;
00904
00905
00906 if (_patch)
00907 _patch->triangulation_changed();
00908 _orient = 0;
00909
00910
00911
00912 geometry_changed();
00913
00914 return 1;
00915 }
00916
00917 CWvec&
00918 Bface::vert_normal(CBvert* v, Wvec& n) const
00919 {
00920
00921
00922
00923 assert(this->contains(v));
00924
00925 if(!v->is_crease()) {
00926 n = v->norm();
00927 return n;
00928 }
00929
00930
00931
00932
00933
00934 n = weighted_vnorm(this, v);
00935 int count = 1;
00936
00937
00938
00939 CBface* f = this;
00940 Bedge* e = edge_from_vert(v);
00941 for (; e&&!e->is_crease() && (f=e->other_face(f)); e=f->edge_from_vert(v)) {
00942 n += weighted_vnorm(f, v);
00943 if (++count > v->degree()) {
00944
00945
00946
00947 break;
00948 }
00949 }
00950
00951
00952
00953 f = this;
00954 e = edge_before_vert(v);
00955 for(; e&&!e->is_crease()&&(f=e->other_face(f)); e=f->edge_before_vert(v)) {
00956 n += weighted_vnorm(f, v);
00957 if(++count > v->degree())
00958 break;
00959 }
00960
00961 n = n.normalized();
00962 return n;
00963 }
00964
00965 bool
00966 Bface::get_quad_verts(Bvert*& a, Bvert*& b, Bvert*& c, Bvert*& d) const
00967 {
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981 if (!is_quad())
00982 return 0;
00983
00984 Bedge* w = weak_edge();
00985 Bface* f = w->ccw_face(w->v2());
00986 a = w->v1();
00987 b = f->next_vert_ccw(a);
00988 c = w->v2();
00989 d = f->quad_vert();
00990
00991 return true;
00992 }
00993
00994
00995
00996 bool
00997 Bface::get_quad_verts(Bvert_list& verts) const
00998 {
00999 verts.clear();
01000 Bvert *v1=0, *v2=0, *v3=0, *v4=0;
01001 if (!get_quad_verts(v1,v2,v3,v4))
01002 return 0;
01003 verts += v1;
01004 verts += v2;
01005 verts += v3;
01006 verts += v4;
01007 return 1;
01008
01009 }
01010 bool
01011 Bface::get_quad_pts(Wpt& a, Wpt& b, Wpt& c, Wpt& d) const
01012 {
01013 Bvert *v1=0, *v2=0, *v3=0, *v4=0;
01014 if (!get_quad_verts(v1,v2,v3,v4))
01015 return 0;
01016 a = v1->loc();
01017 b = v2->loc();
01018 c = v3->loc();
01019 d = v4->loc();
01020 return 1;
01021 }
01022
01023 bool
01024 Bface::get_quad_edges(Bedge*& a, Bedge*& b, Bedge*& c, Bedge*& d) const
01025 {
01026 Bvert *v1=0, *v2=0, *v3=0, *v4=0;
01027 if (!get_quad_verts(v1,v2,v3,v4))
01028 return 0;
01029
01030 assert(v1&&v2&&v3&&v4);
01031
01032 a=v1->lookup_edge(v2);
01033 b=v2->lookup_edge(v3);
01034 c=v3->lookup_edge(v4);
01035 d=v4->lookup_edge(v1);
01036
01037 assert(a&&b&&c&&d);
01038 return 1;
01039
01040 }
01041 bool
01042 Bface::get_quad_edges(Bedge_list& edges) const
01043 {
01044 edges.clear();
01045 Bedge *e1=0, *e2=0, *e3=0, *e4=0;
01046 if (!get_quad_edges(e1,e2,e3,e4))
01047 return 0;
01048 edges += e1;
01049 edges += e2;
01050 edges += e3;
01051 edges += e4;
01052 return 1;
01053 }
01054
01055
01056
01057
01058 Wvec
01059 Bface::quad_tan1() const
01060 {
01061
01062
01063 Wpt a, b, c, d;
01064 get_quad_pts(a,b,c,d);
01065
01066 Wvec t = ((b - a) + (c - d))*0.5;
01067 return t.orthogonalized(quad_norm()).normalized();
01068 }
01069
01070 Wvec
01071 Bface::quad_tan2() const
01072 {
01073
01074
01075 Wpt a, b, c, d;
01076 get_quad_pts(a,b,c,d);
01077
01078 Wvec t = ((d - a) + (c - b))*0.5;
01079 return t.orthogonalized(quad_norm()).normalized();
01080 }
01081
01082 double
01083 Bface::quad_dim1() const
01084 {
01085
01086
01087 Wpt a, b, c, d;
01088 get_quad_pts(a,b,c,d);
01089
01090 return (b.dist(a) + c.dist(d))/2;
01091 }
01092
01093 double
01094 Bface::quad_dim2() const
01095 {
01096
01097
01098 Wpt a, b, c, d;
01099 get_quad_pts(a,b,c,d);
01100
01101 return (b.dist(c) + a.dist(d))*0.5;
01102 }
01103
01104 UVpt
01105 Bface::quad_bc_to_uv(CWvec& bc) const
01106 {
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123 Bvert *a=0, *b=0, *c=0, *d=0;
01124 if (!get_quad_verts(a, b, c, d)) {
01125 err_msg("Bface::quad_bc_to_uv: Error: can't get quad verts");
01126 return UVpt();
01127 }
01128
01129
01130
01131
01132
01133
01134
01135 int k = vindex(a) - 1;
01136 if (k < 0 || k > 2) {
01137 err_msg("Bface::quad_bc_to_uv: Error: can't get oriented");
01138 return UVpt();
01139 }
01140 if (contains(b)) {
01141
01142 return UVpt(1 - bc[k], bc[(k + 2)%3]);
01143 } else if (contains(d)) {
01144
01145 return UVpt(bc[(k + 1)%3], 1 - bc[k]);
01146 } else {
01147
01148 err_msg("Bface::quad_bc_to_uv: Error: can't get oriented");
01149 return UVpt();
01150 }
01151 }
01152
01153 Wpt
01154 Bface::quad_uv2loc(CUVpt& uv) const
01155 {
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170 Bvert *a=0, *b=0, *c=0, *d=0;
01171 if (!get_quad_verts(a, b, c, d)) {
01172 err_msg("Bface::quad_uv2loc: Error: can't get quad verts");
01173 return Wpt();
01174 }
01175
01176
01177 double u = clamp(uv[0], 0.0, 1.0);
01178 double v = clamp(uv[1], 0.0, 1.0);
01179
01180
01181 if (v <= u) {
01182 double w = ((u == 0) ? 0.0 : (v/u));
01183 return interp(interp(a->loc(), b->loc(), u),
01184 interp(a->loc(), c->loc(), u), w);
01185 } else {
01186 double w = ((u == 1) ? 1.0 : ((v - u)/(1 - u)));
01187 return interp(interp(a->loc(), c->loc(), u),
01188 interp(d->loc(), c->loc(), u), w);
01189 }
01190 }
01191
01192
01193
01194
01195
01196 void
01197 Bface_list::clear_vert_flags() const
01198 {
01199
01200
01201 for (int i=0; i<_num; i++)
01202 for (int j=1; j<4; j++)
01203 _array[i]->v(j)->clear_flag();
01204 }
01205
01206 void
01207 Bface_list::clear_edge_flags() const
01208 {
01209
01210 for (int i=0; i<_num; i++)
01211 for (int j=1; j<4; j++)
01212 _array[i]->e(j)->clear_flag();
01213 }
01214
01215 Bvert_list
01216 Bface_list::get_verts() const
01217 {
01218
01219
01220
01221 clear_vert_flags();
01222
01223
01224 Bvert_list ret(_num);
01225 for (int i=0; i<_num; i++) {
01226 for (int j=1; j<4; j++) {
01227 Bvert* v = _array[i]->v(j);
01228 if (!v) {
01229 err_msg("Bface_list::get_verts: null vert");
01230 } else if (v->flag() == 0) {
01231 v->set_flag(1);
01232 ret += v;
01233 }
01234 }
01235 }
01236 return ret;
01237 }
01238
01239 Bedge_list
01240 Bface_list::get_edges() const
01241 {
01242
01243
01244
01245 clear_edge_flags();
01246
01247
01248 Bedge_list ret(_num*2);
01249 for (int i=0; i<_num; i++) {
01250 for (int j=1; j<4; j++) {
01251 Bedge* e = _array[i]->e(j);
01252 if (e->flag() == 0) {
01253 e->set_flag(1);
01254 ret += e;
01255 }
01256 }
01257 }
01258 return ret;
01259 }
01260
01261 Wvec
01262 Bface_list::avg_normal() const
01263 {
01264
01265 Wvec ret;
01266 for (int i=0; i<_num; i++)
01267 ret += _array[i]->norm();
01268 return ret.normalized();
01269 }
01270
01271 double
01272 Bface_list::max_norm_deviation(CWvec& n) const
01273 {
01274
01275
01276
01277 double ret = 0;
01278 for (int i=0; i<_num; i++)
01279 ret = max(ret, n.angle(_array[i]->norm()));
01280 return ret;
01281 }
01282
01283 double
01284 Bface_list::volume() const
01285 {
01286
01287
01288
01289
01290
01291
01292
01293 double ret = 0;
01294 for (int k=0; k<_num; k++)
01295 ret += _array[k]->volume_el();
01296 return ret;
01297 }
01298
01299 void
01300 Bface_list::mark_faces() const
01301 {
01302
01303
01304
01305
01306
01307 get_verts().clear_flag02();
01308
01309
01310 set_flags(1);
01311 }
01312
01313 Bface_list
01314 Bface_list::exterior_faces() const
01315 {
01316
01317
01318 Bface_list ret = one_ring_faces();
01319 mark_faces();
01320 return ret.filter(SimplexFlagFilter(0));
01321 }
01322
01323 inline Bface*
01324 check_partner(Bface* f)
01325 {
01326
01327
01328 if (!(f && f->is_quad()))
01329 return 0;
01330 Bface* p = f->quad_partner();
01331 return p->flag() ? 0 : p;
01332 }
01333
01334 Bface_list
01335 Bface_list::quad_complete_faces() const
01336 {
01337
01338
01339
01340 mark_faces();
01341 Bface* p=0;
01342 Bface_list ret = *this;
01343 for (int i=0; i<_num; i++)
01344 if ((p = check_partner(_array[i])))
01345 ret.add(p);
01346 return ret;
01347 }
01348
01349 Bface_list
01350 Bface_list::reachable_faces(Bface* f, CSimplexFilter& pass)
01351 {
01352
01353
01354
01355
01356 Bface_list ret;
01357
01358 if (!(f && f->mesh()))
01359 return ret;
01360
01361
01362
01363
01364
01365
01366
01367 f->mesh()->faces().set_flags(1);
01368
01369 ret.grow_connected(f, pass);
01370 return ret;
01371 }
01372
01373 bool
01374 Bface_list::grow_connected(Bface* f, CSimplexFilter& pass)
01375 {
01376
01377
01378
01379 if (!(f && f->flag() == 1))
01380 return false;
01381
01382 f->set_flag(2);
01383 add(f);
01384
01385
01386 for (int i=1; i<4; i++) {
01387 Bedge* e = f->e(i);
01388 if (pass.accept(e)) {
01389
01390
01391 for (int j=1; j<=e->num_all_faces(); j++)
01392 grow_connected(e->f(j), pass);
01393 }
01394 }
01395
01396 return true;
01397 }
01398
01399 bool
01400 Bface_list::is_connected() const
01401 {
01402
01403
01404
01405
01406
01407 if (mesh() == NULL)
01408 return false;
01409
01410
01411
01412
01413
01414
01415
01416 mark_faces();
01417
01418
01419
01420
01421
01422 Bface_list comp1(_num);
01423 comp1.grow_connected(first());
01424
01425 bool debug = Config::get_var_bool("DEBUG_BFACE_LIST_IS_CONNECTED", false);
01426
01427 err_adv(debug, "Bface_list::is_connected:");
01428 err_adv(debug, " nfaces: %d, comp 1: %d, connected: %s",
01429 _num, comp1.num(), ((comp1.num() == _num) ? "yes" : "no"));
01430
01431
01432 return comp1.num() == _num;
01433 }
01434
01435 bool
01436 Bface_list::is_disk() const
01437 {
01438
01439
01440
01441 return (is_connected() &&
01442 get_boundary().num_line_strips() == 1 &&
01443 is_2_manifold());
01444 }
01445
01446 EdgeStrip
01447 Bface_list::get_boundary() const
01448 {
01449
01450
01451
01452
01453
01454
01455 mark_faces();
01456
01457 EdgeStrip ret;
01458 ret.build_ccw_boundaries(get_edges(), SimplexFlagFilter(1));
01459 return ret;
01460 }
01461
01462 Bedge_list
01463 Bface_list::boundary_edges() const
01464 {
01465 return get_boundary().edges();
01466 }
01467
01468 Bedge_list
01469 Bface_list::interior_edges() const
01470 {
01471
01472
01473
01474 mark_faces();
01475 return get_edges().filter(!BoundaryEdgeFilter(SimplexFlagFilter(1)));
01476 }
01477
01478 Bvert_list
01479 Bface_list::interior_verts() const
01480 {
01481
01482
01483
01484 mark_faces();
01485 return get_verts().filter(VertFaceDegreeFilter(0, SimplexFlagFilter(0)));
01486 }
01487
01488 bool
01489 Bface_list::is_consistently_oriented() const
01490 {
01491
01492
01493
01494 SimplexFlagFilter me(1);
01495 BoundaryEdgeFilter boundary(me);
01496 NotFilter interior(boundary);
01497 ConsistentEdgeFilter consistent;
01498 NotFilter inconsistent(consistent);
01499
01500
01501
01502 mark_faces();
01503
01504 if (Config::get_var_bool("DEBUG_INFLATE_ALL",false)) {
01505 err_msg("Total faces: %d", _num);
01506 err_msg("Total edges: %d", get_edges().num());
01507 err_msg("Boundary edges: %d", get_edges().filter(boundary).num());
01508 err_msg("Interior edges: %d", get_edges().filter(!boundary).num());
01509 err_msg("Inconsistent edges: %d", get_edges().filter(inconsistent).num());
01510 }
01511
01512 return get_edges().filter(interior + inconsistent).empty();
01513 }
01514
01515
01516 bool
01517 Bface_list::is_2_manifold() const
01518 {
01519
01520
01521
01522
01523 mark_faces();
01524
01525
01526 return get_edges().all_satisfy(ManifoldEdgeFilter(SimplexFlagFilter(1)));
01527 }
01528
01529 bool
01530 Bface_list::can_push_layer() const
01531 {
01532
01533
01534
01535
01536
01537
01538 if (is_all_secondary())
01539 return true;
01540
01541 return (!empty() && same_mesh());
01542 }
01543
01544 inline void
01545 demote(Bface* f)
01546 {
01547
01548
01549
01550
01551 if (!f) return;
01552 if (f->e1()->flag()) f->e1()->demote(f);
01553 if (f->e2()->flag()) f->e2()->demote(f);
01554 if (f->e3()->flag()) f->e3()->demote(f);
01555 }
01556
01557 bool
01558 Bface_list::push_layer(bool push_boundary) const
01559 {
01560
01561
01562
01563
01564 if (!can_push_layer()) {
01565 err_msg("Bface_list::push_layer: invalid operation");
01566 return false;
01567 }
01568
01569
01570
01571 if (is_all_secondary())
01572 return true;
01573
01574
01575
01576
01577 make_secondary();
01578
01579
01580 if (push_boundary) {
01581
01582
01583
01584 EdgeStrip bdry = get_boundary();
01585
01586
01587
01588 UVdata::split(bdry);
01589
01590
01591
01592
01593 get_edges().clear_flags();
01594
01595 bdry.edges().set_flags();
01596
01597
01598 for (int i=0; i<num(); i++)
01599 demote(_array[i]);
01600
01601 }
01602
01603
01604 assert(mesh());
01605 mesh()->changed();
01606
01607 return true;
01608 }
01609
01610 bool
01611 Bface_list::can_unpush_layer() const
01612 {
01613
01614
01615
01616
01617
01618 if (is_all_primary())
01619 return true;
01620
01621 static bool debug = Config::get_var_bool("DEBUG_PUSH_FACES",false);
01622 if (debug) {
01623 bool b = boundary_edges().all_satisfy(CanPromoteEdgeFilter());
01624 cerr << "Bface_list::can_unpush_layer: " << endl
01625 << " " << num() << " faces, "
01626 << (same_mesh() ? "same mesh" : "different meshes") << ", "
01627 << (is_2_manifold() ? "" : "non-") << "manifold, "
01628 << "boundary: " << (b ? "good" : "bad")
01629 << " (" << boundary_edges().num() << " edges)"
01630 << endl;
01631 Bedge_list bad_edges = boundary_edges().filter(!CanPromoteEdgeFilter());
01632 cerr << bad_edges.num() << " bad edges" << endl;
01633 if (!b) {
01634 MeshGlobal::select(bad_edges);
01635 }
01636 }
01637 return (!empty() && same_mesh() &&
01638 is_2_manifold() &&
01639 boundary_edges().all_satisfy(CanPromoteEdgeFilter()));
01640 }
01641
01642 inline void
01643 promote(Bface* f)
01644 {
01645
01646
01647
01648
01649 if (!f) return;
01650 if (f->e1()->flag()) f->e1()->promote(f);
01651 if (f->e2()->flag()) f->e2()->promote(f);
01652 if (f->e3()->flag()) f->e3()->promote(f);
01653 }
01654
01655 bool
01656 Bface_list::unpush_layer(bool unpush_boundary) const
01657 {
01658
01659
01660
01661 if (!can_unpush_layer()) {
01662 err_msg("Bface_list::unpush_layer: invalid operation");
01663 return false;
01664 }
01665
01666
01667
01668 if (is_all_primary())
01669 return true;
01670
01671
01672
01673 make_primary();
01674
01675 if (unpush_boundary) {
01676
01677 EdgeStrip bdry = get_boundary();
01678 get_edges().clear_flags();
01679 bdry.edges().set_flags();
01680
01681
01682 for (int i=0; i<num(); i++)
01683 promote(_array[i]);
01684 }
01685
01686
01687 assert(mesh());
01688 mesh()->changed();
01689
01690 return true;
01691 }
01692
01693