bool CustomQuadrilateral<ConcreteQuadrilateralType, BaseClass>:: collapse_edges(std::vector<Face*>& vNewFacesOut, std::vector<Vertex*>& vNewEdgeVertices, Vertex** pSubstituteVertices) { if(vNewEdgeVertices.size() > BaseClass::num_edges()) { assert(!"WARNING in Quadrilateral::collapse_edges(...): bad number of newEdgeVertices."); LOG("WARNING in Quadrilateral::collapse_edges(...): bad number of newEdgeVertices."); return false; } vNewFacesOut.clear(); // check if there is a valid entry in vNewEdgeVertices int collapseIndex = -1; int numCollapses = 0; for(uint i = 0; i < 4; ++i) { if(i < vNewEdgeVertices.size()) { if(vNewEdgeVertices[i] != NULL) { ++numCollapses; collapseIndex = i; } } } // if more than 1 edge is collapsed, nothing remains. if(numCollapses == 0) { assert(!"WARNING in Quadrilateral::collapse:edges(...): no new vertex was specified."); LOG("WARNING in Quadrilateral::collapse:edges(...): no new vertex was specified."); return false; } else if(numCollapses == 1) { // call collapse_edge with the edges index. collapse_edge(vNewFacesOut, collapseIndex, vNewEdgeVertices[collapseIndex], pSubstituteVertices); } return true; }
bool EdgeCollapser::collapse_pass() { if ( m_surf.m_verbose ) { std::cout << "\n\n\n---------------------- EdgeCollapser: collapsing ----------------------" << std::endl; std::cout << "m_min_edge_length: " << m_min_edge_length; std::cout << ", m_use_curvature: " << m_use_curvature; std::cout << ", m_min_curvature_multiplier: " << m_min_curvature_multiplier << std::endl; std::cout << "m_surf.m_collision_safety: " << m_surf.m_collision_safety << std::endl; } bool collapse_occurred = false; assert( m_surf.m_dirty_triangles.size() == 0 ); std::vector<SortableEdge> sortable_edges_to_try; // // get set of edges to collapse // for( size_t i = 0; i < m_surf.m_mesh.m_edges.size(); i++ ) { if ( m_surf.m_mesh.edge_is_deleted(i) ) { continue; // skip deleted edges } if ( m_surf.edge_is_solid(i) ) { continue; // skip solids } if ( m_surf.m_mesh.m_edge_to_triangle_map[i].size() < 2 ) { continue; // skip boundary edges } if( m_surf.m_mesh.m_is_boundary_vertex[m_surf.m_mesh.m_edges[i][0]] || m_surf.m_mesh.m_is_boundary_vertex[m_surf.m_mesh.m_edges[i][1]] ) { continue; } double current_length; if ( m_use_curvature ) { current_length = get_curvature_scaled_length( m_surf, m_surf.m_mesh.m_edges[i][0], m_surf.m_mesh.m_edges[i][1], m_min_curvature_multiplier, 1e+30 ); } else { current_length = m_surf.get_edge_length(i); } if ( current_length < m_min_edge_length ) { sortable_edges_to_try.push_back( SortableEdge( i, current_length ) ); } } // // sort in ascending order by length (collapse shortest edges first) // std::sort( sortable_edges_to_try.begin(), sortable_edges_to_try.end() ); if ( m_surf.m_verbose ) { std::cout << sortable_edges_to_try.size() << " candidate edges sorted" << std::endl; std::cout << "total edges: " << m_surf.m_mesh.m_edges.size() << std::endl; } // // attempt to collapse each edge in the sorted list // for ( size_t si = 0; si < sortable_edges_to_try.size(); ++si ) { size_t e = sortable_edges_to_try[si].m_edge_index; assert( e < m_surf.m_mesh.m_edges.size() ); if ( m_surf.m_mesh.edge_is_deleted(e) ) { continue; } double edge_length; if ( m_use_curvature ) { edge_length = get_curvature_scaled_length( m_surf, m_surf.m_mesh.m_edges[e][0], m_surf.m_mesh.m_edges[e][1], m_min_curvature_multiplier, 1e+30 ); } else { edge_length = m_surf.get_edge_length(e); } if ( edge_length < m_min_edge_length ) { if ( m_surf.m_mesh.m_edges[e][0] == m_surf.m_mesh.m_edges[e][1] ) { continue; // skip deleted edges } if ( m_surf.m_mesh.m_edge_to_triangle_map[e].size() < 2 ) { continue; // skip boundary edges } if( m_surf.m_mesh.m_is_boundary_vertex[m_surf.m_mesh.m_edges[e][0]] || m_surf.m_mesh.m_is_boundary_vertex[m_surf.m_mesh.m_edges[e][1]] ) { continue; } bool result = collapse_edge( e ); if ( result ) { // clean up degenerate triangles and tets m_surf.trim_non_manifold( m_surf.m_dirty_triangles ); } collapse_occurred |= result; } } return collapse_occurred; }