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 void make_strip(Bvert_list chain, int k0, int k1, EdgeStrip& strip) { assert(chain.forms_chain()); assert(0 <= k0 && k0 < (int)chain.size() && 0 <= k1 && k1 < (int)chain.size()); assert(k0 != k1); if (k0 > k1) { std::reverse(chain.begin(), chain.end()); int n = chain.size()-1; k0 = n - k0; k1 = n - k1; } strip.reset(); for (int i=k0; i<k1; i++) { strip.add(chain[i], lookup_edge(chain[i], chain[i+1])); } }
inline void debug_check_verts(const string& msg, CBvert_list& verts, CBvert_list& dirty_verts) { Bvert_list A = verts.filter(BitSetSimplexFilter(Lvert::DIRTY_VERT_LIST_BIT)); if (!dirty_verts.contains_all(A)) { Bvert_list bad = A.minus(dirty_verts); cerr << msg << ": found " << bad.size() << " vertices missing from dirty list" << endl; WORLD::show_pts(bad.pts(), 8, Color::red); } Bvert_list B = verts.filter(BitClearSimplexFilter(Lvert::DIRTY_VERT_LIST_BIT)); if (dirty_verts.contains_any(B)) { Bvert_list bad = dirty_verts.minus(B); cerr << msg << ": found " << bad.size() << " unexpected vertices in dirty list" << endl; WORLD::show_pts(bad.pts(), 8, Color::blue); } }
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; }
bool OVERSKETCH::compute_offsets(CPIXEL_list& pts, CEdgeStrip& sils) { double yardstick = compute_yardstick(sils.edges(), debug); assert(sils.num_line_strips() == 1); Bvert_list chain; int k = 0; sils.get_chain(k, chain); int count = 0; vector<double> offsets; Wpt_list new_locs = chain.pts(); for (Bvert_list::size_type i=0; i<chain.size(); i++) { offsets.push_back(compute_offset(chain[i], pts, yardstick)); if (offsets.back() > 0) { count++; } } err_adv(debug, "found %d/%d offsets", count, chain.size()); apply_offsets(chain, offsets); return true; }
Bvert_list LMESH::get_subdiv_inputs(CBvert_list& verts) { static bool debug = Config::get_var_bool("DEBUG_LMESH_SUBDIV_INPUTS",false); // Given a set of vertices from the same LMESH, return // the vertices of the parent LMESH that affect the // subdivision locations of the given vertices. // Require verts share common LMESH // XXX - could relax this, provided we test each Bvert // to ensure it is really an Lvert. if (!dynamic_pointer_cast<LMESH>(verts.mesh())) return Bvert_list(); // Get direct parent vertices and edges Bvert_list vp; // vertex parents Bedge_list ep; // edge parents get_parents(verts, vp, ep); err_adv(debug, "%d verts: parents: %d verts, %d edges", verts.size(), vp.size(), ep.size()); // Clear flags of all adjacent faces clear_face_flags(vp); ep.clear_flag02(); // Put all adjacent faces into a list Bface_list faces = get_q_faces(vp); err_adv(debug, "parent faces from verts: %d", faces.size()); try_append(faces, ep.get_primary_faces()); err_adv(debug, "parent faces from edges too: %d", faces.size()); // Pull out the vertices: return faces.get_verts(); }