//! Given the starting face "orig_face" and an offset amount "dist", //! determine the appropriate edit level, re-map orig_face to that //! level, and "inflate" the portion of the mesh reachable from //! orig_face by amount dist. The offset may be made relative to the //! local edge length. bool INFLATE::do_inflate( Bface* orig_face, double dist, Bsurface*& output, Bface_list*& reversed_faces, MULTI_CMDptr cmd) { // Reject garbage if (fabs(dist) < epsAbsMath()) { err_adv(debug, "INFLATE::do_inflate: bad offset distance: %f", dist); return 0; } // Throw out trash if (!get_lmesh(orig_face)) { err_adv(debug, "INFLATE::do_inflate: error: bad face"); return 0; } Lface* face = (Lface*)orig_face; err_adv(debug, "INFLATE::do_inflate: face at level %d", subdiv_level(face)); // Decide which level to do inflation -- should match offset dist int rel_level = 0; // XXX - it may not be a good idea //if (!choose_level(face, dist, rel_level)) // defined above // return 0; // Remap face to chosen level face = remap(face, rel_level); if (!face) { err_adv(debug, "INFLATE::do_inflate: can't remap %d from level %d", rel_level, subdiv_level(face)); return 0; } assert(face && face->mesh()); err_adv(debug, "chosen edit level: %d", subdiv_level(face)); // Get set of reachable faces: Bface_list set = Bface_list::reachable_faces(face); assert(set.mesh() != NULL); err_adv(debug, "reachable faces: %d, subdiv level: %d, total faces: %d", set.num(), set.mesh()->subdiv_level(), set.mesh()->nfaces()); if (!set.is_consistently_oriented()) { err_msg("INFLATE::do_inflate: rejecting inconsistently \ oriented surface..."); return 0; }
//! Given boundary curve (near-planar), activate the //! widget to inflate ... bool INFLATE::setup(Bface *bf, double dist, double dur) { reset(); // Given the starting face f and an offset amount h, // determine the appropriate edit level, re-map f to that // level, and "inflate" the portion of the mesh reachable // from f by h, relative to the local edge length. // reject garbage if (!(bf && LMESH::isa(bf->mesh()))) { err_adv(debug, "INFLATE::setup: error: bad face"); return 0; } Lface* f = (Lface*)bf; err_adv(debug, "setup: face at level %d", bf->mesh()->subdiv_level()); // get avg edge length of edges in face: double avg_len = avg_strong_edge_len(f); if (avg_len < epsAbsMath()) { err_adv(debug, "INFLATE::setup: bad average edge length: %f", avg_len); return 0; } // Get set of reachable faces: Bface_list set = Bface_list::reachable_faces(f); assert(set.mesh() != NULL); err_adv(debug, "reachable faces: %d, subdiv level: %d, total faces: %d", set.num(), set.mesh()->subdiv_level(), set.mesh()->nfaces()); // given face set should be an entire connected piece. if (!is_maximal_connected(set )) { err_adv(debug, "INFLATE::setup: rejecting subset of surface..."); return 0; } Bface_list p = set;//get_top_level(set); assert(LMESH::isa(p.mesh())); err_adv(debug, "top level: %d faces (out of %d)", p.num(), p.mesh()->nfaces()); BMESH* m = p.mesh(); if (!m) { err_adv(debug, "INFLATE::setup: Error: null mesh"); return 0; } if (!LMESH::isa(m)) { err_adv(debug, "INFLATE::setup: Error: non-LMESH"); return 0; } if (!p.is_consistently_oriented()) { err_adv(debug, "INFLATE::setup: Error: inconsistently oriented faces"); return 0; } // We ensured the mesh in an LMESH so this is okay: _boundary=p.get_boundary(); if (_boundary.edges().empty()) { err_adv(debug, "INFLATE::setup: Error: No boundary. Quitting."); _boundary.reset(); return 0; } // ******** From here on, we accept it ******** err_adv(debug, "Inflating... %d boundary loops", _boundary.num_line_strips()); _faces = p; _mode = false; _d = _boundary.cur_edges().avg_len(); _mesh = (LMESH*)m; _orig_face = bf; _preview_dist = dist; // Set the timeout duration set_timeout(dur); // Become the active widget and get in the world's DRAWN list: activate(); return true; }