Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

bvert.C

Go to the documentation of this file.
00001 /**********************************************************************
00002  * bvert.C
00003  **********************************************************************/
00004 #include "disp/ray.H"
00005 #include "mi.H"
00006 
00007 using namespace mlib;
00008 
00009 Bvert::~Bvert() 
00010 {
00011    // remove self from global selection list, if needed
00012    if (is_selected()) {
00013       MeshGlobal::deselect(this);
00014    }
00015 
00016    // must be isolated vertex -- make sure
00017    // adjacent edges are removed:
00018    if (_mesh) {
00019       while (degree() > 0)
00020          _mesh->remove_edge(_adj.last());
00021    }
00022 }
00023 
00024 int
00025 Bvert::index() const
00026 {
00027    // index in BMESH Bvert array:
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    // forget about an edge which is disconnecting from this
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    // Returns "neighboring" vertices that share a quad with
00073    // this vertex, and that are positioned at the opposite
00074    // corner.
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    // Return a set of neighboring vertices from the
00114    // given set of edges, all of which must contain
00115    // this vertex (or an assertion failure will occur):
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    // Return a border edge, if any, that forms the leading
00129    // edge for a fan of triangles running in CCW order
00130    // around v.
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    // Return list of edges in CCW order:
00144    // returns an empty list if the operation is invalid.
00145 
00146    // XXX - needs revision to deal w/ non-manifold surfaces.
00147 
00148    // If no edges, nothing to do:
00149    if (degree() < 1)
00150       return Bedge_list();
00151 
00152    // Check number of border edges:
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    // Find an edge to start from for CCW traversal of star faces
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    // add first edge
00169    Bedge_list ret(degree());
00170    ret += start;
00171 
00172    // Repeatedly advance to next face and next edge going CCW.
00173    // Add edges to the list until we reach the start edge.
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    // Arrange edges in counter-clockwise order.
00196 
00197    // Don't redo it if VALID_CCW_BIT indicates the edges are
00198    // already ordereed CCW:
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    // return neighboring vertices in an array
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    // run a sweep over the fan of nm faces originating at <v,e,f>
00235    // and mark them
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    // run a sweep over each fan of nm faces originating at <v,e>
00250    // and mark them
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    // for each nm edge, run over nm faces and mark them
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    // Return adjacent edges the normal way, unless it's a
00288    // "multi" vertex; then return manifold edges.
00289 
00290    if (is_manifold()) {
00291       ret = _adj;
00292       return;
00293    }
00294    // clear all edge and face flags:
00295    _adj.clear_flag02();
00296 
00297    // set flags on faces we don't want:
00298    mark_pushed_faces(this, _adj.filter(MultiEdgeFilter()));
00299 
00300    // collect up edges adjacent to faces we do want:
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    // Helper function used below in Bvert::get_faces()
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    // Return a list of faces in the star of this vertex.
00327    //
00328    // At a non-manifold part of the mesh,
00329    // select faces just from the primary layer
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    // Helper method used in add_quad_partners() below.
00342    // Add a non-null face uniquely to the list.
00343 
00344    if (f)
00345       faces.add_uniquely(f);
00346 }
00347 
00348 inline void
00349 add_quad_partners(ARRAY<Bface*>& faces)
00350 {
00351    // Expand the given face list to include "quad partners"
00352    // of any of the faces in the original list.
00353 
00354    // Work backwards to add faces as we go.
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    // Return a list of faces in the star of this vertex,
00363    // including both faces of every quad adjacent to this vertex.
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    // Return ALL faces incident to the vertex,
00400    // including faces adjacent to non-manifold ("multi") edges:
00401 
00402    // get ordinary (manifold) faces:
00403    get_faces(ret);
00404 
00405    // if there are no "multi" edges, we're done
00406    if (is_manifold())
00407       return;
00408 
00409    // collect up additional faces from multi-edges
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    // Helper function used below in Bvert::get_quad_faces()
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    // Return a list of quads in the star of this vertex.
00439    //
00440    // At a non-manifold part of the mesh,
00441    // select quads just from the primary layer
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    // within the star of this vertex, return the number of
00474    // faces that satisify the given filter:
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    // Computes angle-weighted average normal from the given faces:
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    // if all edges are "polylines" (no adjacent faces), do nothing:
00514    if (_adj.all_satisfy(PolylineEdgeFilter()))
00515       return;
00516 
00517    // get star faces
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    // return a normal WRT faces accepted by the given filter:
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    // normal transformed to world space
00536    // xf.inverse().transpose() * norm
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    // Return a list of distinct "normals." For a vertex that
00548    // contains no crease edges just return the single vertex
00549    // normal. Otherwise return 1 distinct normal for each sector
00550    // of faces between crease edges.
00551 
00552    // XXX - should be more efficient.
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    // The location of this vertex changed...
00572 
00573    // Notify simplex data
00574    Bsimplex::geometry_changed();
00575 
00576    int i;
00577 
00578    // Tell adjacent edges they changed shape:
00579    for (i=0; i<_adj.num(); i++)
00580       _adj[i]->geometry_changed();
00581 
00582    // Tell 1-ring faces they changed shape, which will cause each
00583    // of them to call normal_changed() on their adjacent vertices
00584    // and edges.
00585    //
00586    // XXX - This is not optimally efficient, because
00587    // non-border edges will receive 2 normal_changed()
00588    // notifications, and so will each vertex at the opposite
00589    // ends of those edges.
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    // notify simplex data
00613    Bsimplex::normal_changed();
00614 }
00615 
00616 double
00617 Bvert::star_sum_angles() const
00618 {
00619    // add up "interior" angles around the vertex
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    // add up the areas of the triangles around the vertex
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    // add up angles around this vertex.
00648    // if it's much less than 2 pi say this is "sharp".
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    // The edges must contain vertex v;
00663    // Returns corresponding opposite verts.
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;                                     // computed centroid to be returned
00678    double w = 0;                                // net weight
00679    Bedge_list star = get_manifold_edges();      // work with primary layer 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;                                     // computed centroid to be returned
00699    double total_weight = 0;                     // net weight
00700    double w=0;                                  // weight for a given neighbor
00701    Bedge_list star = get_manifold_edges();      // work with primary layer 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    //   Special kind of centroid that weights regular ("r")
00723    //   neighbors differently from quad ("q") neighbors:
00724    //
00725    //              q -------- r -------- q              
00726    //              |          |          |            
00727    //              |          |          |            
00728    //              |          |          |            
00729    //              |          |          |            
00730    //              |          |          |            
00731    //              r -------- v -------- r              
00732    //              |         / \         |               
00733    //              |       /     \       |              
00734    //              |     /         \     |               
00735    //              |   /             \   |               
00736    //              | /                 \ |               
00737    //             r -------------------- r  
00738    // 
00739    //    There are 2 kinds of "neighboring" vertices: regular (r)
00740    //    vertices, joined to this vertex by a strong edge, and
00741    //    quad (q) vertices, which lie at the opposite corner of a
00742    //    quad from this vertex.  q vertices are not necessarily
00743    //    connected to this vertex by an edge. r vertices are
00744    //    weighted by 1, q vertices are weighted by 1/2.
00745 
00746    Wpt ret;  // computed centroid to be returned
00747    double net_weight = 0; 
00748    Bedge_list star = get_manifold_edges(); // work with primary layer edges
00749 
00750    if (star.empty())
00751       return loc();
00752 /*
00753    if (0) {
00754       BorderEdgeFilter b;
00755       PolylineEdgeFilter p;
00756       if (star.any_satisfy(b || p))
00757          return ::get_nbrs(this, star.filter(b || p)).center();
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          // add contribution from r neighbor
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             // add contribution from q neighbor
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,           // Screen point at which to do intersect
00786    Wpt&    nearpt,      // Point on vert visually nearest to p
00787    double& dist,        // Distance from nearpt to ray from camera
00788    double& d2d,         // Distance in pixels nearpt to p
00789    Wvec& n              // "normal" at nearpt
00790    ) const
00791 {
00792    // (Bsimplex virtual method):
00793    // Intersection w/ ray from given screen point -- returns the point
00794    // on the Bvert that is nearest to the given screen space point.
00795    // Note: the returned "near point" and "normal" are both
00796    //       transformed to world space.
00797 
00798    // HEY! This is easy!!!
00799    nearpt = wloc();
00800    Wpt eye = XYpt(p);
00801    dist = nearpt.dist(eye);
00802    d2d  = PIXEL(nearpt).dist(PIXEL(p));
00803 
00804    // Go for average of face normals if available, or else vector
00805    // to camera:
00806    Wvec n1 = norm();
00807    if (n1.is_null())
00808       n1 = eye - loc();
00809 
00810    // Transform the normal properly:
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)   // XXX - TODO: figure out what this means
00833          return repeater ? true : false; // XXX - used to return -1 : 0 -- should check
00834    }
00835    end = this;
00836    final_bc = Wvec(1,0,0);
00837    reached = _loc;
00838 
00839    return 1;
00840 }
00841 
00842 // TODO: unreadable arguments!
00843 // what's input? what's output?
00844 //              -tc
00845 NDCpt 
00846 Bvert::nearest_pt_ndc(
00847    CNDCpt &/*p*/,
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  * Stuff for computing curvatures at vertices
00923  *****************************************************************/
00924 
00925 // First, some 3x3 matrix stuff
00926 
00927 // 3x3 matrix: t1 + t2
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 // 3x3 matrix: t1 * sc
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 // 3x3 matrix:  I-t1
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 // outer product of two vectors
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 // outer product of vector with itself
00986 inline Wtransf mat3_outerProd(CWvec x)
00987 {
00988     return mat3_outerProd(x, x);
00989 }
00990 
00991 // zero out this matrix
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  * Bvert filters
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  * Bvert_list
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    // Return the chain of edges formed by the vertices
01052    // (or the empty list)
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())); // gets the edge if it exists
01060       
01061    return ret;
01062 }
01063 
01064 Bedge_list
01065 Bvert_list::get_closed_chain() const
01066 {
01067    // Same as get_chain(), but includes the edge
01068    // joining first and last vertices. Returns
01069    // the empty list if it failed.
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    // Are the vertices joined sequentially by edges in a
01082    // connected chain?
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    // Convenience method used in 1-ring extractions, below
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    // Convenience method used in 1-ring extractions, below
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    // Convenience method used in 1-ring extractions, below
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    // Returns the 1-ring faces of a set of vertices
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    // Returns the 2-ring faces of a set of vertices:
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    // Convenience method used in 1-ring extractions, below
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    // Return the set of edges containing at least 1 vertex
01170    // from this set
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    // Return the set of edges that connect 2 vertices
01197    // from this set
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 // end of file bvert.C

Generated on Mon Sep 18 11:39:28 2006 for jot by  doxygen 1.4.4