a48
2.0.2
|
This is an example of how to use the functions in the mesh algorithms header.
#include <cmath> #include <limits> #include <sstream> #include <mesh.hh> template< class Traits > class GeometryVertex : public a48::AdaptiveVertexT< Traits > { public: unsigned int id; float pos[3]; }; class GeometryTraits { public: typedef GeometryVertex< GeometryTraits > vertex_type; typedef a48::AdaptiveHalfedgeT< GeometryTraits > halfedge_type; typedef a48::AdaptiveFaceT< GeometryTraits > face_type; }; typedef a48::AdaptiveMeshT< GeometryTraits > GeometryMesh; typedef GeometryMesh::vertex_type vertex_type; typedef GeometryMesh::halfedge_type halfedge_type; typedef GeometryMesh::face_type face_type; typedef GeometryMesh::face_iterator face_iterator; static GeometryMesh m; void set_vertex_geometry(vertex_type *v, const std::string& str) { std::stringstream ss(std::stringstream::in | std::stringstream::out); ss << str; ss >> v->pos[0] >> v->pos[1] >> v->pos[2]; } void set_vertex_index(vertex_type *v, const unsigned& id) { v->id = id; } float rank(halfedge_type *h) { if( h->is_boundary() ) return std::numeric_limits<float>::max(); vertex_type *v0 = h->next()->vertex(), *v1 = h->vertex(), *v2 = h->from_vertex(), *v3 = h->opposite()->next()->vertex(), *v4 = h->opposite()->vertex(), *v5 = h->opposite()->from_vertex(); float v_01[3], v_02[3], v_34[3], v_35[3], l_01 = 0.f, l_02 = 0.f, l_34 = 0.f, l_35 = 0.f, dot_012 = 0.f, dot_345 = 0.f; for (unsigned int k = 0; k < 3; ++k) { v_01[k] = v1->pos[k] - v0->pos[k]; v_02[k] = v2->pos[k] - v0->pos[k]; v_34[k] = v4->pos[k] - v3->pos[k]; v_35[k] = v5->pos[k] - v3->pos[k]; l_01 += (v_01[k] * v_01[k]); l_02 += (v_02[k] * v_02[k]); l_34 += (v_34[k] * v_34[k]); l_35 += (v_35[k] * v_35[k]); } if( l_01*l_02*l_34*l_35 == 0.f ) return std::numeric_limits<float>::max(); l_01 = sqrt( l_01 ); l_02 = sqrt( l_02 ); l_34 = sqrt( l_34 ); l_35 = sqrt( l_35 ); for (unsigned int k = 0; k < 3; ++k) { dot_012 += (v_01[k] / l_01) * (v_02[k] / l_02); dot_345 += (v_34[k] / l_34) * (v_35[k] / l_35); } return fabs(dot_012) + fabs(dot_345); } int main(int argc, char* argv[]) { if( argc != 2 ) { std::cerr << "Usage: " << argv[0] << " file.off\n"; return 1; } std::cout << "[GeometryMesh] Reading OFF: " << argv[1] << " ... " << std::flush; if( !a48::read_off_mesh( m, argv[1], set_vertex_geometry, set_vertex_index ) ) return 1; std::cout << "done!\n"; std::cout << "[GeometryMesh] Vertices: " << m.size_of_vertices() << std::endl; std::cout << "[GeometryMesh] Halfedges: " << m.size_of_halfedges() << std::endl; std::cout << "[GeometryMesh] Faces: " << m.size_of_faces() << std::endl; std::cout << "[GeometryMesh] The input mesh is" << (m.is_valid()?" ":" not ") << "valid.\n"; std::cout << "[GeometryMesh] The input mesh is" << (m.is_closed()?" ":" not ") << "closed.\n"; std::cout << "[GeometryMesh] The input mesh is" << (m.is_consistent()?" ":" not ") << "consistent.\n"; std::cout << "[GeometryMesh] The input mesh is" << (m.is_manifold()?" ":" not ") << "a manifold.\n"; std::cout << "[GeometryMesh] The input mesh is" << (m.is_tri()?" ":" not ") << "a triangulated mesh.\n"; std::cout << "[GeometryMesh] The input mesh is" << (m.is_triquad()?" ":" not ") << "a tri-quad mesh.\n"; srand( time(0) ); unsigned int r; // random value to determine face flip std::cout << "[GeometryMesh] Flipping indices of the mesh ... " << std::flush; for (face_iterator fit = m.faces_begin(); fit != m.faces_end(); ++fit) { r = rand() % 4; if( r == 0 ) continue; flip_orientation( (*fit)->halfedge() ); } std::cout << "done!\n"; std::cout << "[GeometryMesh] The input mesh is" << (a48::make_consistent(m)?" ":" non-") << "orientable.\n"; std::cout << "[GeometryMesh] Making triquad mesh: " << (make_triquad( m, rank, 1 ) ? "success" : "failure") << "!\n"; std::cout << "[GeometryMesh] Now mesh is" << (m.is_triquad()?" ":" not ") << "a tri-quad mesh.\n"; std::cout << "[GeometryMesh] Now mesh is" << (m.is_consistent()?" ":" not ") << "consistent.\n"; std::cout << "[GeometryMesh] Now mesh is" << (m.is_valid()?" ":" not ") << "valid.\n"; return 0; }