bool Bface::get_quad_verts(Bvert*& a, Bvert*& b, Bvert*& c, Bvert*& d) const { // Return CCW verts a, b, c, d as in the picture, orienting // things so that the weak edge runs NE as shown: // // d ---------- c = w->v2() ^ // | / | | // | / | | // | w / | tan1 tan2 | // | / | --------> | // | / f | | // |/ | // a ---------- b // = w->v1() // if (!is_quad()) return 0; Bedge* w = weak_edge(); Bface* f = w->ccw_face(w->v2()); a = w->v1(); b = f->next_vert_ccw(a); c = w->v2(); d = f->quad_vert(); return true; }
void EdgeStrip::build_with_tips(CBedge_list& edges, CSimplexFilter& filter) { // Build the strip from the given pool of edges, with the // given filter. Try to start the edge strip at the "tips" of // chains of edges of the desired type. The given filter // should just screen for edges of the desired kind; // internally this method also screens for edges that have not // yet been reached (added to the strip). // Clear edge flags to screen for unreached edges: set_adjacent_edges(edges.get_verts(), 1); edges.clear_flags(); // Pull out the edge tips: Bedge_list tips = edges.filter(ChainTipEdgeFilter(filter)); // Construct the filter that screens out previously reached // edges: UnreachedSimplexFilter unreached; AndFilter wanted = unreached + filter; int k; // Start from all the tips first: for (k=0; k<tips.num(); k++) { Bedge* e = tips[k]; Bvert* v = (e->v2()->degree(filter) != 2) ? e->v2() : e->v1(); build(v, e, wanted); } // Now check the rest: for (k=0; k<edges.num(); k++) build(0, edges[k], wanted); }
void EdgeStrip::build_ccw_boundaries( CBedge_list& edges, CSimplexFilter& face_filter ) { // Similar to previous... // // XXX - needs comments // Clear edge flags to screen for unreached edges: // set edge flags to 1 in 1-ring of verts, // then clear edge flags of internal edges set_adjacent_edges(edges.get_verts(), 1); edges.clear_flags(); // get an edge filter that accepts "boundary" edges WRT the // given face filter BoundaryEdgeFilter boundary(face_filter); // Pull out the edge tips: Bedge_list tips = edges.filter(ChainTipEdgeFilter(boundary)); // Construct the filter that screens out previously reached // edges: UnreachedSimplexFilter unreached; AndFilter wanted = unreached + boundary; int k; // Start from all the tips first: for (k=0; k<tips.num(); k++) { Bedge* e = tips[k]; Bvert* v = (e->v2()->degree(boundary) != 2) ? e->v2() : e->v1(); Bface* f = e->screen_face(face_filter); assert(f); // e must have 1 face satisfying the filter // If this will start out running ccw, take it. // otherwise skip: if (f->next_vert_ccw(v) == e->other_vertex(v)) build(v, e, wanted); } // Now check the rest: for (k=0; k<edges.num(); k++) { Bedge* e = edges[k]; Bface* f = e->screen_face(face_filter); assert(f); // e must have 1 face satisfying the filter // Go CCW around faces build(f->leading_vert_ccw(e), e, wanted); } }
void Lface::allocate_subdiv_elements() { // Generate 4 faces and 3 internal edges // in the subdivision mesh next level down. // NOTE: The specific order that sub-faces are created, // and the order of the vertices used in creating them, // should not be changed. The barycentric coordinate // conversion routines (below) depend on these orderings. // Make this lightweight, so you can call // it when you're not sure if you need to: if (is_set(SUBDIV_ALLOCATED_BIT)) return; set_bit(SUBDIV_ALLOCATED_BIT); assert(lmesh() != nullptr); lmesh()->allocate_subdiv_mesh(); LMESHptr submesh = lmesh()->subdiv_mesh(); assert(submesh != nullptr); // lv3 # // /\ # // /3 \ # // / \ # // / \ # // / child3 \ # // / \ # // / 1 2 \ # // le3 /______________\ le2 # // /\ 2 1 /\ # // /3 \ /3 \ # // / \ center / \ # // / \ child / \ # // / \ / \ # // / child1 \ / child2 \ # // / \3 / \ # // / 1 2 \/ 1 2 \ # // lv1 -------------------------------- lv2 # // le1 # // Make sure subdiv elements have // been allocated around face boundary: lv(1)->allocate_subdiv_vert(); lv(2)->allocate_subdiv_vert(); lv(3)->allocate_subdiv_vert(); le(1)->allocate_subdiv_elements(); le(2)->allocate_subdiv_elements(); le(3)->allocate_subdiv_elements(); Patch* child_patch = _patch ? _patch->get_child() : nullptr; // hook up 4 faces (verifying they're not already there): if (!subdiv_face1()) gen_child_face( lv(1)->subdiv_vertex(), le(1)->subdiv_vertex(), le(3)->subdiv_vertex(), child_patch, submesh); if (!subdiv_face2()) gen_child_face( le(1)->subdiv_vertex(), lv(2)->subdiv_vertex(), le(2)->subdiv_vertex(), child_patch, submesh); if (!subdiv_face3()) gen_child_face( le(3)->subdiv_vertex(), le(2)->subdiv_vertex(), lv(3)->subdiv_vertex(), child_patch, submesh); if (!subdiv_face_center()) gen_child_face( le(2)->subdiv_vertex(), le(3)->subdiv_vertex(), le(1)->subdiv_vertex(), child_patch, submesh, true); // true: face is at center if (is_quad()) { // // o // | . // | . // | . w // | . // sub1 o .----- o. // | . | . // | . | . // | .| . // o ------ o ----- o // v sub2 // // A quad face is one that has a "weak" edge // (shown as the dotted edge labelled 'w' above). // A weak edge is considered to be the internal // diagonal edge of a quad, with this face making // up one half of the quad and the face on the // other side (not shown) making up the other // half. In subdivision we label the subdivision // edges accordingly. I.e. the edge connecting // subdivision vertices sub1 and sub2 should be // labelled weak. Bedge* w = weak_edge(); Bvert* v = other_vertex(w); Bvert* sub1 = ((Ledge*)v->lookup_edge(w->v1()))->subdiv_vertex(); Bvert* sub2 = ((Ledge*)v->lookup_edge(w->v2()))->subdiv_vertex(); sub1->lookup_edge(sub2)->set_bit(Bedge::WEAK_BIT); } // Now that child faces are generated, propagate multi // status (if any) to children le(1)->push_multi(this); le(2)->push_multi(this); le(3)->push_multi(this); // Notify observers: if (_data_list) _data_list->notify_subdiv_gen(); }