int do_diag (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { unsigned int i; if (argc == 1 || strcmp (argv[1], "run") != 0) { /* List test info */ if (argc == 1) { puts ("Available hardware tests:\n"); post_info (NULL); puts ("Use 'diag [<test1> [<test2> ...]]'" " to get more info.\n"); puts ("Use 'diag run [<test1> [<test2> ...]]'" " to run tests.\n"); } else { for (i = 1; i < argc; i++) { if (post_info (argv[i]) != 0) printf ("%s - no such test\n", argv[i]); } } } else { /* Run tests */ if (argc == 2) { post_run (NULL, POST_RAM | POST_MANUAL); } else { for (i = 2; i < argc; i++) { if (post_run (argv[i], POST_RAM | POST_MANUAL) != 0) printf ("%s - unable to execute the test\n", argv[i]); } } } return 0; }
bool EdgeFlipper::flip_edge( size_t edge, size_t tri0, size_t tri1, size_t third_vertex_0, size_t third_vertex_1 ) { NonDestructiveTriMesh& m_mesh = m_surf.m_mesh; const std::vector<Vec3d>& xs = m_surf.get_positions(); Vec2st& edge_vertices = m_mesh.m_edges[edge]; // Find the vertices which will form the new edge Vec2st new_edge( third_vertex_0, third_vertex_1); // -------------- // Control volume change double vol = fabs( signed_volume( xs[edge_vertices[0]], xs[edge_vertices[1]], xs[new_edge[0]], xs[new_edge[1]] ) ); if ( vol > m_surf.m_max_volume_change ) { if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: volume change = " << vol << std::endl; } return false; } // -------------- // Prevent non-manifold surfaces if we're not allowing them if ( false == m_surf.m_allow_non_manifold ) { for ( size_t i = 0; i < m_mesh.m_vertex_to_edge_map[ third_vertex_0 ].size(); ++i ) { if ( ( m_mesh.m_edges[ m_mesh.m_vertex_to_edge_map[third_vertex_0][i] ][0] == third_vertex_1 ) || ( m_mesh.m_edges[ m_mesh.m_vertex_to_edge_map[third_vertex_0][i] ][1] == third_vertex_1 ) ) { // edge already exists if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: edge exists" << std::endl; } return false; } } } // -------------- // Don't flip edge on a degenerate tet if ( third_vertex_0 == third_vertex_1 ) { if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: degenerate tet" << std::endl; } return false; } // -------------- // Create the new triangles // new edge winding order == winding order of old triangle0 == winding order of new triangle0 size_t new_triangle_third_vertex_0, new_triangle_third_vertex_1; if ( m_mesh.oriented( m_mesh.m_edges[edge][0], m_mesh.m_edges[edge][1], m_mesh.get_triangle(tri0) ) ) { assert( m_mesh.oriented( m_mesh.m_edges[edge][1], m_mesh.m_edges[edge][0], m_mesh.get_triangle(tri1) ) ); new_triangle_third_vertex_0 = m_mesh.m_edges[edge][1]; new_triangle_third_vertex_1 = m_mesh.m_edges[edge][0]; } else { assert( m_mesh.oriented( m_mesh.m_edges[edge][0], m_mesh.m_edges[edge][1], m_mesh.get_triangle(tri1) ) ); assert( m_mesh.oriented( m_mesh.m_edges[edge][1], m_mesh.m_edges[edge][0], m_mesh.get_triangle(tri0) ) ); new_triangle_third_vertex_0 = m_mesh.m_edges[edge][0]; new_triangle_third_vertex_1 = m_mesh.m_edges[edge][1]; } Vec3st new_triangle0( new_edge[0], new_edge[1], new_triangle_third_vertex_0 ); Vec3st new_triangle1( new_edge[1], new_edge[0], new_triangle_third_vertex_1 ); if ( m_surf.m_verbose ) { std::cout << "flip --- new triangle 0: " << new_triangle0 << std::endl; std::cout << "flip --- new triangle 1: " << new_triangle1 << std::endl; } // -------------- // if both triangle normals agree before flipping, make sure they agree after flipping if ( dot( m_surf.get_triangle_normal(tri0), m_surf.get_triangle_normal(tri1) ) > 0.0 ) { if ( dot( m_surf.get_triangle_normal(new_triangle0), m_surf.get_triangle_normal(new_triangle1) ) < 0.0 ) { if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: normal inversion" << std::endl; } return false; } if ( dot( m_surf.get_triangle_normal(new_triangle0), m_surf.get_triangle_normal(tri0) ) < 0.0 ) { if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: normal inversion" << std::endl; } return false; } if ( dot( m_surf.get_triangle_normal(new_triangle1), m_surf.get_triangle_normal(tri1) ) < 0.0 ) { if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: normal inversion" << std::endl; } return false; } if ( dot( m_surf.get_triangle_normal(new_triangle0), m_surf.get_triangle_normal(tri1) ) < 0.0 ) { if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: normal inversion" << std::endl; } return false; } if ( dot( m_surf.get_triangle_normal(new_triangle1), m_surf.get_triangle_normal(tri0) ) < 0.0 ) { if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: normal inversion" << std::endl; } return false; } } // -------------- // Prevent intersection if ( m_surf.m_collision_safety && flip_introduces_collision( edge, new_edge, new_triangle0, new_triangle1 ) ) { if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: intersection" << std::endl; } return false; } // -------------- // Prevent degenerate triangles if ( triangle_area( xs[new_triangle0[0]], xs[new_triangle0[1]], xs[new_triangle0[2]] ) < m_surf.m_min_triangle_area ) { if ( m_surf.m_verbose ) { std::cout << "edge flip rejected: area too small" << std::endl; } return false; } if ( triangle_area( xs[new_triangle1[0]], xs[new_triangle1[1]], xs[new_triangle1[2]] ) < m_surf.m_min_triangle_area ) { if ( m_surf.m_verbose ) {std::cout << "edge flip rejected: area too small" << std::endl; } return false; } // -------------- // Control change in area double old_area = m_surf.get_triangle_area( tri0 ) + m_surf.get_triangle_area( tri1 ); double new_area = triangle_area( xs[new_triangle0[0]], xs[new_triangle0[1]], xs[new_triangle0[2]] ) + triangle_area( xs[new_triangle1[0]], xs[new_triangle1[1]], xs[new_triangle1[2]] ); if ( fabs( old_area - new_area ) > 0.1 * old_area ) { if ( m_surf.m_verbose ) {std::cout << "edge flip rejected: area change too great" << std::endl; } return false; } // -------------- // Don't flip unless both vertices are on a smooth patch if ( ( m_surf.classify_vertex( edge_vertices[0] ) > 1 ) || ( m_surf.classify_vertex( edge_vertices[1] ) > 1 ) ) { if ( m_surf.m_verbose ) {std::cout << "edge flip rejected: vertices not on smooth patch" << std::endl; } return false; } // -------------- // Don't introduce a large or small angle double min_angle = min_triangle_angle( xs[new_triangle0[0]], xs[new_triangle0[1]], xs[new_triangle0[2]] ); min_angle = min( min_angle, min_triangle_angle( xs[new_triangle1[0]], xs[new_triangle1[1]], xs[new_triangle1[2]] ) ); if ( rad2deg(min_angle) < m_surf.m_min_triangle_angle ) { return false; } double max_angle = max_triangle_angle( xs[new_triangle0[0]], xs[new_triangle0[1]], xs[new_triangle0[2]] ); max_angle = max( max_angle, max_triangle_angle( xs[new_triangle1[0]], xs[new_triangle1[1]], xs[new_triangle1[2]] ) ); if ( rad2deg(max_angle) > m_surf.m_max_triangle_angle ) { return false; } // -------------- PreEdgeFlipInfo pre_info( edge, tri0, tri1 ); for ( size_t i = 0; i < m_observers.size(); ++i ) { if ( false == m_observers[i]->operationOK(m_surf, pre_info) ) { return false; } } // -------------- // Okay, now do the actual operation Vec3st old_tri0 = m_mesh.get_triangle(tri0); Vec3st old_tri1 = m_mesh.get_triangle(tri1); m_surf.remove_triangle( tri0 ); m_surf.remove_triangle( tri1 ); size_t new_triangle_index_0 = m_surf.add_triangle( new_triangle0 ); size_t new_triangle_index_1 = m_surf.add_triangle( new_triangle1 ); if ( m_surf.m_collision_safety ) { if ( m_surf.m_collision_pipeline.check_triangle_vs_all_triangles_for_intersection( new_triangle_index_0 ) ) { std::cout << "missed an intersection. New triangles: " << new_triangle0 << ", " << new_triangle1 << std::endl; std::cout << "old triangles: " << old_tri0 << ", " << old_tri1 << std::endl; assert(0); } if ( m_surf.m_collision_pipeline.check_triangle_vs_all_triangles_for_intersection( new_triangle_index_1 ) ) { std::cout << "missed an intersection. New triangles: " << new_triangle0 << ", " << new_triangle1 << std::endl; std::cout << "old triangles: " << old_tri0 << ", " << old_tri1 << std::endl; assert(0); } } m_surf.m_dirty_triangles.push_back( new_triangle_index_0 ); m_surf.m_dirty_triangles.push_back( new_triangle_index_1 ); if ( m_surf.m_verbose ) { std::cout << "edge flip: ok" << std::endl; } PostEdgeFlipInfo post_info( pre_info, new_triangle_index_0, new_triangle_index_1 ); for ( size_t i = 0; i < m_observers.size(); ++i ) { m_observers[i]->operationOccurred(m_surf, post_info); } return true; }