|
| 1 | +#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> |
| 2 | + |
| 3 | +#include <CGAL/Surface_mesh.h> |
| 4 | + |
| 5 | +#include <CGAL/AABB_face_graph_triangle_primitive.h> |
| 6 | +#include <CGAL/AABB_tree.h> |
| 7 | +#include <CGAL/AABB_traits.h> |
| 8 | +#include <CGAL/boost/graph/helpers.h> |
| 9 | +#include <CGAL/Dynamic_property_map.h> |
| 10 | +#include <CGAL/Polygon_mesh_processing/locate.h> |
| 11 | +#include <CGAL/Polygon_mesh_processing/triangulate_faces.h> |
| 12 | + |
| 13 | +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; |
| 14 | +typedef K::FT FT; |
| 15 | +typedef K::Point_2 Point_2; |
| 16 | +typedef K::Ray_2 Ray_2; |
| 17 | +typedef K::Point_3 Point_3; |
| 18 | +typedef K::Ray_3 Ray_3; |
| 19 | + |
| 20 | +typedef CGAL::Surface_mesh<Point_3> Mesh; |
| 21 | +typedef typename boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor; |
| 22 | +typedef typename boost::graph_traits<Mesh>::face_descriptor face_descriptor; |
| 23 | + |
| 24 | +namespace CP = CGAL::parameters; |
| 25 | +namespace PMP = CGAL::Polygon_mesh_processing; |
| 26 | + |
| 27 | +typedef PMP::Barycentric_coordinates<FT> Barycentric_coordinates; |
| 28 | +typedef PMP::Face_location<Mesh, FT> Face_location; |
| 29 | + |
| 30 | +int main(int /*argc*/, char** /*argv*/) |
| 31 | +{ |
| 32 | + // Generate a simple 3D triangle mesh that with vertices on the plane xOy |
| 33 | + Mesh tm; |
| 34 | + CGAL::make_grid(10, 10, tm); |
| 35 | + PMP::triangulate_faces(tm); |
| 36 | + |
| 37 | + // Basic usage |
| 38 | + Face_location random_location = PMP::random_location_on_mesh<FT>(tm); |
| 39 | + const face_descriptor f = random_location.first; |
| 40 | + const Barycentric_coordinates& coordinates = random_location.second; |
| 41 | + |
| 42 | + std::cout << "Random location on the mesh: face " << f |
| 43 | + << " and with coordinates [" << coordinates[0] << "; " |
| 44 | + << coordinates[1] << "; " |
| 45 | + << coordinates[2] << "]\n"; |
| 46 | + std::cout << "It corresponds to point (" << PMP::construct_point(random_location, tm) << ")\n\n"; |
| 47 | + |
| 48 | + // Locate a known 3D point in the mesh |
| 49 | + const Point_3 query(1.2, 7.4, 0); |
| 50 | + Face_location query_location = PMP::locate(query, tm); |
| 51 | + |
| 52 | + std::cout << "Point (" << query << ") is located in face " << query_location.first |
| 53 | + << " with barycentric coordinates [" << query_location.second[0] << "; " |
| 54 | + << query_location.second[1] << "; " |
| 55 | + << query_location.second[2] << "]\n\n"; |
| 56 | + |
| 57 | + // Locate a 3D point in the mesh as the intersection of the mesh and a 3D ray. |
| 58 | + // The AABB tree can be cached in case many queries are performed (otherwise, it is rebuilt |
| 59 | + // on each call, which is expensive). |
| 60 | + typedef CGAL::AABB_face_graph_triangle_primitive<Mesh> AABB_face_graph_primitive; |
| 61 | + typedef CGAL::AABB_traits<K, AABB_face_graph_primitive> AABB_face_graph_traits; |
| 62 | + |
| 63 | + CGAL::AABB_tree<AABB_face_graph_traits> tree; |
| 64 | + PMP::build_AABB_tree(tm, tree); |
| 65 | + |
| 66 | + const Ray_3 ray_3(Point_3(4.2, 6.8, 2.4), Point_3(7.2, 2.3, -5.8)); |
| 67 | + Face_location ray_location = PMP::locate_with_AABB_tree(ray_3, tree, tm); |
| 68 | + |
| 69 | + std::cout << "Intersection of the 3D ray and the mesh is in face " << ray_location.first |
| 70 | + << " with barycentric coordinates [" << ray_location.second[0] << " " |
| 71 | + << ray_location.second[1] << " " |
| 72 | + << ray_location.second[2] << "]\n"; |
| 73 | + std::cout << "It corresponds to point (" << PMP::construct_point(ray_location, tm) << ")\n"; |
| 74 | + std::cout << "Is it on the face's border? " << (PMP::is_on_face_border(ray_location, tm) ? "Yes" : "No") << "\n\n"; |
| 75 | + |
| 76 | + // ----------------------------------------------------------------------------------------------- |
| 77 | + // Now, we artifically project the mesh to the natural 2D dimensional plane, with a little translation |
| 78 | + // via a custom vertex point property map |
| 79 | + |
| 80 | + typedef CGAL::dynamic_vertex_property_t<Point_2> Point_2_property; |
| 81 | + typedef typename boost::property_map<Mesh, Point_2_property>::type Projection_pmap; |
| 82 | + Projection_pmap projection_pmap = get(Point_2_property(), tm); |
| 83 | + |
| 84 | + for(vertex_descriptor v : vertices(tm)) |
| 85 | + { |
| 86 | + const Point_3& p = tm.point(v); |
| 87 | + put(projection_pmap, v, Point_2(p.x() + 1, p.y())); // simply ignoring the z==0 coordinate and translating along Ox |
| 88 | + } |
| 89 | + |
| 90 | + // Locate the same 3D point but in a 2D context |
| 91 | + const Point_2 query_2(query.x() + 1, query.y()); |
| 92 | + Face_location query_location_2 = PMP::locate(query_2, tm, CP::vertex_point_map(projection_pmap)); |
| 93 | + |
| 94 | + std::cout << "Point (" << query_2 << ") is located in face " << query_location_2.first |
| 95 | + << " with barycentric coordinates [" << query_location_2.second[0] << "; " |
| 96 | + << query_location_2.second[1] << "; " |
| 97 | + << query_location_2.second[2] << "]\n\n"; |
| 98 | + |
| 99 | + // Shoot a 2D ray and locate the intersection with the mesh in 2D |
| 100 | + const Ray_2 ray_2(Point_2(-10, -10), Point_2(10, 10)); |
| 101 | + Face_location ray_location_2 = PMP::locate(ray_2, tm, CP::vertex_point_map(projection_pmap)); // This rebuilds an AABB tree on each call |
| 102 | + |
| 103 | + std::cout << "Intersection of the 2D ray and the mesh is in face " << ray_location_2.first |
| 104 | + << " with barycentric coordinates [" << ray_location_2.second[0] << "; " |
| 105 | + << ray_location_2.second[1] << "; " |
| 106 | + << ray_location_2.second[2] << "]\n"; |
| 107 | + std::cout << "It corresponds to point (" << PMP::construct_point(ray_location_2, tm, CP::vertex_point_map(projection_pmap)) << ")\n"; |
| 108 | + |
| 109 | + if(PMP::is_on_mesh_border(ray_location_2, tm)) |
| 110 | + std::cout << "It is on the border of the mesh!\n" << std::endl; |
| 111 | + |
| 112 | + return EXIT_SUCCESS; |
| 113 | +} |
0 commit comments