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

ledge.C

Go to the documentation of this file.
00001 /**********************************************************************
00002  * ledge.C
00003  **********************************************************************/
00004 #include "std/config.H"
00005 #include "subdiv_calc.H"
00006 #include "lmesh.H"
00007 #include "mi.H"
00008 
00009 Ledge::~Ledge() 
00010 {
00011    // The first thing we do is kill all the adjacent faces.
00012    // If we don't do it now, it will happen in the Bedge
00013    // destructor; then the faces will call Bedge::operator-=(Bface*);
00014    // that will trigger a call to an Ledge virtual method,
00015    // but since the Ledge destructor will have completed,
00016    // the result is a seg fault.
00017    if (_mesh) {
00018       if (_f1) _mesh->remove_face(_f1);
00019       if (_f2) _mesh->remove_face(_f2);
00020       if (_adj) {
00021          for (int i=0; i<_adj->num(); i++)
00022             _mesh->remove_face((*_adj)[i]);
00023       }
00024    }
00025 
00026    // and kill off subdiv elements, if any
00027    delete_subdiv_elements(); 
00028 }
00029 
00030 Ledge*
00031 Ledge::subdiv_edge1() const 
00032 {
00033    return (Ledge*)lookup_edge(lv(1)->subdiv_vertex(),_subdiv_vertex);
00034 }
00035 
00036 Ledge*
00037 Ledge::subdiv_edge2() const 
00038 {
00039    return (Ledge*)lookup_edge(lv(2)->subdiv_vertex(),_subdiv_vertex);
00040 }
00041 
00042 Ledge*
00043 Ledge::parallel_sub_edge(int k) const
00044 {
00045    Lface* f = lf(k);
00046    if (!(f && (f = f->subdiv_face_center())))
00047       return 0;
00048    return (Ledge*)f->opposite_edge(_subdiv_vertex);
00049 }
00050 
00051 Ledge* 
00052 Ledge::parent_edge(int rel_level) const 
00053 { 
00054    // Get parent edge (it it exists) at the given relative
00055    // level up from this edge
00056 
00057    Ledge* e = (Ledge*)this; 
00058    for (int i=0; e && i<rel_level; i++) {
00059       Bsimplex* p = e->parent();
00060       if (!is_edge(p))
00061          return 0;
00062       e = (Ledge*)p;
00063    }
00064 
00065    return e;
00066 }
00067 
00068 Bsimplex* 
00069 Ledge::ctrl_element() const 
00070 {
00071    if (!_parent)
00072       return (Bsimplex*)this;
00073    if (is_edge(_parent))
00074       return ((Ledge*)_parent)->ctrl_element();
00075    if (is_face(_parent))
00076       return ((Lface*)_parent)->control_face();
00077    return 0;
00078 }
00079 
00080 uint 
00081 Ledge::rel_level() const
00082 {
00083    // Difference between subdiv level of this edge and its control element
00084 
00085    Bsimplex* c = ctrl_element();
00086    return (mesh() && c && c->mesh()) ?
00087       mesh()->subdiv_level() - c->mesh()->subdiv_level() : 0;
00088 }
00089 
00090 void
00091 Ledge::delete_subdiv_elements()
00092 {
00093    // removing the subdiv vertex also causes any
00094    // adjacent edges or faces in the subdivision
00095    // mesh to be removed -- specifically the two
00096    // subdivision edges generated by *this* edge
00097 
00098    // Make this lightweight, so you can call
00099    // it when you're not sure if you need to:
00100    if (!is_set(SUBDIV_ALLOCATED_BIT))
00101       return;
00102    clear_bit(SUBDIV_ALLOCATED_BIT);
00103 
00104    if (_subdiv_vertex) {
00105       _subdiv_vertex->mesh()->remove_vertex(_subdiv_vertex);
00106 
00107       // after this we need to get treated as a "dirty" edge.
00108       // that means the vertices have to be dirty
00109       lv(1)->mark_dirty();
00110       lv(2)->mark_dirty();
00111    }
00112 }
00113 
00114 void    
00115 Ledge::subdiv_vert_deleted() 
00116 { 
00117    _subdiv_vertex = 0; 
00118 
00119    clear_bit(SUBDIV_LOC_VALID_BIT);
00120    clear_bit(SUBDIV_COLOR_VALID_BIT);
00121    clear_bit(SUBDIV_CREASE_VALID_BIT);
00122 }
00123 
00124 
00125 int  
00126 Ledge::redefine(Bvert *v, Bvert *u)
00127 {
00128    delete_subdiv_elements();
00129    return Bedge::redefine(v,u);
00130 }
00131 
00132 void 
00133 Ledge::set_new_vertices(Bvert *v1, Bvert *v2)
00134 {
00135    delete_subdiv_elements();
00136    Bedge::set_new_vertices(v1, v2);
00137 }
00138 
00139 inline void
00140 swap_edge(Bedge* e)
00141 {
00142    if (e) e->do_swap();
00143 }
00144 
00145 bool
00146 Ledge::do_swap()
00147 {
00148    if (!swap_is_legal())
00149       return false;
00150 
00151    if (is_set(SUBDIV_ALLOCATED_BIT)) {
00152       Bedge* e1 = subdiv_edge1();
00153       Bedge* e2 = subdiv_edge2();
00154       Bedge* e3 = parallel_sub_edge(1);
00155       Bedge* e4 = parallel_sub_edge(2);
00156       swap_edge(e1);
00157       swap_edge(e2);
00158       swap_edge(e3);
00159       swap_edge(e4);
00160    }
00161    return Bedge::do_swap();
00162 }
00163 
00164 bool
00165 Ledge::add_multi(Bface* f)
00166 {
00167    if (Bedge::add_multi(f)) {
00168       push_multi(f);
00169       return true;
00170    }
00171    return false;
00172 }
00173 
00174 bool
00175 Ledge::add_primary(Bface* f)
00176 {
00177    if (Bedge::add_primary(f)) {
00178       push_primary(f);
00179       return true;
00180    }
00181    return false;
00182 }
00183 
00184 void
00185 Ledge::get_sub_faces(Bface* f, Bedge* &e1, Bface* &sf1, Bedge* &e2, Bface* &sf2)
00186 {
00187 //     The diagram shows the situation one level down in the
00188 //     subdivision hierarchy. This edge runs from sv1 to sv2.
00189 //     Return values are the child/face pairs e1/sf1, e2/sf2.
00190 //
00191 //                        /\                                       #
00192 //                       /  \                                      #
00193 //                      /    \                                     #
00194 //                     /      \                                    #
00195 //                    /        \                                   #
00196 //                   /          \                                  #
00197 //                  /            \                                 #
00198 //             sva /______________\ svb                            #
00199 //                /\              /\                               #
00200 //               /  \            /  \                              #
00201 //              /    \          /    \                             #
00202 //             /      \        /      \                            #
00203 //            /        \      /        \                           #
00204 //           /   sf1    \    /   sf2    \                          #
00205 //          /            \  /            \                         #
00206 //         /              \/              \                        #
00207 //     sv1 -------------------------------- sv2                    #
00208 //              e1        sve      e2                              #
00209 
00210    e1  = e2  = 0;
00211    sf1 = sf2 = 0;
00212 
00213    Lvert* sve = _subdiv_vertex;
00214 
00215    if (!sve)
00216       return;
00217 
00218    // Parent verts for sv1 and sv2:
00219    // (may be in reverse order from _v1 and _v2 in this edge):
00220    Lvert* pv1 = (Lvert*)f->leading_vert_ccw(this);
00221    Lvert* pv2 = (Lvert*)f->next_vert_ccw(pv1);
00222    assert(pv1 && pv2);
00223 
00224    Lvert* sv1 = pv1->subdiv_vertex();
00225    if (sv1) {
00226       e1 = sv1->lookup_edge(sve);
00227       if (e1) {
00228          Lvert* sva = ((Ledge*)f->edge_before_vert(pv1))->subdiv_vertex();
00229          sf1 = ::lookup_face(sv1, sve, sva);
00230       }
00231    }
00232 
00233    Lvert* sv2 = pv2->subdiv_vertex();
00234    if (sv2) {
00235       e2 = sv2->lookup_edge(sve);
00236       if (e2) {
00237          Lvert* svb = ((Ledge*)f->edge_from_vert(pv2))->subdiv_vertex();
00238          sf2 = ::lookup_face(sve, sv2, svb);
00239       }
00240    }
00241 }
00242 
00243 void
00244 Ledge::push_multi(Bface* f)
00245 {
00246    // If the given face is a secondary face WRT this edge,
00247    // then ensure its children have the same relationship
00248    // WRT the child edges of this edge.
00249 
00250    if (!is_multi(f))
00251       return;
00252 
00253    // See the diagram of child elements in
00254    // Ledge::get_sub_faces(), above.
00255    Bedge  *e1=0,  *e2=0;
00256    Bface *sf1=0, *sf2=0;
00257    get_sub_faces(f, e1, sf1, e2, sf2);
00258 
00259    if (e1 && sf1)
00260       e1->demote(sf1);
00261    if (e2 && sf2)
00262       e2->demote(sf2);
00263 }
00264 
00265 void
00266 Ledge::push_primary(Bface* f)
00267 {
00268    // If the given face is a primary face WRT this edge,
00269    // then ensure its children have the same relationship
00270    // WRT the child edges of this edge.
00271 
00272    if (!(f == _f1 || f == _f2))
00273       return;
00274 
00275    // See the diagram of child elements in
00276    // Ledge::get_sub_faces(), above.
00277    Bedge  *e1=0,  *e2=0;
00278    Bface *sf1=0, *sf2=0;
00279    get_sub_faces(f, e1, sf1, e2, sf2);
00280 
00281    if (e1 && sf1)
00282       e1->promote(sf1);
00283    if (e2 && sf2)
00284       e2->promote(sf2);
00285 }
00286 
00287 void
00288 Ledge::claim_child(Ledge* child)
00289 {
00290    if (!child)
00291       return;
00292 
00293    // Record this face as the child's parent
00294    assert(child->parent() == NULL);
00295    child->set_parent(this);
00296 
00297    // Propagate attributes to child:
00298    if (is_weak())
00299       child->set_bit(WEAK_BIT);
00300 
00301    // Add more attributes here... (when needed).
00302 }
00303 
00304 void
00305 Ledge::claim_child(Lvert* child)
00306 {
00307    if (!child)
00308       return;
00309    assert(child->parent() == NULL);
00310 
00311    // Record child, and set this face as the child's parent
00312    _subdiv_vertex = child;
00313    child->set_parent(this);
00314 
00315    // Propagate attributes here... (when needed).
00316 }
00317 
00318 void
00319 Ledge::set_subdiv_elements(Lvert* subv)
00320 {
00321    if (is_set(SUBDIV_ALLOCATED_BIT)) {
00322       err_msg("Ledge::set_subdiv_elements: elements already set");
00323       return;
00324    }
00325    set_bit(SUBDIV_ALLOCATED_BIT);
00326 
00327    assert(_subdiv_vertex == NULL);
00328    if (!subv)
00329       return;
00330    assert(lmesh()->subdiv_mesh() == subv->lmesh());
00331 
00332    claim_child(subv);
00333    claim_child(subdiv_edge1());
00334    claim_child(subdiv_edge2());
00335 
00336    // Notify observers:
00337    if (_data_list)
00338       _data_list->notify_subdiv_gen();
00339 }
00340 
00341 void
00342 Ledge::allocate_subdiv_elements()
00343 {
00344    // The policy is: if the edge's subdiv vertex is allocated,
00345    // then the subdiv edges must already be allocated.
00346    //
00347    // So when _subdiv_vertex != NULL this is a no-op.
00348 
00349    // Make this lightweight, so you can call
00350    // it when you're not sure if you need to:
00351    if (is_set(SUBDIV_ALLOCATED_BIT))
00352       return;
00353    set_bit(SUBDIV_ALLOCATED_BIT);
00354 
00355    assert(!_subdiv_vertex);
00356 
00357    LMESH* submesh = lmesh()->subdiv_mesh();
00358    assert(submesh);
00359 
00360    // Allocate subdiv vertex in middle:
00361    claim_child((Lvert*)submesh->add_vertex(mid_pt()));
00362 
00363    if (!_subdiv_vertex)
00364       return;
00365 
00366    // Allocate two edges (making sure endpoint verts are
00367    // allocated).
00368    //
00369    // We preserve the directedness of the edge. I.e., the
00370    // forward direction of the edge is from v1 to v2, and we
00371    // keep the same directedness in the subdiv edges.
00372 
00373    Bvert* u1 = lv(1)->allocate_subdiv_vert();
00374    if (u1) {
00375       claim_child((Ledge*)submesh->add_edge(u1, _subdiv_vertex));
00376    }
00377 
00378    Bvert* u2 = lv(2)->allocate_subdiv_vert();
00379    if (u2) {
00380       claim_child((Ledge*)submesh->add_edge(_subdiv_vertex,u2));
00381    }
00382 
00383    // Notify observers:
00384    if (_data_list)
00385       _data_list->notify_subdiv_gen();
00386 }
00387 
00388 // Helper used below in Ledge::append_subdiv_edges():
00389 inline bool
00390 get_subdiv_edges(Ledge* e, int lev, ARRAY<Bedge*>& edges)
00391 {
00392    return e ? e->append_subdiv_edges(lev, edges) : false;
00393 }
00394 
00395 bool
00396 Ledge::append_subdiv_edges(int lev, ARRAY<Bedge*>& edges)
00397 {
00398    // Return an ordered list of edges at the given subdiv level
00399    // *relative* to the level of this edge. (Level must be >= 0).
00400    // E.g. level 1 means one level down the subdivision hierarchy.
00401    // The returned edges run in the direction of v1 to v2.
00402 
00403    // Use depth-first search.
00404 
00405    if (lev < 0) {
00406       err_msg("Ledge::append_subdiv_edges: error: bad level: %d", lev);
00407       return false;
00408    } else if (lev == 0) {
00409       edges += this;
00410       return true;
00411    } else {
00412       return (
00413          get_subdiv_edges(subdiv_edge1(), lev - 1, edges) &&
00414          get_subdiv_edges(subdiv_edge2(), lev - 1, edges)
00415          );
00416    }
00417 }
00418 
00419 bool
00420 Ledge::get_subdiv_verts(int lev, Bvert_list& ret)
00421 {
00422    // Similar to append_subdiv_edges(), but returns the
00423    // ordered list of subdiv verts at the given level lev >= 0:
00424 
00425    ret.clear();
00426    Bedge_list edges;
00427    if (!append_subdiv_edges(lev, edges))
00428       return false;
00429    Lvert* v = lv(1)->subdiv_vert(lev);
00430    assert(v && !edges.empty() && edges.first()->contains(v));
00431    ret += v;
00432    for (int i=0; i<edges.num(); i++) {
00433       ret += edges[i]->other_vertex(ret.last());
00434    }
00435    return true;
00436 }
00437 
00438 inline void
00439 set_crease(Ledge* e, unsigned short c) { if (e) e->set_crease(c); }
00440 
00441 void
00442 Ledge::update_subdivision()
00443 {
00444    // make sure subdiv vert and edges are allocated:
00445    allocate_subdiv_elements();
00446 
00447    // our child may have been deleted in a mesh edit next
00448    // level down
00449    if (!_subdiv_vertex)
00450       return;
00451 
00452    // propagate variable sharpness crease (if needed):
00453    if (is_clear(SUBDIV_CREASE_VALID_BIT)) {
00454       set_bit(SUBDIV_CREASE_VALID_BIT);
00455       unsigned short subcrease = (_crease > 0) ? _crease - 1 : 0;
00456       ::set_crease(subdiv_edge1(), subcrease);
00457       ::set_crease(subdiv_edge2(), subcrease);
00458    }
00459 
00460    // calculate subdiv color (if needed):
00461    if (is_clear(SUBDIV_COLOR_VALID_BIT)) {
00462       set_bit(SUBDIV_COLOR_VALID_BIT);
00463       if (_v1->has_color())
00464          _subdiv_vertex->set_color(lmesh()->subdiv_color(this));
00465    }
00466 
00467    // calculate subdiv loc:
00468    if (is_clear(SUBDIV_LOC_VALID_BIT)) {
00469       set_bit(SUBDIV_LOC_VALID_BIT);
00470 
00471       // Defer to observers
00472       if (!_data_list || !_data_list->handle_subdiv_calc())
00473          _subdiv_vertex->set_subdiv_base_loc(lmesh()->subdiv_loc(this));
00474    }
00475 }
00476 
00477 unsigned short 
00478 Ledge::subdiv_mask() const 
00479 {
00480    // problems w/ caching old values...
00481    if (!is_set(MASK_VALID_BIT))
00482       ((Ledge*)this)->set_mask();
00483    return _mask;
00484 }
00485 
00486 void 
00487 Ledge::set_mask() 
00488 {
00489    set_bit(MASK_VALID_BIT);
00490 
00491    if (is_interior() &&
00492        (!is_crease() || lv(1)->is_smooth() || lv(2)->is_smooth())) {
00493          _mask = REGULAR_SMOOTH_EDGE;
00494    } else {
00495       _mask = REGULAR_CREASE_EDGE;
00496    }
00497 }
00498 
00499 void
00500 Ledge::set_crease(unsigned short c)
00501 {
00502    if (c != _crease) {
00503       Bedge::set_crease(_crease = c);
00504       if (c == 0)
00505          Bedge::clear_bit(CREASE_BIT);
00506       crease_changed();
00507    }
00508 }
00509 
00510 void 
00511 Ledge::crease_changed()
00512 {
00513    Bedge::crease_changed();
00514 
00515    clear_bit(SUBDIV_CREASE_VALID_BIT);
00516    mask_changed();
00517    lv(1)->mask_changed();
00518    lv(2)->mask_changed();
00519 }
00520 
00521 void  
00522 Ledge::normal_changed()        
00523 {
00524    Bedge::normal_changed();
00525 
00526    subdiv_loc_changed(); 
00527 }
00528 
00529 void  
00530 Ledge::geometry_changed()
00531 {
00532    Bedge::geometry_changed();
00533 
00534    subdiv_loc_changed(); 
00535 }
00536 
00537 void 
00538 Ledge::color_changed()
00539 {
00540    // XXX - should fix for non-manifold case
00541 
00542    if (_f1) lf(1)->color_changed();
00543    if (_f2) lf(2)->color_changed();
00544 }
00545 
00546 void 
00547 Ledge::faces_changed()
00548 {
00549    // called when faces are added or deleted
00550 
00551    mask_changed();       
00552 
00553    lv(1)->mask_changed();
00554    lv(2)->mask_changed();
00555 }
00556 
00557 void 
00558 Ledge::mask_changed()
00559 {
00560    clear_bit(MASK_VALID_BIT);
00561    subdiv_loc_changed();
00562    subdiv_color_changed();
00563 }
00564 
00565 /*****************************************************************
00566  *  get_subdiv_chain:
00567  *****************************************************************/
00568 bool
00569 get_subdiv_chain(Bvert* v1, Bvert* v2, int level, Bvert_list& ret)
00570 {
00571    // Given vertices v1 and v2 joined by an Ledge, recursively
00572    // extract chain of subdivision vertices generated along the
00573    // edge at the given level (relative to the original edge):
00574 
00575    static bool debug = Config::get_var_bool("DEBUG_GET_SUBDIV_CHAIN",false);
00576 
00577    ret.clear();
00578 
00579    if (!(v1 && v2)) {
00580       err_adv(debug, "get_subdiv_chain: null vertex (level %d)", level);
00581       return 0;
00582    }
00583 
00584    if (!(v1->mesh() == v2->mesh() && LMESH::isa(v1->mesh()))){
00585       err_adv(debug, "get_subdiv_chain: non-LMESH (level %d)", level);
00586       return 0;
00587    }
00588 
00589    if (level < 0){
00590       err_adv(debug, "get_subdiv_chain: negative level (%d)", level);
00591       return 0;
00592    }
00593 
00594    Bedge* e = v1->lookup_edge(v2);
00595    if (!e){
00596       err_adv(debug, "get_subdiv_chain: verts don't form edge (level %d)",
00597               level);
00598       return 0;
00599    }
00600 
00601    if (level == 0) {
00602       ret += v1;
00603       ret += v2;
00604       return true;
00605    }
00606 
00607    Bvert* s1 = ((Lvert*)v1)->subdiv_vertex();
00608    Bvert* sv = ((Ledge*)e) ->subdiv_vertex();
00609    Bvert* s2 = ((Lvert*)v2)->subdiv_vertex();
00610 
00611    Bvert_list l1;
00612    Bvert_list l2;
00613 
00614    if (!(get_subdiv_chain(s1, sv, level-1, l1) &&
00615          get_subdiv_chain(sv, s2, level-1, l2))) {
00616       return 0;
00617    }
00618     
00619    l1.pop();
00620    ret = l1 + l2;
00621    return true;
00622 } 
00623 
00624 /*****************************************************************
00625  *  get_subdiv_chain:
00626  *****************************************************************/
00627 bool 
00628 get_subdiv_chain(CBvert_list& chain, int level, Bvert_list& ret)
00629 {
00630    //  Given a connected chain of vertices, recursively extract
00631    //  the corresponding chain of subdivision vertices at the
00632    //  given level (relative to the original chain). On failure
00633    //  returns the empty list.
00634 
00635    static bool debug = Config::get_var_bool("DEBUG_GET_SUBDIV_CHAIN",false);
00636 
00637    ret.clear();
00638 
00639    if (level < 0) {
00640       err_adv(debug, "get_subdiv_chain: negative level (%d)", level);
00641       return 0;
00642    }
00643 
00644    if (chain.empty()) {
00645       err_adv(debug, "get_subdiv_chain: empty chain passed in");
00646       return true;
00647    }
00648 
00649    if (!chain.forms_chain()) {
00650       err_adv(debug, "get_subdiv_chain: non-chain passed in");
00651       return 0;
00652    }
00653 
00654    ret.realloc(((chain.num()-1) * (1 << level)) + 1);
00655 
00656    for (int i=1; i<chain.num(); i++) {
00657       Bvert_list segment;       // sub-chain from vertex i-1 to i
00658       if (!get_subdiv_chain(chain[i-1], chain[i], level, segment))
00659          return false;
00660       if (!ret.empty())
00661          ret.pop();
00662       ret += segment;
00663    }
00664       
00665    return true;
00666 }
00667 
00668 // end of file ledge.C

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