void DenseBipartiteGraph::switch_4_cycle(int u1, int v1, int u2, int v2) { if (u1 > v1) { // rotate uint tmp = u1; u1 = v1; v1 = u2; u2 = v2; v2 = tmp; } // translate node labels v1 -= nrows; v2 -= nrows; #ifdef DEBUG std::cout << "switch cycle [ " << u1 << " " << v1 << " " << u2 << " " << v2 << " ]" << std::endl; #endif flip_edge(u1, v1); flip_edge(u1, v2); flip_edge(u2, v1); flip_edge(u2, v2); }
CubitStatus CubitFacetData::flip_edge( CubitFacetEdge *edge ) { int i; for(i=0; i<3; i++) { if (edgeArray[i] == edge) return flip_edge(i); } return CUBIT_FAILURE; }
IGL_INLINE void igl::delaunay_triangulation( const Eigen::PlainObjectBase<DerivedV>& V, Orient2D orient2D, InCircle incircle, Eigen::PlainObjectBase<DerivedF>& F) { assert(V.cols() == 2); typedef typename DerivedF::Scalar Index; typedef typename DerivedV::Scalar Scalar; igl::lexicographic_triangulation(V, orient2D, F); const size_t num_faces = F.rows(); if (num_faces == 0) { // Input points are degenerate. No faces will be generated. return; } assert(F.cols() == 3); Eigen::MatrixXi E; Eigen::MatrixXi uE; Eigen::VectorXi EMAP; std::vector<std::vector<Index> > uE2E; igl::unique_edge_map(F, E, uE, EMAP, uE2E); auto is_delaunay = [&V,&F,&uE2E,num_faces,&incircle](size_t uei) { auto& half_edges = uE2E[uei]; if (half_edges.size() != 2) { throw "Cannot flip non-manifold or boundary edge"; } const size_t f1 = half_edges[0] % num_faces; const size_t f2 = half_edges[1] % num_faces; const size_t c1 = half_edges[0] / num_faces; const size_t c2 = half_edges[1] / num_faces; assert(c1 < 3); assert(c2 < 3); assert(f1 != f2); const size_t v1 = F(f1, (c1+1)%3); const size_t v2 = F(f1, (c1+2)%3); const size_t v4 = F(f1, c1); const size_t v3 = F(f2, c2); const Scalar p1[] = {V(v1, 0), V(v1, 1)}; const Scalar p2[] = {V(v2, 0), V(v2, 1)}; const Scalar p3[] = {V(v3, 0), V(v3, 1)}; const Scalar p4[] = {V(v4, 0), V(v4, 1)}; auto orientation = incircle(p1, p2, p4, p3); return orientation <= 0; }; bool all_delaunay = false; while(!all_delaunay) { all_delaunay = true; for (size_t i=0; i<uE2E.size(); i++) { if (uE2E[i].size() == 2) { if (!is_delaunay(i)) { all_delaunay = false; flip_edge(F, E, uE, EMAP, uE2E, i); } } } } }
void EdgeFlipper::process_mesh( ) { if ( m_surf.m_verbose ) { std::cout << "---------------------- EdgeFlipper: flipping ----------------------" << std::endl; } m_surf.m_dirty_triangles.clear(); bool flip_occurred_ever = false; // A flip occurred in this function call bool flip_occurred = true; // A flip occurred in the current loop iteration static unsigned int MAX_NUM_FLIP_PASSES = 5; unsigned int num_flip_passes = 0; NonDestructiveTriMesh& m_mesh = m_surf.m_mesh; const std::vector<Vec3d>& xs = m_surf.get_positions(); // // Each "pass" is once over the entire set of edges (ignoring edges created during the current pass) // while ( flip_occurred && num_flip_passes++ < MAX_NUM_FLIP_PASSES ) { if ( m_surf.m_verbose ) { std::cout << "---------------------- El Topo: flipping "; std::cout << "pass " << num_flip_passes << "/" << MAX_NUM_FLIP_PASSES; std::cout << "----------------------" << std::endl; } flip_occurred = false; size_t number_of_edges = m_mesh.m_edges.size(); // don't work on newly created edges for( size_t i = 0; i < number_of_edges; i++ ) { if ( m_mesh.m_edges[i][0] == m_mesh.m_edges[i][1] ) { continue; } if ( m_mesh.m_edge_to_triangle_map[i].size() > 4 || m_mesh.m_edge_to_triangle_map[i].size() < 2 ) { continue; } if ( m_mesh.m_is_boundary_vertex[ m_mesh.m_edges[i][0] ] || m_mesh.m_is_boundary_vertex[ m_mesh.m_edges[i][1] ] ) { continue; } // skip boundary vertices size_t triangle_a = (size_t)~0, triangle_b =(size_t)~0; if ( m_mesh.m_edge_to_triangle_map[i].size() == 2 ) { triangle_a = m_mesh.m_edge_to_triangle_map[i][0]; triangle_b = m_mesh.m_edge_to_triangle_map[i][1]; assert ( m_mesh.oriented( m_mesh.m_edges[i][0], m_mesh.m_edges[i][1], m_mesh.get_triangle(triangle_a) ) != m_mesh.oriented( m_mesh.m_edges[i][0], m_mesh.m_edges[i][1], m_mesh.get_triangle(triangle_b) ) ); } else if ( m_mesh.m_edge_to_triangle_map[i].size() == 4 ) { triangle_a = m_mesh.m_edge_to_triangle_map[i][0]; // Find first triangle with orientation opposite triangle_a's orientation unsigned int j = 1; for ( ; j < 4; ++j ) { triangle_b = m_mesh.m_edge_to_triangle_map[i][j]; if ( m_mesh.oriented( m_mesh.m_edges[i][0], m_mesh.m_edges[i][1], m_mesh.get_triangle(triangle_a) ) != m_mesh.oriented( m_mesh.m_edges[i][0], m_mesh.m_edges[i][1], m_mesh.get_triangle(triangle_b) ) ) { break; } } assert ( j < 4 ); } else { std::cout << m_mesh.m_edge_to_triangle_map[i].size() << " triangles incident to an edge" << std::endl; assert(0); } // Don't flip edge on a degenerate triangle const Vec3st& tri_a = m_mesh.get_triangle( triangle_a ); const Vec3st& tri_b = m_mesh.get_triangle( triangle_b ); if ( tri_a[0] == tri_a[1] || tri_a[1] == tri_a[2] || tri_a[2] == tri_a[0] || tri_b[0] == tri_b[1] || tri_b[1] == tri_b[2] || tri_b[2] == tri_b[0] ) { continue; } size_t third_vertex_0 = m_mesh.get_third_vertex( m_mesh.m_edges[i][0], m_mesh.m_edges[i][1], tri_a ); size_t third_vertex_1 = m_mesh.get_third_vertex( m_mesh.m_edges[i][0], m_mesh.m_edges[i][1], tri_b ); if ( third_vertex_0 == third_vertex_1 ) { continue; } bool flipped = false; double current_length = mag( xs[m_mesh.m_edges[i][1]] - xs[m_mesh.m_edges[i][0]] ); double potential_length = mag( xs[third_vertex_1] - xs[third_vertex_0] ); if ( potential_length < current_length - m_edge_flip_min_length_change ) { flipped = flip_edge( i, triangle_a, triangle_b, third_vertex_0, third_vertex_1 ); } // else if ( regularity_improves( i, triangle_a, triangle_b, third_vertex_0, third_vertex_1 ) ) // { // // size_t r_before = total_mesh_regularity(); // // flipped = flip_edge( i, triangle_a, triangle_b, third_vertex_0, third_vertex_1 ); // // size_t r_after = total_mesh_regularity(); // // assert( !flipped || r_after < r_before ); // // } flip_occurred |= flipped; } flip_occurred_ever |= flip_occurred; } if ( flip_occurred_ever ) { m_surf.trim_non_manifold( m_surf.m_dirty_triangles ); } }
// Subdivide each facet of the lcc by using sqrt(3)-subdivision. void subdivide_lcc_3 (LCC & m) { if (m.number_of_darts () == 0) return; LCC::size_type mark = m.get_new_mark (); LCC::size_type treated = m.get_new_mark (); m.negate_mark (mark); // All the old darts are marked in O(1). // 1) We smoth the old vertices. std::vector <std::pair<Point_3, Dart_handle> > vertices; // smooth the old vertices vertices.reserve (m.number_of_attributes<0> ()); // get intermediate space std::transform (m.vertex_attributes().begin (), m.vertex_attributes().end (), std::back_inserter (vertices), Smooth_old_vertex (m, mark)); // 2) We subdivide each facet. m.negate_mark (treated); // All the darts are marked in O(1). unsigned int nb = 0; for (LCC::Dart_range::iterator it (m.darts().begin ()); m.number_of_marked_darts (treated) > 0; ++it) { ++nb; if (m.is_marked (it, treated)) { // We unmark the darts of the facet to process only once dart/facet. CGAL::unmark_cell < LCC, 2 > (m, it, treated); // We triangulate the facet. m.insert_barycenter_in_cell<2>(it); } } CGAL_assertion (m.is_whole_map_unmarked (treated)); CGAL_assertion (m.is_valid ()); m.free_mark (treated); // 3) We update the coordinates of old vertices. for (std::vector<std::pair<Point_3, Dart_handle> >::iterator vit=vertices.begin(); vit!=vertices.end(); ++vit) { m.point(vit->second)=vit->first; } // 4) We flip all the old edges. m.negate_mark (mark); // Now only new darts are marked. Dart_handle d2 =LCC::null_handle; for (LCC::Dart_range::iterator it (m.darts().begin ()); it != m.darts().end ();) { d2 = it++; if (!m.is_marked (d2, mark)) // This is an old dart. { // We process only the last dart of a same edge. if (!m.is_free(d2,2) && (m.beta(d2,2,3)==m.beta(d2,3,2))) { if (m.is_marked(m.beta(d2,2), mark) && (m.is_free(d2,3) || (m.is_marked(m.beta(d2,3), mark) && m.is_marked(m.beta(d2,2,3), mark)))) { flip_edge (m, d2); m.mark(d2, mark); } else m.mark (d2, mark); } else m.mark (d2, mark); } } CGAL_assertion (m.is_whole_map_marked (mark)); m.free_mark (mark); CGAL_postcondition ( m.is_valid ()); }