void EdgeStrip::build(Bvert* v, Bedge* e, CSimplexFilter& filter) { // continue building the edge strip, starting with the // given edge e. if v is not null, e must contain v. // in that case v will be the leading vertex of the strip. // must have an edge to proceed, // and the edge must be accepted by the filter. if (!(e && filter.accept(e))) // someone has to punch its ticket return; assert(!v || e->contains(v)); static Bvert_list stack(64); stack.clear(); // first loop: build_line_strip(v ? v : e->v1(), e, filter, stack); // get the rest of them while (!stack.empty()) { if ((v = stack.pop()) && (e = next_edge(v, stack, filter))) build_line_strip(v, e, filter, stack); } }
inline Bvert_list reorder(CBedge_list& edges) { Bvert_list ret; Bvert_list verts = edges.get_verts(); for (Bvert_list::size_type i = 0; i < verts.size(); i++) if (Bpoint::find_controller(verts[i]) || Bcurve::find_controller(verts[i])) { ret.push_back(verts[i]); break; } if (ret.empty()) return ret; for (Bvert_list::size_type i = 1; i < verts.size(); i++) { for (Bedge_list::size_type j = 0; j < edges.size(); j++) { Bvert* v = edges[j]->other_vertex(ret.back()); if (v && std::find(ret.begin(), ret.end(), v) == ret.end()) { ret.push_back(v); break; } } } err_adv(debug, " reorder: num of verts: %d", ret.size()); return ret; }
inline double compute_h(Bvert* v) { assert(v); PCell_list cells = Panel::find_cells(v->get_faces()); if (cells.size() == 2) { // common case: vertex in a tube ring (2 neighboring cells) if (Bpoint::find_controller(v) || Bcurve::find_controller(v)) return cells[0]->shared_boundary(cells[1]).avg_len()/2; Bvert_list verts = reorder(cells[0]->shared_boundary(cells[1])); double num = verts.size()-1; assert(num > 1); int index = verts.get_index(v); assert(index != -1); double h = (compute_h(verts.front()) + compute_h(verts.back())) / 2; return h * (1 + min(index/num, 1-index/num)); } else if (cells.size() > 2) { // multiple adjacent cells return PCell::shared_edges(cells).avg_len()/2; } else if (cells.size() == 1) { // just one cell, e.g. tip of a tube, or part of a disk if (cells[0]->num_corners() == 3) { if (cells[0]->nbrs().size() != 1) { return cells[0]->boundary_edges().avg_len()/2; } assert(cells[0]->nbrs().size() == 1); return 0; // it's the tip of the triangle } else if (cells[0]->num_corners() == 4) { if (cells[0]->nbrs().size() == 0) { return cells[0]->boundary_edges().avg_len()/2; } else if (cells[0]->nbrs().size() == 1) { // or maybe should do same rule as next case Bedge_list end_edges = quad_cell_end_edges(cells[0]); err_adv(debug, "found %d end edges", end_edges.size()); return end_edges.avg_len()/2; } return v->strong_edges().avg_len()/2; } if (Bpoint::find_controller(v) || Bcurve::find_controller(v)) return cells[0]->boundary_edges().filter(BorderEdgeFilter()||BcurveFilter()).avg_len()/2; Bvert_list nbrs; v->get_nbrs(nbrs); assert(!nbrs.empty()); return 1.5 * compute_h(nbrs[0]); } err_adv(debug, "compute_h: unexpected number of cells: %d", cells.size()); return -1; }
SubdivUpdater::SubdivUpdater(LMESHptr m, CBvert_list& verts) : _parent(nullptr) { // Screened in SubdivUpdater::create(): assert(m && m == verts.mesh()); _mesh = m; _verts = verts; // Get bbases, add to inputs _inputs = Bbase::find_owners(verts).bnodes(); if (debug) { err_msg("SubdivUpdater::SubdivUpdater:"); cerr << " "; print_dependencies(); err_msg(" level %d, %d verts, %d boss memes", m->subdiv_level(), verts.size(), Bbase::find_boss_vmemes(verts).size()); } // If not covered, create parent if (!Bbase::is_covered(verts)) { // Get parent verts list Bvert_list parents = LMESH::get_subdiv_inputs(verts); // If non-empty create parent SubdivUpdater if (!parents.empty()) { // Create parent subdiv updater on parent verts // and add to _inputs _parent = create(parents); _inputs += _parent; } } hookup(); }