Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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);
}
Ejemplo n.º 3
0
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);
   }
}
Ejemplo n.º 4
0
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();
}