00001
00002
00003
00004 #include "disp/ray.H"
00005 #include "mi.H"
00006
00007 using namespace mlib;
00008
00009 Bvert::~Bvert()
00010 {
00011
00012 if (is_selected()) {
00013 MeshGlobal::deselect(this);
00014 }
00015
00016
00017
00018 if (_mesh) {
00019 while (degree() > 0)
00020 _mesh->remove_edge(_adj.last());
00021 }
00022 }
00023
00024 int
00025 Bvert::index() const
00026 {
00027
00028
00029 if (!_mesh) return -1;
00030 return _mesh->verts().get_index((Bvert*)this);
00031 }
00032
00033 void
00034 Bvert::operator +=(Bedge* e)
00035 {
00036 _adj += e;
00037 degree_changed();
00038 if (e->is_crease())
00039 crease_changed();
00040 }
00041
00042 int
00043 Bvert::operator -=(Bedge* e)
00044 {
00045
00046
00047 int ret = (_adj -= e);
00048 if (!ret)
00049 err_msg("Bvert::operator -=(Bedge* e): can't remove e: not in list");
00050 if (e->is_crease())
00051 crease_changed();
00052 degree_changed();
00053 return ret;
00054 }
00055
00056
00057 NDCZpt
00058 Bvert::ndc() const
00059 {
00060 return NDCZpt(_loc,_mesh->obj_to_ndc());
00061 }
00062
00063 Wpt
00064 Bvert::wloc() const
00065 {
00066 return _mesh->xform()*_loc;
00067 }
00068
00069 void
00070 Bvert::get_q_nbrs(ARRAY<Bvert*>& q) const
00071 {
00072
00073
00074
00075
00076 q.clear();
00077
00078 Bface* f;
00079 Bedge_list a = get_manifold_edges();
00080 for (int i=0; i<a.num(); i++)
00081 if (a[i]->is_strong() && (f = ccw_face(a[i], this)) && f->is_quad())
00082 q += f->quad_opposite_vert(this);
00083 }
00084
00085 Bsimplex_list
00086 Bvert::neighbors() const
00087 {
00088 Bface_list faces = get_all_faces();
00089 Bsimplex_list ret(faces.num() + _adj.num());
00090 for (int i=0; i<faces.num(); i++)
00091 ret += faces[i];
00092 for (int j=0; j<_adj.num(); j++)
00093 ret += _adj[j];
00094 return ret;
00095 }
00096
00097 inline void
00098 get_nbrs(CBvert* v, CBedge_list& edges, ARRAY<Bvert*>& nbrs)
00099 {
00100 nbrs.clear();
00101 if (!v)
00102 return;
00103 for (int i=0; i<edges.num(); i++) {
00104 Bvert* nbr = edges[i]->other_vertex(v);
00105 assert(nbr);
00106 nbrs += nbr;
00107 }
00108 }
00109
00110 Bvert_list
00111 Bvert::get_nbrs(CBedge_list& edges) const
00112 {
00113
00114
00115
00116 Bvert_list ret(edges.num());
00117 for (int i=0; i<edges.num(); i++) {
00118 Bvert* v = nbr(edges[i]);
00119 assert(v);
00120 ret += v;
00121 }
00122 return ret;
00123 }
00124
00125 inline Bedge*
00126 leading_ccw_edge(CBvert* v)
00127 {
00128
00129
00130
00131
00132 Bedge* e = 0;
00133 for (int i=0; i<v->degree(); i++)
00134 if ((e = v->e(i))->is_border() && ccw_face(e, v))
00135 return e;
00136
00137 return 0;
00138 }
00139
00140 Bedge_list
00141 Bvert::get_ccw_edges() const
00142 {
00143
00144
00145
00146
00147
00148
00149 if (degree() < 1)
00150 return Bedge_list();
00151
00152
00153 int border_degree = degree(BorderEdgeFilter());
00154 if (border_degree > 0 && border_degree != 2) {
00155 err_msg("Bvert::ccw_edges: error: too many border edges, %d.",
00156 border_degree);
00157 return Bedge_list();
00158 }
00159
00160
00161 Bedge* start = (border_degree == 2) ? leading_ccw_edge(this) : e(0);
00162
00163 if (!start) {
00164 cerr << "Bvert::ccw_edges: error: can't find starting edge." << endl;
00165 return Bedge_list();
00166 }
00167
00168
00169 Bedge_list ret(degree());
00170 ret += start;
00171
00172
00173
00174 Bedge* e = start;
00175 Bface* f = 0;
00176 while ((f = ccw_face(e, this)) &&
00177 (e = f->opposite_edge(e->other_vertex(this))) &&
00178 (e != start))
00179 ret += e;
00180
00181 assert(ret.num() == _adj.num());
00182
00183 return ret;
00184 }
00185
00186 Bvert_list
00187 Bvert::get_ccw_nbrs() const
00188 {
00189 return get_nbrs(get_ccw_edges());
00190 }
00191
00192 bool
00193 Bvert::order_edges_ccw()
00194 {
00195
00196
00197
00198
00199 if (is_set(VALID_CCW_BIT))
00200 return true;
00201
00202 Bedge_list ordered = get_ccw_edges();
00203 if (ordered.num() == degree()) {
00204 _adj = ordered;
00205 set_bit(VALID_CCW_BIT);
00206 return true;
00207 }
00208 return false;
00209 }
00210
00211 void
00212 Bvert::get_nbrs(ARRAY<Bvert*>& nbrs) const
00213 {
00214
00215
00216 ::get_nbrs(this, _adj, nbrs);
00217 }
00218
00219 void
00220 Bvert::get_primary_nbrs(ARRAY<Bvert*>& nbrs) const
00221 {
00222 ::get_nbrs(this, get_manifold_edges(), nbrs);
00223 }
00224
00225 void
00226 Bvert::get_p_nbrs(ARRAY<Bvert*>& nbrs) const
00227 {
00228 ::get_nbrs(this, get_manifold_edges(), nbrs);
00229 }
00230
00231 inline void
00232 mark_pushed_faces(CBvert* v, Bedge* e, Bface* f)
00233 {
00234
00235
00236 assert(v && e && f && e->contains(v) && f->contains(e));
00237 if (f->flag())
00238 return;
00239 do {
00240 f->set_flag();
00241 } while ((e = f->opposite_edge(e->other_vertex(v))) &&
00242 (f = e->other_face(f)) &&
00243 !f->flag());
00244 }
00245
00246 inline void
00247 mark_pushed_faces(CBvert* v, Bedge* e)
00248 {
00249
00250
00251 assert(v && e && e->contains(v));
00252 if (!e->adj()) return;
00253 CBface_list& adj = *e->adj();
00254 for (int i=0; i<adj.num();i++)
00255 mark_pushed_faces(v, e, adj[i]);
00256 }
00257
00258 inline void
00259 mark_pushed_faces(CBvert* v, CBedge_list& edges)
00260 {
00261
00262 assert(v);
00263 for (int i=0; i<edges.num(); i++)
00264 mark_pushed_faces(v, edges[i]);
00265 }
00266
00267 inline bool
00268 has_unmarked_face(Bedge* e)
00269 {
00270 assert(e);
00271 return ((e->f1() && e->f1()->flag() == 0) ||
00272 (e->f2() && e->f2()->flag() == 0));
00273 }
00274
00275 inline void
00276 try_get_nm_edge(Bedge* e, ARRAY<Bedge*>& ret)
00277 {
00278 if (e && e->flag() == 0 && has_unmarked_face(e)) {
00279 e->set_flag();
00280 ret += e;
00281 }
00282 }
00283
00284 void
00285 Bvert::get_manifold_edges(ARRAY<Bedge*>& ret) const
00286 {
00287
00288
00289
00290 if (is_manifold()) {
00291 ret = _adj;
00292 return;
00293 }
00294
00295 _adj.clear_flag02();
00296
00297
00298 mark_pushed_faces(this, _adj.filter(MultiEdgeFilter()));
00299
00300
00301 ret.clear();
00302 for (int i=0; i<_adj.num(); i++) {
00303 try_get_nm_edge(_adj[i], ret);
00304 }
00305 }
00306
00307 inline void
00308 get_faces(CBedge_list& e, ARRAY<Bface*>& ret)
00309 {
00310
00311
00312 ret.clear();
00313
00314 Bface* f;
00315 for (int k=0; k<e.num(); k++) {
00316 if ((f = e[k]->f1()))
00317 ret.add_uniquely(f);
00318 if ((f = e[k]->f2()))
00319 ret.add_uniquely(f);
00320 }
00321 }
00322
00323 void
00324 Bvert::get_faces(ARRAY<Bface*>& ret) const
00325 {
00326
00327
00328
00329
00330
00331 if (is_manifold()) {
00332 ::get_faces(_adj, ret);
00333 } else {
00334 ::get_faces(get_manifold_edges(), ret);
00335 }
00336 }
00337
00338 inline void
00339 add_face(ARRAY<Bface*>& faces, Bface* f)
00340 {
00341
00342
00343
00344 if (f)
00345 faces.add_uniquely(f);
00346 }
00347
00348 inline void
00349 add_quad_partners(ARRAY<Bface*>& faces)
00350 {
00351
00352
00353
00354
00355 for (int k=faces.num()-1; k>=0; k--)
00356 add_face(faces, faces[k]->quad_partner());
00357 }
00358
00359 void
00360 Bvert::get_q_faces(ARRAY<Bface*>& ret) const
00361 {
00362
00363
00364
00365 get_faces(ret);
00366 add_quad_partners(ret);
00367 }
00368
00369 inline Bedge*
00370 next_border_edge_cw(CBvert* v, CBedge_list& edges)
00371 {
00372 assert(v);
00373 for (int i=0; i<edges.num(); i++) {
00374 Bedge* e = edges[i];
00375 if (e->is_border() && e->cw_face(v))
00376 return e;
00377 }
00378 return 0;
00379 }
00380
00381 Bedge*
00382 Bvert::next_border_edge_cw()
00383 {
00384 return ::next_border_edge_cw(
00385 this, is_non_manifold() ? get_manifold_edges() : _adj
00386 );
00387 }
00388
00389 inline void
00390 add_uniquely(ARRAY<Bface*>& a, CBface_list& b)
00391 {
00392 for (int i=0; i<b.num(); i++)
00393 a.add_uniquely(b[i]);
00394 }
00395
00396 void
00397 Bvert::get_all_faces(ARRAY<Bface*>& ret) const
00398 {
00399
00400
00401
00402
00403 get_faces(ret);
00404
00405
00406 if (is_manifold())
00407 return;
00408
00409
00410 for (int i=0; i<degree(); i++) {
00411 if (e(i)->adj() != NULL) {
00412 add_uniquely(ret, e(i)->get_all_faces());
00413 }
00414 }
00415 }
00416
00417 inline void
00418 get_quad_faces(CBedge_list& e, ARRAY<Bface*>& ret)
00419 {
00420
00421
00422 ret.clear();
00423
00424 Bface* f;
00425 for (int k=0; k<e.num(); k++) {
00426 if (!e[k]->is_weak()) {
00427 if ((f = e[k]->f1()) && f->is_quad())
00428 ret.add_uniquely(f->quad_rep());
00429 if ((f = e[k]->f2()) && f->is_quad())
00430 ret.add_uniquely(f->quad_rep());
00431 }
00432 }
00433 }
00434
00435 void
00436 Bvert::get_quad_faces(ARRAY<Bface*>& ret) const
00437 {
00438
00439
00440
00441
00442 if (is_manifold())
00443 ::get_quad_faces(_adj, ret);
00444 else {
00445 ::get_quad_faces(get_manifold_edges(), ret);
00446 }
00447 }
00448
00449 int
00450 Bvert::num_quads() const
00451 {
00452 static Bface_list faces;
00453
00454 get_quad_faces(faces);
00455 return faces.num();
00456 }
00457
00458 int
00459 Bvert::num_tris() const
00460 {
00461 static Bface_list faces;
00462 get_faces(faces);
00463 int ret=0;
00464 for (int i=0; i<faces.num(); i++)
00465 if (!faces[i]->is_quad())
00466 ret++;
00467 return ret;
00468 }
00469
00470 int
00471 Bvert::face_degree(CSimplexFilter& f) const
00472 {
00473
00474
00475
00476 static Bface_list faces;
00477 get_faces(faces);
00478 return faces.num_satisfy(f);
00479 }
00480
00481 Bface*
00482 Bvert::get_face() const
00483 {
00484 Bface* ret = 0;
00485 for (int k=0; k<_adj.num(); k++)
00486 if ((ret = e(k)->get_face()))
00487 return ret;
00488 return 0;
00489 }
00490
00491 bool
00492 Bvert::on_face(CBface* f) const
00493 {
00494 return f->contains(this);
00495 }
00496
00497 Wvec
00498 Bvert::compute_normal(CARRAY<Bface*>& faces) const
00499 {
00500
00501
00502 Wvec ret;
00503 for (int k=0; k<faces.num(); k++)
00504 ret += weighted_vnorm(faces[k], this);
00505 return ret.normalized();
00506 }
00507
00508 void
00509 Bvert::set_normal()
00510 {
00511 set_bit(VALID_NORMAL_BIT,1);
00512
00513
00514 if (_adj.all_satisfy(PolylineEdgeFilter()))
00515 return;
00516
00517
00518 static Bface_list star(32);
00519 get_faces(star);
00520 _norm = compute_normal(star);
00521 }
00522
00523 Wvec
00524 Bvert::norm(CSimplexFilter& f) const
00525 {
00526
00527 Bface_list faces;
00528 get_all_faces(faces);
00529 return compute_normal(faces.filter(f));
00530 }
00531
00532 Wvec
00533 Bvert::wnorm() const
00534 {
00535
00536
00537
00538 if (!_mesh)
00539 return norm();
00540
00541 return (_mesh->inv_xform().transpose() * norm()).normalized();
00542 }
00543
00544 void
00545 Bvert::get_normals(ARRAY<Wvec>& norms) const
00546 {
00547
00548
00549
00550
00551
00552
00553
00554 norms.clear();
00555 if (is_crease()) {
00556 Bface_list faces;
00557 get_faces(faces);
00558 for (int i=0; i<faces.num(); i++) {
00559 Wvec n;
00560 faces[i]->vert_normal(this, n);
00561 norms.add_uniquely(n);
00562 }
00563 } else {
00564 norms += norm();
00565 }
00566 }
00567
00568 void
00569 Bvert::geometry_changed()
00570 {
00571
00572
00573
00574 Bsimplex::geometry_changed();
00575
00576 int i;
00577
00578
00579 for (i=0; i<_adj.num(); i++)
00580 _adj[i]->geometry_changed();
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590 static Bface_list star(32);
00591 get_all_faces(star);
00592 for (i=0; i<star.num(); i++) {
00593 star[i]->geometry_changed();
00594 }
00595 }
00596
00597 void
00598 Bvert::degree_changed()
00599 {
00600 clear_bit(VALID_STRESSED_BIT);
00601
00602 star_changed();
00603 normal_changed();
00604 }
00605
00606 void
00607 Bvert::normal_changed()
00608 {
00609 clear_bit(VALID_NORMAL_BIT);
00610 clear_bit(VALID_STRESSED_BIT);
00611
00612
00613 Bsimplex::normal_changed();
00614 }
00615
00616 double
00617 Bvert::star_sum_angles() const
00618 {
00619
00620
00621 static Bface_list star(32);
00622 get_faces(star);
00623
00624 double ret = 0;
00625 for (int i=0; i<star.num(); i++)
00626 ret += star[i]->angle(this);
00627 return ret;
00628 }
00629
00630 double
00631 Bvert::star_area() const
00632 {
00633
00634
00635 static Bface_list star(32);
00636 get_faces(star);
00637
00638 double ret = 0;
00639 for (int i=0; i<star.num(); i++)
00640 ret += star[i]->area();
00641 return ret;
00642 }
00643
00644 bool
00645 Bvert::is_sharp_point(double sharpness)
00646 {
00647
00648
00649
00650 return (2*M_PI) - star_sum_angles() > sharpness;
00651 }
00652
00653 Wpt
00654 Bvert::eye_local() const
00655 {
00656 return mesh() ? mesh()->eye_local() : VIEW::eye();
00657 }
00658
00659 inline Bvert_list
00660 get_nbrs(const Bvert* v, CBedge_list& edges)
00661 {
00662
00663
00664
00665 assert(v);
00666 Bvert_list ret(edges.num());
00667 for (int i=0; i<edges.num(); i++) {
00668 assert(v->nbr(edges[i]));
00669 ret += v->nbr(edges[i]);
00670 }
00671 return ret;
00672 }
00673
00674 Wpt
00675 Bvert::centroid() const
00676 {
00677 Wpt ret;
00678 double w = 0;
00679 Bedge_list star = get_manifold_edges();
00680
00681 if (star.empty())
00682 return loc();
00683
00684 if (star.any_satisfy(BorderEdgeFilter()))
00685 return ::get_nbrs(this, star.filter(BorderEdgeFilter())).center();
00686
00687 for (int i=0; i<star.num(); i++) {
00688 ret = ret + nbr_loc(star[i]);
00689 w += 1.0;
00690 }
00691 assert(w > 0);
00692 return ret/w;
00693 }
00694
00695 Wpt
00696 Bvert::area_centroid() const
00697 {
00698 Wpt ret;
00699 double total_weight = 0;
00700 double w=0;
00701 Bedge_list star = get_manifold_edges();
00702
00703 if (star.empty())
00704 return loc();
00705
00706 if (star.any_satisfy(BorderEdgeFilter()))
00707 return ::get_nbrs(this, star.filter(BorderEdgeFilter())).center();
00708
00709 for (int i=0; i < star.num(); i++) {
00710 Bedge* e = star[i];
00711 w = e->avg_area();
00712 total_weight += w;
00713 ret = ret + (w*nbr_loc(e));
00714 }
00715 assert(total_weight > 0);
00716 return ret / total_weight;
00717 }
00718
00719 Wpt
00720 Bvert::qr_centroid() const
00721 {
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746 Wpt ret;
00747 double net_weight = 0;
00748 Bedge_list star = get_manifold_edges();
00749
00750 if (star.empty())
00751 return loc();
00752
00753
00754
00755
00756
00757
00758
00759
00760 double avg_len = star.avg_len();
00761 assert(avg_len > 0);
00762 for (int i=0; i<star.num(); i++) {
00763 Bedge* e = star[i];
00764 if (e->is_strong()) {
00765
00766 double w = e->length()/avg_len;
00767 ret = ret + w*nbr_loc(e);
00768 net_weight += w;
00769 Bface* f = ccw_face(e, this);
00770 if (f && f->is_quad() && f->quad_opposite_vert(this)) {
00771
00772 Bvert* q = f->quad_opposite_vert(this);
00773 w = 0.5*q->loc().dist(loc())/avg_len;
00774 ret = ret + w*q->loc();
00775 net_weight += w;
00776 }
00777 }
00778 }
00779 assert(net_weight > 0);
00780 return ret/net_weight;
00781 }
00782
00783 bool
00784 Bvert::view_intersect(
00785 CNDCpt& p,
00786 Wpt& nearpt,
00787 double& dist,
00788 double& d2d,
00789 Wvec& n
00790 ) const
00791 {
00792
00793
00794
00795
00796
00797
00798
00799 nearpt = wloc();
00800 Wpt eye = XYpt(p);
00801 dist = nearpt.dist(eye);
00802 d2d = PIXEL(nearpt).dist(PIXEL(p));
00803
00804
00805
00806 Wvec n1 = norm();
00807 if (n1.is_null())
00808 n1 = eye - loc();
00809
00810
00811 n = (_mesh->inv_xform().transpose()*n1).normalized();
00812
00813 return 1;
00814 }
00815
00816 bool
00817 Bvert::local_search(
00818 Bsimplex *&end,
00819 Wvec &final_bc,
00820 CWpt &target,
00821 Wpt &reached,
00822 Bsimplex *repeater,
00823 int iters)
00824 {
00825 Bface_list star(16);
00826 get_faces(star);
00827 for (int k = star.num()-1; k>=0; k--) {
00828 int good_path = star[k]->local_search(
00829 end, final_bc, target, reached, this, iters-1);
00830 if (good_path == 1)
00831 return 1;
00832 else if (good_path==-1)
00833 return repeater ? true : false;
00834 }
00835 end = this;
00836 final_bc = Wvec(1,0,0);
00837 reached = _loc;
00838
00839 return 1;
00840 }
00841
00842
00843
00844
00845 NDCpt
00846 Bvert::nearest_pt_ndc(
00847 CNDCpt &,
00848 Wvec &bc,
00849 int &is_on_simplex
00850 ) const
00851 {
00852 bc = Wvec(1,0,0);
00853 is_on_simplex = 1;
00854 return _loc;
00855 }
00856
00857 Wpt
00858 Bvert::nearest_pt(CWpt&, Wvec& bc, bool& is_on_simplex) const
00859 {
00860 bc = Wvec(1,0,0);
00861 is_on_simplex = true;
00862 return _loc;
00863 }
00864
00865 BMESHcurvature_data::curv_tensor_t
00866 Bvert::curv_tensor() const
00867 {
00868
00869 return _mesh->curvature()->curv_tensor(this);
00870
00871 }
00872
00873 BMESHcurvature_data::diag_curv_t
00874 Bvert::diag_curv() const
00875 {
00876
00877 return _mesh->curvature()->diag_curv(this);
00878
00879 }
00880
00881 double
00882 Bvert::k1() const
00883 {
00884
00885 return _mesh->curvature()->k1(this);
00886
00887 }
00888
00889 double
00890 Bvert::k2() const
00891 {
00892
00893 return _mesh->curvature()->k2(this);
00894
00895 }
00896
00897 Wvec
00898 Bvert::pdir1() const
00899 {
00900
00901 return _mesh->curvature()->pdir1(this);
00902
00903 }
00904
00905 Wvec
00906 Bvert::pdir2() const
00907 {
00908
00909 return _mesh->curvature()->pdir2(this);
00910
00911 }
00912
00913 BMESHcurvature_data::dcurv_tensor_t
00914 Bvert::dcurv_tensor() const
00915 {
00916
00917 return _mesh->curvature()->dcurv_tensor(this);
00918
00919 }
00920
00921
00922
00923
00924
00925
00926
00927
00928 inline Wtransf mat3_add(CWtransf t1, CWtransf t2)
00929 {
00930 Wtransf t = t1;
00931
00932 t(0,0) += t2(0,0);
00933 t(0,1) += t2(0,1);
00934 t(0,2) += t2(0,2);
00935
00936 t(1,0) += t2(1,0);
00937 t(1,1) += t2(1,1);
00938 t(1,2) += t2(1,2);
00939
00940 t(2,0) += t2(2,0);
00941 t(2,1) += t2(2,1);
00942 t(2,2) += t2(2,2);
00943
00944 return t;
00945 }
00946
00947
00948 inline Wtransf mat3_scale(CWtransf t1, double sc)
00949 {
00950 Wtransf t = t1;
00951
00952 t(0,0) *= sc;
00953 t(0,1) *= sc;
00954 t(0,2) *= sc;
00955 t(1,0) *= sc;
00956 t(1,1) *= sc;
00957 t(1,2) *= sc;
00958 t(2,0) *= sc;
00959 t(2,1) *= sc;
00960 t(2,2) *= sc;
00961
00962 return t;
00963 }
00964
00965
00966 inline Wtransf mat3_identminus(CWtransf t1)
00967 {
00968 Wtransf t = mat3_scale(t1, -1);
00969
00970 t(0,0) += 1;
00971 t(1,1) += 1;
00972 t(2,2) += 1;
00973
00974 return t;
00975 }
00976
00977
00978 inline Wtransf mat3_outerProd(CWvec x, CWvec y)
00979 {
00980 Wtransf ret(x * y[0], x * y[1], x * y[2]);
00981
00982 return ret;
00983 }
00984
00985
00986 inline Wtransf mat3_outerProd(CWvec x)
00987 {
00988 return mat3_outerProd(x, x);
00989 }
00990
00991
00992 inline void mat3_zero(Wtransf &t)
00993 {
00994 t(0,0) = 0;
00995 t(0,1) = 0;
00996 t(0,2) = 0;
00997 t(1,0) = 0;
00998 t(1,1) = 0;
00999 t(1,2) = 0;
01000 t(2,0) = 0;
01001 t(2,1) = 0;
01002 t(2,2) = 0;
01003 }
01004
01005
01006
01007
01008 bool
01009 FoldVertFilter::accept(CBsimplex* s) const
01010 {
01011 if (!is_vert(s))
01012 return false;
01013 Bvert* v = (Bvert*)s;
01014
01015 Bedge_list edges = v->get_adj().filter(_edge_filter);
01016
01017 if (edges.num() != 2)
01018 return false;
01019
01020 return is_fold(
01021 edges[0]->other_vertex(v)->loc(),
01022 v->loc(),
01023 edges[1]->other_vertex(v)->loc(),
01024 v->norm()
01025 );
01026 }
01027
01028 bool
01029 VertDegreeFilter::accept(CBsimplex* s) const
01030 {
01031 if (!is_vert(s))
01032 return false;
01033 Bvert* v = (Bvert*)s;
01034 return v->degree(_edge_filter) == _n;
01035 }
01036
01037
01038
01039
01040 inline bool
01041 get_edge(Bedge_list& list, Bedge* e)
01042 {
01043 if (!e) return false;
01044 list += e;
01045 return true;
01046 }
01047
01048 Bedge_list
01049 Bvert_list::get_chain(bool try_close) const
01050 {
01051
01052
01053
01054 Bedge_list ret(_num);
01055 for (int i=1; i<_num; i++)
01056 if (!get_edge(ret, _array[i]->lookup_edge(_array[i-1])))
01057 return Bedge_list(0);
01058 if (try_close && num() > 2)
01059 get_edge(ret, first()->lookup_edge(last()));
01060
01061 return ret;
01062 }
01063
01064 Bedge_list
01065 Bvert_list::get_closed_chain() const
01066 {
01067
01068
01069
01070
01071 Bedge_list ret = get_chain();
01072 if (ret.empty()) return ret;
01073 if (!get_edge(ret, first()->lookup_edge(last())))
01074 return Bedge_list(0);
01075 return ret;
01076 }
01077
01078 bool
01079 Bvert_list::forms_chain() const
01080 {
01081
01082
01083
01084 return !get_chain().empty();
01085 }
01086
01087 bool
01088 Bvert_list::forms_closed_chain() const
01089 {
01090 return (num() > 1) && forms_chain() && first()->lookup_edge(last());
01091 }
01092
01093 inline void
01094 try_get_face(Bface* f, Bface_list& ret)
01095 {
01096
01097
01098 if ( f && !f->flag() ) {
01099 f->set_flag();
01100 ret += f;
01101 }
01102 }
01103
01104 inline void
01105 try_get_faces(CBedge* e, Bface_list& ret)
01106 {
01107
01108
01109 if (e) {
01110 try_get_face(e->f1(), ret);
01111 try_get_face(e->f2(), ret);
01112 }
01113 }
01114
01115 inline void
01116 try_get_faces(CBedge_list& edges, Bface_list& ret)
01117 {
01118
01119
01120 for (int i=0; i<edges.num(); i++) {
01121 try_get_faces(edges[i], ret);
01122 }
01123 }
01124
01125 Bface_list
01126 Bvert_list::one_ring_faces() const
01127 {
01128
01129
01130 clear_flag02();
01131
01132 Bface_list ret;
01133 for (int i=0; i<_num; i++) {
01134 try_get_faces(_array[i]->get_manifold_edges(), ret);
01135 }
01136 return ret.quad_complete_faces();
01137 }
01138
01139 Bface_list
01140 Bvert_list::two_ring_faces() const
01141 {
01142
01143
01144 return one_ring_faces().one_ring_faces();
01145 }
01146
01147 inline void
01148 try_get_edge(Bedge* e, Bedge_list& ret)
01149 {
01150 if (e && !e->flag()) {
01151 e->set_flag();
01152 ret += e;
01153 }
01154 }
01155
01156 inline void
01157 try_get_edges(CBedge_list& edges, Bedge_list& ret)
01158 {
01159
01160
01161 for (int i=0; i<edges.num(); i++) {
01162 try_get_edge(edges[i], ret);
01163 }
01164 }
01165
01166 Bedge_list
01167 Bvert_list::get_outer_edges() const
01168 {
01169
01170
01171
01172 clear_flag02();
01173 Bedge_list ret;
01174 for (int i=0; i<_num; i++) {
01175 try_get_edges(_array[i]->get_adj(), ret);
01176 }
01177 return ret;
01178 }
01179
01180 inline bool
01181 both_set(Bedge* e)
01182 {
01183 return e && e->v1()->flag() && e->v2()->flag();
01184 }
01185
01186 class VertsSetEdgeFilter : public SimplexFilter {
01187 public:
01188 virtual bool accept(CBsimplex* s) const {
01189 return is_edge(s) && both_set((Bedge*)s);
01190 }
01191 };
01192
01193 Bedge_list
01194 Bvert_list::get_inner_edges() const
01195 {
01196
01197
01198
01199 Bedge_list outer = get_outer_edges();
01200 outer.get_verts().clear_flags();
01201 set_flags(1);
01202 return outer.filter(VertsSetEdgeFilter());
01203 }
01204
01205