From 79026c255e7c2a0889228799201d1f6bfd484574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 8 Oct 2019 15:35:29 +0200 Subject: [PATCH 1/7] Fix documentation of CGAL::make_grid (bad line break, bad links) --- BGL/include/CGAL/boost/graph/generators.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/generators.h b/BGL/include/CGAL/boost/graph/generators.h index 5189bd7297d8..abcd8982f6dc 100644 --- a/BGL/include/CGAL/boost/graph/generators.h +++ b/BGL/include/CGAL/boost/graph/generators.h @@ -742,11 +742,12 @@ make_icosahedron(Graph& g, * If `triangulated` is `true`, the diagonal of each cell is oriented from (0,0) to (1,1) * in the cell coordinates. * - *\tparam CoordinateFunctor a function object providing `Point_3 operator()(size_type I, size_type J)` with `Point_3` being - * the value_type of the internal property_map for `CGAL::vertex_point_t`. - * and outputs a `boost::property_traits::%type>::%value_type`. - * It will be called with arguments (`w`, `h`), with `w` in [0..`i`] and `h` in [0..`j`]. - *

%Default: a point with positive integer coordinates (`w`, `h`, 0), with `w` in [0..`i`] and `h` in [0..`j`] + *\tparam CoordinateFunctor a function object providing: + * `%Point_3 operator()(size_type I, size_type J)`, with `%Point_3` being the value_type + * of the internal property_map for `CGAL::vertex_point_t` and outputs an object of type + * `boost::property_traits::%type>::%value_type`. + * It will be called with arguments (`w`, `h`), with `w` in [0..`i`] and `h` in [0..`j`].
+ * %Default: a point with positive integer coordinates (`w`, `h`, 0), with `w` in [0..`i`] and `h` in [0..`j`] * * \returns the non-border non-diagonal halfedge that has the target vertex associated with the first point of the grid (default is (0,0,0) ). */ From 0b67e30c018a66696902cabd21920c7bcdff8e80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 8 Oct 2019 15:37:08 +0200 Subject: [PATCH 2/7] Improve user-friendliness of PMP::Locate by removing the class Location_traits The problem was that Location_traits is templated by Named Parameters, and it is extremely unpractical to have to explicitly write the type (it's nested classes all the way down). Instead, we use template aliases for most types, and template by the field type (FT) when necessary, which is much easier to write for the user. Since template aliases cannot automatically deduce template parameters, non-Doxygen versions of functions must be written without them from time to time. Other fixes: - Simplify implementation of function 'random_location_halfedge' - Don't initialize FTs from doubles - Minor doc improvements - reference to points when using VPMs --- .../CGAL/Polygon_mesh_processing/locate.h | 800 ++++++++++-------- 1 file changed, 442 insertions(+), 358 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h index 14e5e9192ace..f82daed743b1 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h @@ -60,9 +60,7 @@ // - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` namespace CGAL { - namespace Polygon_mesh_processing { - namespace internal { // The Ray must have the same ambient dimension as the property map's value type (aka, the point type) @@ -75,91 +73,87 @@ struct Ray_type_selector typedef typename Kernel::Ray_2 type; }; -template +template struct Ray_type_selector { typedef typename CGAL::Kernel_traits::type Kernel; typedef typename Kernel::Ray_3 type; }; -} // end namespace internal - -/// \ingroup PMP_locate_grp -/// -/// \brief Helper class whose sole purpose is to make it easier to access some useful types. -/// -/// \tparam TriangleMesh a model of `FaceListGraph` -/// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" -/// +// Just for convenience template > -class Location_traits +struct Location_traits { -public: - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef boost::variant descriptor_variant; + typedef typename GetVertexPointMap::const_type VertexPointMap; + typedef typename boost::property_traits::value_type Point; + typedef typename internal::Ray_type_selector::type Ray; -#ifdef DOXYGEN_RUNNING - /// This is the type of the vertex point property map, either the one passed through the named parameters - /// or the default, internal one of the mesh. - typedef unspecified_type VPM; + typedef typename GetGeomTraits::type Geom_traits; + typedef typename Geom_traits::FT FT; - /// The traits class, either passed as a named parameter or deduced from the Point type - /// of the vertex property map (the point type must then be compatible with `CGAL::Kernel_traits`) - typedef unspecified_type Geom_traits; -#else - typedef typename GetVertexPointMap::const_type VPM; - typedef typename GetGeomTraits::type Geom_traits; -#endif + typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename boost::property_traits::value_type Point; - typedef typename Geom_traits::FT FT; + typedef std::array Barycentric_coordinates; + typedef std::pair Face_location; +}; -#ifdef DOXYGEN_RUNNING - /// Either Geom_traits::Ray_2 or Geom_traits::Ray_3, depending on the ambient dimension of the mesh - typedef unspecified_type Ray; -#else - typedef typename internal::Ray_type_selector::type Ray; -#endif +} // end namespace internal - typedef std::array Barycentric_coordinates; +/// \ingroup PMP_locate_grp +/// +/// A variant used in the function `get_descriptor_from_location()`. +template +using descriptor_variant = boost::variant::vertex_descriptor, + typename boost::graph_traits::halfedge_descriptor, + typename boost::graph_traits::face_descriptor>; - /// If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) - /// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance - /// between the coordinates in `bc` and the vertices of the face `f` is the following: - /// - `w0` corresponds to `source(halfedge(f, tm), tm)` - /// - `w1` corresponds to `target(halfedge(f, tm), tm)` - /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` - typedef std::pair Face_location; -}; +/// \ingroup PMP_locate_grp +/// +/// A triplet of coordinates describing the barycentric coordinates of a point +/// with respect to the vertices of a triangular face. +/// +/// \sa `Face_location` +template +using Barycentric_coordinates = std::array; + +/// \ingroup PMP_locate_grp +/// +/// If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) +/// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance +/// between the coordinates in `bc` and the vertices of the face `f` is the following: +/// - `w0` corresponds to `source(halfedge(f, tm), tm)` +/// - `w1` corresponds to `target(halfedge(f, tm), tm)` +/// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` +template +using Face_location = std::pair::face_descriptor, + Barycentric_coordinates >; // forward declarations -template -bool is_in_face(const typename Location_traits::Face_location& loc, +template +bool is_in_face(const std::pair::face_descriptor, + std::array >& loc, const TriangleMesh& tm); -template -typename Location_traits::descriptor_variant -get_descriptor_from_location(const typename Location_traits::Face_location& loc, +template +descriptor_variant +get_descriptor_from_location(const std::pair::face_descriptor, + std::array >& loc, const TriangleMesh& tm); -template -typename Location_traits::Face_location -locate_in_face(typename boost::graph_traits::halfedge_descriptor he, - typename Location_traits::FT t, +template +Face_location +locate_in_face(typename boost::graph_traits::halfedge_descriptor hd, + const FT t, const TriangleMesh& tm); // end of forward declarations namespace internal { -template +template OutputIterator -incident_faces(const typename Location_traits::Face_location& location, +incident_faces(const std::pair::face_descriptor, + std::array >& location, const TriangleMesh& tm, OutputIterator out) { @@ -167,11 +161,7 @@ incident_faces(const typename Location_traits::Face_location& loca typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef boost::variant descriptor_variant; - - descriptor_variant dv = get_descriptor_from_location(location, tm); + const descriptor_variant dv = get_descriptor_from_location(location, tm); if(const vertex_descriptor* vd_ptr = boost::get(&dv)) { @@ -195,14 +185,11 @@ incident_faces(const typename Location_traits::Face_location& loca } // Snapping coordinates for robustness -template +template bool -snap_coordinates_to_border(typename Location_traits::Barycentric_coordinates& coords, - const typename Location_traits::FT tolerance = - std::numeric_limits::FT>::epsilon()) +snap_coordinates_to_border(std::array& coords, + const FT tolerance = std::numeric_limits::epsilon()) { - typedef typename Location_traits::FT FT; - #ifdef CGAL_PMP_LOCATE_DEBUG std::cout << "Pre-snapping: " << coords[0] << " " << coords[1] << " " << coords[2] << std::endl; std::cout << "Sum: " << coords[0] + coords[1] + coords[2] << std::endl; @@ -210,7 +197,7 @@ snap_coordinates_to_border(typename Location_traits::Barycentric_c #endif // To still keep a sum roughly equals to 1, keep in memory the small changes - FT residue = 0.; + FT residue(0); bool snapped = false; for(int i=0; i<3; ++i) @@ -219,20 +206,20 @@ snap_coordinates_to_border(typename Location_traits::Barycentric_c { snapped = true; residue += coords[i]; - coords[i] = 0.; + coords[i] = FT(0); } - else if(CGAL::abs(1 - coords[i]) <= tolerance) + else if(CGAL::abs(FT(1) - coords[i]) <= tolerance) { snapped = true; - residue -= 1. - coords[i]; - coords[i] = 1.; + residue -= FT(1) - coords[i]; + coords[i] = FT(1); } } // Dump the residue into one of the barycentric values that is neither 0 nor 1 for(int i=0; i<3; ++i) { - if(coords[i] != 0. && coords[i] != 1.) + if(coords[i] != FT(0) && coords[i] != FT(1)) { coords[i] += residue; break; @@ -249,13 +236,14 @@ snap_coordinates_to_border(typename Location_traits::Barycentric_c return snapped; } -template +template bool -snap_location_to_border(typename Location_traits::Face_location& loc, - const typename Location_traits::FT tolerance = - std::numeric_limits::FT>::epsilon()) +snap_location_to_border(std::pair::face_descriptor, + std::array >& loc, + const TriangleMesh /*tm*/, + const FT tolerance = std::numeric_limits::epsilon()) { - return snap_coordinates_to_border(loc.second, tolerance); + return snap_coordinates_to_border(loc.second, tolerance); } template @@ -287,7 +275,7 @@ struct Barycentric_coordinate_calculator // 2D version FT d21 = csp2(v2, v1); FT denom = d00 * d11 - d01 * d01; - CGAL_assertion((d00 * d11 - d01 * d01) != FT(0)); // denom != 0. + CGAL_assertion((d00 * d11 - d01 * d01) != FT(0)); // denom != 0 FT v = (d11 * d20 - d01 * d21) / denom; FT w = (d00 * d21 - d01 * d20) / denom; @@ -324,8 +312,8 @@ struct Barycentric_coordinate_calculator FT d20 = csp3(v2, v0); FT d21 = csp3(v2, v1); - CGAL_assertion((d00 * d11 - d01 * d01) != FT(0)); // denom != 0. - FT denom_inv = 1. / (d00 * d11 - d01 * d01); + CGAL_assertion((d00 * d11 - d01 * d01) != FT(0)); // denom != 0 + FT denom_inv = FT(1) / (d00 * d11 - d01 * d01); FT v = (d11 * d20 - d01 * d21) * denom_inv; FT w = (d00 * d21 - d01 * d20) * denom_inv; @@ -343,7 +331,7 @@ struct Barycentric_point_constructor // 2D version const K& /*k*/) const { FT sum = wp + wq + wr; - CGAL_assertion(sum != 0); + CGAL_assertion(sum != FT(0)); // In theory, this should be compute_x_2(compute_point_2(...)) and construct_P() at the end... FT x = (wp * p.x() + wq * q.x() + wr * r.x()) / sum; @@ -362,7 +350,7 @@ struct Barycentric_point_constructor // 3D version const K& /*k*/) const { FT sum = wp + wq + wr; - CGAL_assertion(sum != 0); + CGAL_assertion(sum != FT(0)); FT x = (wp * p.x() + wq * q.x() + wr * r.x()) / sum; FT y = (wp * p.y() + wq * q.y() + wr * r.y()) / sum; FT z = (wp * p.z() + wq * q.z() + wr * r.z()) / sum; @@ -378,25 +366,24 @@ struct Barycentric_point_constructor // 3D version /// \brief Given a set of three points and a query point, computes the barycentric /// coordinates of the query point with respect to the first three points. /// +/// \tparam GeomTraits the type of a geometric traits. Must be a model of `Kernel` and be compatible +/// with the template parameter `Point`. /// \tparam Point the type of a geometric 2D or 3D point -/// \tparam K the type of a geometric traits. Must be a model of `Kernel`. /// /// \param p,q,r three points with respect to whom the barycentric coordinates of `query` will be computed /// \param query the query point whose barycentric coordinates will be computed -/// \param k an instance of the geometric traits +/// \param gt an instance of the geometric traits /// /// \pre `p`, `q`, and `r` are not collinear. -/// \pre It must be possible to extract a kernel type model of `Kernel`, using `CGAL::Kernel_traits

` -/// (this is the case for all standard %CGAL point types and classes inheriting such point types). /// \pre `query` lies on the plane defined by `p`, `q`, and `r`. /// -template -std::array +template +std::array barycentric_coordinates(const Point& p, const Point& q, const Point& r, const Point& query, - const K& k) + const GeomTraits& gt) { - internal::Barycentric_coordinate_calculator calculator; - return calculator(p, q, r, query, k); + internal::Barycentric_coordinate_calculator calculator; + return calculator(p, q, r, query, gt); } template @@ -420,24 +407,30 @@ barycentric_coordinates(const Point& p, const Point& q, const Point& r, const Po /// a value `t` between `0` and `1` and setting the barycentric coordinates to `t`, `1-t`, /// and `0` for respetively the source and target of `hd`, and the third vertex. /// +/// \tparam FT must be a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param hd a halfedge of `tm` /// \param tm a triangulated surface mesh /// \param rnd optional random number generator /// -template -typename Location_traits::Face_location +template +Face_location random_location_on_halfedge(typename boost::graph_traits::halfedge_descriptor hd, const TriangleMesh& tm, CGAL::Random& rnd = get_default_random()) { - typedef typename Location_traits::FT FT; - CGAL_precondition(CGAL::is_triangle_mesh(tm)); - FT t(rnd.uniform_real(0., 1.)); - return locate_in_face(hd, t, tm); + const int h_id = halfedge_index_in_face(hd, tm); + const FT t(rnd.uniform_real(0., 1.)); + + std::array coordinates; + coordinates[h_id] = t; + coordinates[(h_id+1)%3] = FT(1-t); + coordinates[(h_id+2)%3] = FT(0); + + return std::make_pair(face(hd, tm), coordinates); } /// \ingroup PMP_locate_grp @@ -449,20 +442,19 @@ random_location_on_halfedge(typename boost::graph_traits::halfedge /// a value `v` between `1-u`, and setting the barycentric coordinates to `u`, `v`, and /// `1-u-v` for respectively the source and target of `halfedge(fd, tm)`, and the third point. /// +/// \tparam FT must be a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param fd a face of `tm` /// \param tm a triangulated surface mesh /// \param rnd optional random number generator /// -template -typename Location_traits::Face_location +template +Face_location random_location_on_face(typename boost::graph_traits::face_descriptor fd, const TriangleMesh& tm, CGAL::Random& rnd = get_default_random()) { - typedef typename Location_traits::FT FT; - CGAL_USE(tm); CGAL_precondition(CGAL::is_triangle_mesh(tm)); CGAL_precondition(fd != boost::graph_traits::null_face()); @@ -482,6 +474,7 @@ random_location_on_face(typename boost::graph_traits::face_descrip /// a random point on that face. The barycentric coordinates of the point in the face /// are thus all positive. Note that all faces have the same probability to be chosen. /// +/// \tparam FT must be a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param tm a triangulated surface mesh @@ -489,26 +482,25 @@ random_location_on_face(typename boost::graph_traits::face_descrip /// /// \sa `random_location_on_face()` /// -template -typename Location_traits::Face_location -random_location_on_mesh(const TriangleMesh& tm, CGAL::Random& rnd = get_default_random()) +template +Face_location +random_location_on_mesh(const TriangleMesh& tm, + CGAL::Random& rnd = get_default_random()) { typedef typename boost::graph_traits::face_descriptor face_descriptor; CGAL_precondition(CGAL::is_triangle_mesh(tm)); face_descriptor fd = CGAL::internal::random_face_in_mesh(tm, rnd); - return random_location_on_face(fd, tm, rnd); + return random_location_on_face(fd, tm, rnd); } /// @} /// \ingroup PMP_locate_grp /// -/// \brief Given a location, that is an ordered pair composed of a -/// `boost::graph_traits::%face_descriptor` and an array -/// of barycentric coordinates, returns a descriptor to the simplex -/// of smallest dimension on which the point corresponding to the location lies. +/// \brief Given a location, returns a descriptor to the simplex of smallest dimension +/// on which the point corresponding to the location lies. /// /// \details In other words: /// - if the point lies on a vertex, this function returns a `boost::graph_traits::%vertex_descriptor` `v`; @@ -517,24 +509,30 @@ random_location_on_mesh(const TriangleMesh& tm, CGAL::Random& rnd = get_default_ /// - otherwise, this function returns a `boost::graph_traits::%face_descriptor` /// `fd` (equal to `loc.first`). /// +/// \tparam FT must be a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` /// \param tm a triangulated surface mesh /// -/// \pre the location corresponds to a point that is within a face of `tm`. -/// \pre `loc` describes the barycentric coordinates of a point that lives on the face (boundary included), +/// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. +/// \pre `loc` describes the barycentric coordinates of a point that lives within the face (boundary included), /// meaning the barycentric coordinates are all positive. /// -template -typename Location_traits::descriptor_variant -get_descriptor_from_location(const typename Location_traits::Face_location& loc, +template +descriptor_variant +#ifdef DOXYGEN_RUNNING // just for convenience because template alias do not allow template deduction +get_descriptor_from_location(const Face_location& loc, +#else +get_descriptor_from_location(const std::pair::face_descriptor, + std::array >& loc, +#endif const TriangleMesh& tm) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename Location_traits::Barycentric_coordinates Barycentric_coordinates; + typedef Barycentric_coordinates Barycentric_coordinates; const face_descriptor fd = loc.first; const Barycentric_coordinates& bar = loc.second; @@ -549,7 +547,7 @@ get_descriptor_from_location(const typename Location_traits::Face_ // check if the point is a vertex for(int i=0; i<3; ++i) { - if(bar[i] == 1) // coordinate at target(hd, tm) + if(bar[i] == FT(1)) // coordinate at target(hd, tm) return target(hd, tm); hd = next(hd, tm); } @@ -558,7 +556,7 @@ get_descriptor_from_location(const typename Location_traits::Face_ // check if the point is on an edge for(int i=0; i<3; ++i) { - if(bar[i] == 0) // coordinate at target(hd, tm) + if(bar[i] == FT(0)) // coordinate at target(hd, tm) return prev(hd, tm); hd = next(hd, tm); } @@ -568,15 +566,14 @@ get_descriptor_from_location(const typename Location_traits::Face_ /// \ingroup PMP_locate_grp /// -/// \brief Given a location, that is an ordered pair composed of a -/// `boost::graph_traits::%face_descriptor` and an array -/// of barycentric coordinates, returns the geometric position described +/// \brief Given a location in a face, returns the geometric position described /// by these coordinates, as a point. /// +/// \tparam FT must be a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// -/// \param loc the location to transform into a point +/// \param loc the location from which a point is constructed /// \param tm a triangulated surface mesh /// \param np an optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below: /// @@ -587,44 +584,61 @@ get_descriptor_from_location(const typename Location_traits::Face_ /// `boost::vertex_point_t` must be available in `TriangleMesh`. /// \cgalParamEnd /// \cgalParamBegin{geom_traits} -/// a geometric traits class instance, model of `Kernel`. +/// a geometric traits class instance, model of `Kernel`. If such traits class is provided, +/// its type `FT` must be identical to the template parameter `FT` of this function. /// \cgalParamEnd /// \cgalNamedParamsEnd /// /// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. /// -template -typename Location_traits::Point -construct_point(const typename Location_traits::Face_location& loc, +/// \returns a point whose type is the same as the value type of the vertex point property map +/// provided by the user or via named parameters, or the internal point map of the mesh `tm`. +/// +template +#ifdef DOXYGEN_RUNNING +Point +construct_point(const Face_location& loc, +#else +typename internal::Location_traits::Point +construct_point(const std::pair::face_descriptor, + std::array >& loc, +#endif const TriangleMesh& tm, const NamedParameters& np) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename GetGeomTraits::type Geom_traits; + typedef typename GetVertexPointMap::const_type VertexPointMap; typedef typename boost::property_traits::value_type Point; - typedef typename GetGeomTraits::type Geom_traits; + typedef typename boost::property_traits::reference Point_reference; + using parameters::get_parameter; using parameters::choose_parameter; CGAL_precondition(CGAL::is_triangle_mesh(tm)); - VertexPointMap vpm = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point), get_const_property_map(boost::vertex_point, tm)); Geom_traits gt = choose_parameter(get_parameter(np, internal_np::geom_traits), Geom_traits()); halfedge_descriptor hd = halfedge(loc.first, tm); - const Point& p0 = get(vpm, source(hd, tm)); - const Point& p1 = get(vpm, target(hd, tm)); - const Point& p2 = get(vpm, target(next(hd, tm), tm)); + const Point_reference p0 = get(vpm, source(hd, tm)); + const Point_reference p1 = get(vpm, target(hd, tm)); + const Point_reference p2 = get(vpm, target(next(hd, tm), tm)); internal::Barycentric_point_constructor bp_constructor; return bp_constructor(p0, loc.second[0], p1, loc.second[1], p2, loc.second[2], gt); } -template +template typename property_map_value::type -construct_point(const typename Location_traits::Face_location& loc, +#ifdef DOXYGEN_RUNNING +construct_point(const Face_location& loc, +#else +construct_point(const std::pair::face_descriptor, + std::array >& loc, +#endif const TriangleMesh& tm) { return construct_point(loc, tm, parameters::all_default()); @@ -635,10 +649,7 @@ construct_point(const typename Location_traits::Face_location& loc /// \ingroup PMP_locate_grp /// -/// \brief Given a location, that is an ordered pair composed of a -/// `boost::graph_traits::%face_descriptor` and an array -/// of barycentric coordinates, returns whether the location is -/// on the vertex `vd` or not. +/// \brief Given a location, returns whether the location is on the vertex `vd` or not. /// /// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) /// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance @@ -647,6 +658,7 @@ construct_point(const typename Location_traits::Face_location& loc /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` @@ -655,19 +667,23 @@ construct_point(const typename Location_traits::Face_location& loc /// /// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. /// -template +template bool -is_on_vertex(const typename Location_traits::Face_location& loc, +#ifdef DOXYGEN_RUNNING +is_on_vertex(const Face_location& loc, +#else +is_on_vertex(const std::pair::face_descriptor, + std::array >& loc, +#endif const typename boost::graph_traits::vertex_descriptor vd, const TriangleMesh& tm) { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename Location_traits::descriptor_variant descriptor_variant; if(!is_in_face(loc, tm)) return false; - descriptor_variant dv = get_descriptor_from_location(loc, tm); + const descriptor_variant dv = get_descriptor_from_location(loc, tm); if(const vertex_descriptor* vd_ptr = boost::get(&dv)) return (vd == *vd_ptr); @@ -677,10 +693,7 @@ is_on_vertex(const typename Location_traits::Face_location& loc, /// \ingroup PMP_locate_grp /// -/// \brief Given a location, that is an ordered pair composed of a -/// `boost::graph_traits::%face_descriptor` and an array -/// of barycentric coordinates, returns whether the location is -/// on the halfedge `hd` or not. +/// \brief Given a location, returns whether this location is on the halfedge `hd` or not. /// /// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) /// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance @@ -689,6 +702,7 @@ is_on_vertex(const typename Location_traits::Face_location& loc, /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` @@ -697,20 +711,24 @@ is_on_vertex(const typename Location_traits::Face_location& loc, /// /// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. /// -template +template bool -is_on_halfedge(const typename Location_traits::Face_location& loc, +#ifdef DOXYGEN_RUNNING +is_on_halfedge(const Face_location& loc, +#else +is_on_halfedge(const std::pair::face_descriptor, + std::array >& loc, +#endif const typename boost::graph_traits::halfedge_descriptor hd, const TriangleMesh& tm) { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename Location_traits::descriptor_variant descriptor_variant; if(!is_in_face(loc, tm)) return false; - descriptor_variant dv = get_descriptor_from_location(loc, tm); + const descriptor_variant dv = get_descriptor_from_location(loc, tm); if(const vertex_descriptor* vd_ptr = boost::get(&dv)) return (*vd_ptr == source(hd, tm) || *vd_ptr == target(hd, tm)); @@ -733,14 +751,19 @@ is_on_halfedge(const typename Location_traits::Face_location& loc, /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param bar an array of barycentric coordinates /// \param tm a triangulated surface mesh /// -template +template bool -is_in_face(const typename Location_traits::Barycentric_coordinates& bar, +#ifdef DOXYGEN_RUNNING +is_in_face(const Barycentric_coordinates& bar, +#else +is_in_face(const std::array& bar, +#endif const TriangleMesh& tm) { CGAL_USE(tm); @@ -750,7 +773,7 @@ is_in_face(const typename Location_traits::Barycentric_coordinates { // "|| bar[i] > 1." is not needed because if everything is positive and the sum is '1', // then each coefficient is below '1'. - if(bar[i] < 0.) + if(bar[i] < FT(0)) return false; } @@ -759,10 +782,7 @@ is_in_face(const typename Location_traits::Barycentric_coordinates /// \ingroup PMP_locate_grp /// -/// \brief Given a location, that is an ordered pair composed of a -/// `boost::graph_traits::%face_descriptor` and an array -/// of barycentric coordinates, returns whether the location is -/// in the face (boundary included) or not. +/// \brief Given a location, returns whether the location is in the face (boundary included) or not. /// /// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) /// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance @@ -771,6 +791,7 @@ is_in_face(const typename Location_traits::Barycentric_coordinates /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` @@ -778,9 +799,14 @@ is_in_face(const typename Location_traits::Barycentric_coordinates /// /// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. /// -template +template bool -is_in_face(const typename Location_traits::Face_location& loc, +#ifdef DOXYGEN_RUNNING +is_in_face(const Face_location& loc, +#else +is_in_face(const std::pair::face_descriptor, + std::array >& loc, +#endif const TriangleMesh& tm) { return is_in_face(loc.second, tm); @@ -788,10 +814,7 @@ is_in_face(const typename Location_traits::Face_location& loc, /// \ingroup PMP_locate_grp /// -/// \brief Given a location, that is an ordered pair composed of a -/// `boost::graph_traits::%face_descriptor` and an array -/// of barycentric coordinates, returns whether the location is on the boundary -/// of the face or not. +/// \brief Given a location, returns whether the location is on the boundary of the face or not. /// /// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) /// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance @@ -800,6 +823,7 @@ is_in_face(const typename Location_traits::Face_location& loc, /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` @@ -807,21 +831,23 @@ is_in_face(const typename Location_traits::Face_location& loc, /// /// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. /// -template +template bool -is_on_face_border(const typename Location_traits::Face_location& loc, +#ifdef DOXYGEN_RUNNING +is_on_face_border(const Face_location& loc, +#else +is_on_face_border(const std::pair::face_descriptor, + std::array >& loc, +#endif const TriangleMesh& tm) { - typedef typename Location_traits::Face_location Face_location; - typedef typename Face_location::second_type Barycentric_coordinates; - if(!is_in_face(loc, tm)) return false; - const Barycentric_coordinates& bar = loc.second; + const Barycentric_coordinates& bar = loc.second; for(int i=0; i<3; ++i) - if(bar[i] == 0.) + if(bar[i] == FT(0)) return true; return false; @@ -829,10 +855,7 @@ is_on_face_border(const typename Location_traits::Face_location& l /// \ingroup PMP_locate_grp /// -/// \brief Given a location, that is an ordered pair composed of a -/// `boost::graph_traits::%face_descriptor` and an array -/// of barycentric coordinates, returns whether the location is -/// on the border of the mesh or not. +/// \brief Given a location, returns whether the location is on the border of the mesh or not. /// /// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) /// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance @@ -841,6 +864,7 @@ is_on_face_border(const typename Location_traits::Face_location& l /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` @@ -848,19 +872,21 @@ is_on_face_border(const typename Location_traits::Face_location& l /// /// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. /// -template +template bool -is_on_mesh_border(const typename Location_traits::Face_location& loc, +#ifdef DOXYGEN_RUNNING +is_on_mesh_border(const Face_location& loc, +#else +is_on_mesh_border(const std::pair::face_descriptor, + std::array >& loc, +#endif const TriangleMesh& tm) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename Location_traits::Face_location Face_location; - typedef typename Face_location::second_type Barycentric_coordinates; - const face_descriptor fd = loc.first; - const Barycentric_coordinates& bar = loc.second; + const Barycentric_coordinates& bar = loc.second; if(!is_in_face(bar, tm)) return false; @@ -871,7 +897,7 @@ is_on_mesh_border(const typename Location_traits::Face_location& l // check if the point is a vertex for(int i=0; i<3; ++i) { - if(bar[i] == 1.) // coordinate at target(hd, tm) + if(bar[i] == FT(1)) // coordinate at target(hd, tm) return bool(CGAL::is_border(target(hd, tm), tm)); hd = next(hd, tm); } @@ -880,7 +906,7 @@ is_on_mesh_border(const typename Location_traits::Face_location& l // check if the point is on an edge for(int i=0; i<3; ++i) { - if(bar[i] == 0.) // coordinate at target(hd, tm) + if(bar[i] == FT(0)) // coordinate at target(hd, tm) return CGAL::is_border(edge(prev(hd, tm), tm), tm); hd = next(hd, tm); } @@ -907,6 +933,7 @@ is_on_mesh_border(const typename Location_traits::Face_location& l /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param vd a vertex of `tm` @@ -914,34 +941,33 @@ is_on_mesh_border(const typename Location_traits::Face_location& l /// /// \pre `vd` is not an isolated vertex /// -template -typename Location_traits::Face_location -locate_in_face(typename boost::graph_traits::vertex_descriptor vd, - const TriangleMesh& tm) +template +Face_location +locate_vertex(typename boost::graph_traits::vertex_descriptor vd, + const TriangleMesh& tm) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename Location_traits::FT FT; - typedef typename Location_traits::Face_location Face_location; + typedef Face_location Face_location; - halfedge_descriptor he = halfedge(vd, tm); + halfedge_descriptor hd = halfedge(vd, tm); - // Find a real face in case 'he' is a border halfedge - for(halfedge_descriptor hd : halfedges_around_target(he, tm)) + // Find a real face in case 'hd' is a border halfedge + for(halfedge_descriptor thd : halfedges_around_target(hd, tm)) { - if(!is_border(hd, tm)) + if(!is_border(thd, tm)) { - he = hd; + hd = thd; break; } } - CGAL_postcondition(!CGAL::is_border(he, tm)); // must find a 'real' face incident to 'vd' + CGAL_postcondition(!CGAL::is_border(hd, tm)); // must find a 'real' face incident to 'vd' - face_descriptor fd = face(he, tm); + face_descriptor fd = face(hd, tm); - CGAL_assertion(target(he, tm) == vd); + CGAL_assertion(target(hd, tm) == vd); CGAL_assertion(fd != boost::graph_traits::null_face()); // isolated vertex @@ -949,8 +975,8 @@ locate_in_face(typename boost::graph_traits::vertex_descriptor vd, return Face_location(); FT coords[3] = { FT(0), FT(0), FT(0) }; - he = next(he, tm); // so that source(he, tm) == vd and it's simpler to handle 'index_in_face' - std::size_t halfedge_local_index = halfedge_index_in_face(he, tm); + hd = next(hd, tm); // so that source(hd, tm) == vd and it's simpler to handle 'index_in_face' + int halfedge_local_index = halfedge_index_in_face(hd, tm); coords[halfedge_local_index] = FT(1); return std::make_pair(fd, CGAL::make_array(coords[0], coords[1], coords[2])); @@ -969,6 +995,7 @@ locate_in_face(typename boost::graph_traits::vertex_descriptor vd, /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param vd a vertex of `tm` and a vertex of the face `fd` @@ -977,14 +1004,12 @@ locate_in_face(typename boost::graph_traits::vertex_descriptor vd, /// /// \pre `fd` is not the null face /// -template -typename Location_traits::Face_location -locate_in_face(const typename boost::graph_traits::vertex_descriptor vd, - const typename boost::graph_traits::face_descriptor fd, - const TriangleMesh& tm) +template +Face_location +locate_vertex(const typename boost::graph_traits::vertex_descriptor vd, + const typename boost::graph_traits::face_descriptor fd, + const TriangleMesh& tm) { - typedef typename Location_traits::FT FT; - CGAL_precondition(fd != boost::graph_traits::null_face()); FT coords[3] = { FT(0), FT(0), FT(0) }; @@ -996,8 +1021,8 @@ locate_in_face(const typename boost::graph_traits::vertex_descript /// \ingroup PMP_locate_grp /// -/// \brief Given a point described by a halfedge `he` and a scalar `t` -/// as `p = (1 - t) * source(he, tm) + t * target(he, tm)`, +/// \brief Given a point described by a halfedge `hd` and a scalar `t` +/// as `p = (1 - t) * source(hd, tm) + t * target(hd, tm)`, /// returns this location along the given edge as a location, that is /// an ordered pair specifying a face containing the location and the /// barycentric coordinates of that location in that face. @@ -1009,23 +1034,23 @@ locate_in_face(const typename boost::graph_traits::vertex_descript /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// -/// \param he a halfedge of `tm` -/// \param t the parametric distance of the desired point along `he` +/// \param hd a halfedge of `tm` +/// \param t the parametric distance of the desired point along `hd` /// \param tm a triangulated surface mesh /// -template -typename Location_traits::Face_location -locate_in_face(const typename boost::graph_traits::halfedge_descriptor he, - const typename Location_traits::FT t, - const TriangleMesh& tm) +template +Face_location +locate_on_halfedge(const typename boost::graph_traits::halfedge_descriptor hd, + const FT t, + const TriangleMesh& tm) { typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename Location_traits::FT FT; - face_descriptor fd = face(he, tm); - std::size_t edge_local_index = halfedge_index_in_face(he, tm); + face_descriptor fd = face(hd, tm); + int edge_local_index = halfedge_index_in_face(hd, tm); const FT one_minus_t(FT(1) - t); FT coords[3] = { FT(0), FT(0), FT(0) }; @@ -1052,7 +1077,8 @@ locate_in_face(const typename boost::graph_traits::halfedge_descri /// \tparam TriangleMesh a model of `FaceGraph` /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// -/// \param query a point +/// \param query a point, whose type is equal to the value type of the vertex point property map +/// (either user-provided via named parameters or the internal point map of the mesh `tm`) /// \param fd a face of `tm` /// \param tm a triangulated surface mesh /// \param np an optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below: @@ -1064,7 +1090,9 @@ locate_in_face(const typename boost::graph_traits::halfedge_descri /// `boost::vertex_point_t` must be available in `TriangleMesh`. /// \cgalParamEnd /// \cgalParamBegin{geom_traits} -/// a geometric traits class instance, model of `Kernel`. +/// a geometric traits class instance, model of `Kernel`. If provided, the types `FT` and `Kernel::FT` +/// must be identical and the traits class must be compatible with the value type of the vertex point +/// property map. /// \cgalParamEnd /// \cgalParamBegin{snapping_tolerance} /// a tolerance value used to snap barycentric coordinates. Depending on the geometric traits used, @@ -1077,21 +1105,31 @@ locate_in_face(const typename boost::graph_traits::halfedge_descri /// /// \pre `fd` is not the null face /// +/// \returns a face location. The type `FT` is deduced from the geometric traits, either provided by +/// the user via named parameters (with `geom_traits`) or using `CGAL::Kernel_traits` +/// and the point type of the vertex point property map in use. +/// template -typename Location_traits::Face_location -locate_in_face(const typename Location_traits::Point& query, +#ifdef DOXYGEN_RUNNING +Face_location +locate_in_face(const Point& query, +#else +typename internal::Location_traits::Face_location +locate_in_face(const typename internal::Location_traits::Point& query, +#endif const typename boost::graph_traits::face_descriptor fd, const TriangleMesh& tm, const NamedParameters& np) { - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + + typedef typename GetVertexPointMap::const_type VertexPointMap; + typedef typename boost::property_traits::value_type Point; + typedef typename boost::property_traits::reference Point_reference; - typedef typename Location_traits::FT FT; + typedef typename GetGeomTraits::type Geom_traits; + typedef typename Geom_traits::FT FT; - // VertexPointMap - typedef typename GetGeomTraits::type Geom_traits; - typedef typename GetVertexPointMap::const_type VertexPointMap; - typedef typename boost::property_traits::value_type Point; using parameters::get_parameter; using parameters::choose_parameter; @@ -1107,9 +1145,9 @@ locate_in_face(const typename Location_traits::Po vertex_descriptor vd1 = target(halfedge(fd, tm), tm); vertex_descriptor vd2 = target(next(halfedge(fd, tm), tm), tm); - const Point& p0 = get(vpm, vd0); - const Point& p1 = get(vpm, vd1); - const Point& p2 = get(vpm, vd2); + const Point_reference p0 = get(vpm, vd0); + const Point_reference p1 = get(vpm, vd1); + const Point_reference p2 = get(vpm, vd2); std::array coords = barycentric_coordinates(p0, p1, p2, query, gt); @@ -1120,7 +1158,7 @@ locate_in_face(const typename Location_traits::Po // Try to to snap the coordinates, hoping the problem is just a -1e-17ish epsilon // pushing the coordinates over the edge - internal::snap_coordinates_to_border(coords, snap_tolerance); + internal::snap_coordinates_to_border(coords, snap_tolerance); } return std::make_pair(fd, coords); @@ -1128,8 +1166,8 @@ locate_in_face(const typename Location_traits::Po #ifndef DOXYGEN_RUNNING // because this is in the middle of a @{ @} doxygen group template -typename Location_traits::Face_location -locate_in_face(const typename property_map_value::type& query, +typename internal::Location_traits::Face_location +locate_in_face(const typename internal::Location_traits::Point& query, const typename boost::graph_traits::face_descriptor f, const TriangleMesh& tm) { @@ -1139,10 +1177,7 @@ locate_in_face(const typename property_map_value::%face_descriptor` and an array -/// of barycentric coordinates, and a second face adjacent to the first, -/// return the location of the point in the second face. +/// \brief Given a location and a second face adjacent to the first, returns the location of the point in the second face. /// /// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) /// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance @@ -1151,17 +1186,23 @@ locate_in_face(const typename property_map_value -typename Location_traits::Face_location -locate_in_adjacent_face(const typename Location_traits::Face_location& loc, +template +Face_location +#ifdef DOXYGEN_RUNNING +locate_in_adjacent_face(const Face_location& loc, +#else +locate_in_adjacent_face(const std::pair::face_descriptor, + std::array >& loc, +#endif const typename boost::graph_traits::face_descriptor fd, const TriangleMesh& tm) { @@ -1169,23 +1210,16 @@ locate_in_adjacent_face(const typename Location_traits::Face_locat typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef boost::variant descriptor_variant; - - typedef typename Location_traits::Face_location Face_location; - typedef typename Location_traits::FT FT; - if(loc.first == fd) return loc; - Face_location loc_in_fd = std::make_pair(fd, CGAL::make_array(FT(0), FT(0), FT(0))); - descriptor_variant dv = get_descriptor_from_location(loc, tm); + Face_location loc_in_fd = std::make_pair(fd, CGAL::make_array(FT(0), FT(0), FT(0))); + const descriptor_variant dv = get_descriptor_from_location(loc, tm); if(const vertex_descriptor* vd_ptr = boost::get(&dv)) { int index_of_vd = vertex_index_in_face(*vd_ptr, fd, tm); - loc_in_fd.second[index_of_vd] = 1.; + loc_in_fd.second[index_of_vd] = FT(1); // Note that the barycentric coordinates were initialized to 0, // so the second and third coordinates are already set up properly. } @@ -1234,21 +1268,22 @@ locate_in_adjacent_face(const typename Location_traits::Face_locat // - the first location must be known // - the second must be a point in a face incident to get_descriptor_from_location(known_location) // note: not returning the query location to emphasis that the known location can change too. -template +template bool -locate_in_common_face(typename Location_traits::Face_location& known_location, - const typename Location_traits::Point& query, - typename Location_traits::Face_location& query_location, +locate_in_common_face(std::pair::face_descriptor, + std::array >& known_location, + const typename internal::Location_traits::Point& query, + std::pair::face_descriptor, + std::array >& query_location, const TriangleMesh& tm, - const typename Location_traits::FT tolerance = - std::numeric_limits::FT>::epsilon()) + const NamedParameters& np, + const FT tolerance = std::numeric_limits::epsilon()) { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef boost::variant descriptor_variant; - descriptor_variant dv = get_descriptor_from_location(known_location, tm); + descriptor_variant dv = get_descriptor_from_location(known_location, tm); bool is_query_location_in_face = false; @@ -1263,8 +1298,8 @@ locate_in_common_face(typename Location_traits::Face_location& kno continue; // check if 'query' can be found in that face - query_location = locate_in_face(query, fd, tm); - internal::snap_location_to_border(query_location, tolerance); // @tmp keep or not ? + query_location = locate_in_face(query, fd, tm, np); + internal::snap_location_to_border(query_location, tm, tolerance); // @tmp keep or not ? is_query_location_in_face = is_in_face(query_location, tm); @@ -1279,15 +1314,15 @@ locate_in_common_face(typename Location_traits::Face_location& kno if(fd != boost::graph_traits::null_face()) { - query_location = locate_in_face(query, fd, tm); - internal::snap_location_to_border(query_location, tolerance); // @tmp keep or not ? + query_location = locate_in_face(query, fd, tm, np); + internal::snap_location_to_border(query_location, tm, tolerance); // @tmp keep or not ? is_query_location_in_face = is_in_face(query_location, tm); } if(!is_query_location_in_face) { fd = face(opposite(hd, tm), tm); - query_location = locate_in_face(query, fd, tm); + query_location = locate_in_face(query, fd, tm, np); is_query_location_in_face = is_in_face(query_location, tm); } } @@ -1297,8 +1332,8 @@ locate_in_common_face(typename Location_traits::Face_location& kno CGAL_precondition(fd != boost::graph_traits::null_face()); - query_location = locate_in_face(query, fd, tm); - internal::snap_location_to_border(query_location, tolerance); // @tmp keep or not ? + query_location = locate_in_face(query, fd, tm, np); + internal::snap_location_to_border(query_location, tm, tolerance); // @tmp keep or not ? is_query_location_in_face = is_in_face(query_location, tm); } @@ -1311,10 +1346,12 @@ locate_in_common_face(typename Location_traits::Face_location& kno // Finding a common face to two locations // - both locations must be known but can change -template +template bool -locate_in_common_face(typename Location_traits::Face_location& first_location, - typename Location_traits::Face_location& second_location, +locate_in_common_face(std::pair::face_descriptor, + std::array >& first_location, + std::pair::face_descriptor, + std::array >& second_location, const TriangleMesh& tm) { typedef typename boost::graph_traits::face_descriptor face_descriptor; @@ -1380,38 +1417,38 @@ locate_in_common_face(typename Location_traits::Face_location& fir namespace internal { -template::value> +template ::value> struct Point_to_Point_3 // 2D case { - typedef typename Location_traits::Geom_traits::Point_3 Point_3; + typedef typename GetGeomTraits::type::Point_3 Point_3; Point_3 operator()(const Point& p) const { return Point_3(p.x(), p.y(), 0); } }; -template +template struct Point_to_Point_3::Geom_traits::Point_3, + typename GetGeomTraits::type::Point_3, 3> // 3D case with nothing to do { - typedef typename Location_traits::Geom_traits::Point_3 Point_3; + typedef typename GetGeomTraits::type::Point_3 Point_3; const Point_3& operator()(const Point_3& p) const { return p; } }; -template +template struct Point_to_Point_3 // Generic 3D case { - typedef typename Location_traits::Geom_traits::Point_3 Point_3; + typedef typename GetGeomTraits::type::Point_3 Point_3; Point_3 operator()(const Point& p) const { return Point_3(p.x(), p.y(), p.z()); } }; -template +template struct Ray_to_Ray_3 // 2D case { - typedef typename Location_traits::Geom_traits Geom_traits; + typedef typename GetGeomTraits::type Geom_traits; typedef typename Geom_traits::Ray_2 Ray_2; typedef typename Geom_traits::Ray_3 Ray_3; typedef Point_to_Point_3 P2_to_P3; @@ -1426,9 +1463,9 @@ struct Ray_to_Ray_3 // 2D case }; // Readable property map that converts the output of a given vertex point map to a 3D point -template::const_type> +template ::const_type> struct Point_to_Point_3_VPM { private: @@ -1511,7 +1548,7 @@ void build_AABB_tree(const TriangleMesh& tm, /// to call location functions on more than a single point (or ray) should first compute an AABB /// tree to store it (otherwise, it will be recomputed every time). Note that since the AABB tree /// class is a 3D structure, it might be required to wrap your point property map to convert your -/// point type to the 3D point type (i.e., your kernel's `%Point_3`) if you are working +/// point type to the 3D point type (i.e., your traits' `%Point_3`) if you are working /// with a 2D triangle structure. /// /// @{ @@ -1527,7 +1564,7 @@ void build_AABB_tree(const TriangleMesh& tm, /// /// \tparam TriangleMesh a model of `FaceListGraph` /// \tparam Point3VPM a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` -/// as key type and the \cgal 3D point type (your kernel's `%Point_3`) as value type. +/// as key type and the \cgal 3D point type (your traits' `%Point_3`) as value type. /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// /// \param tm a triangulated surface mesh @@ -1540,18 +1577,28 @@ void build_AABB_tree(const TriangleMesh& tm, /// If this parameter is omitted, an internal property map for /// `boost::vertex_point_t` must be available in `TriangleMesh`. /// \cgalParamEnd +/// \cgalParamBegin{geom_traits} +/// a geometric traits class instance, model of `Kernel` compatible with the point type held +/// in the vertex point property map (either user-provided or internal to the mesh). +/// Must be identical to the traits used in the template parameter of the `AABB_traits`. +/// \cgalParamEnd /// \cgalNamedParamsEnd /// template -void build_AABB_tree(const TriangleMesh& tm, - AABB_tree< - CGAL::AABB_traits< - typename Location_traits::Geom_traits, - CGAL::AABB_face_graph_triangle_primitive - > >& outTree, - const NamedParameters& np) +void +build_AABB_tree(const TriangleMesh& tm, + AABB_tree< + AABB_traits< +#ifdef DOXYGEN_RUNNING + Geom_traits, +#else + typename GetGeomTraits::type, +#endif + CGAL::AABB_face_graph_triangle_primitive > >& outTree, + const NamedParameters& np) { typedef typename GetVertexPointMap::const_type VertexPointMap; + using parameters::get_parameter; using parameters::choose_parameter; @@ -1563,8 +1610,7 @@ void build_AABB_tree(const TriangleMesh& tm, #ifndef DOXYGEN_RUNNING template -void build_AABB_tree(const TriangleMesh& tm, - AABB_tree& outTree) +void build_AABB_tree(const TriangleMesh& tm, AABB_tree& outTree) { return build_AABB_tree(tm, outTree, parameters::all_default()); } @@ -1580,7 +1626,7 @@ void build_AABB_tree(const TriangleMesh& tm, /// /// \tparam TriangleMesh a model of `FaceListGraph` /// \tparam Point3VPM a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` -/// as key type and the \cgal 3D point type (your kernel's `%Point_3`) as value type. +/// as key type and the \cgal 3D point type (your traits' `%Point_3`) as value type. /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// /// \param p the point to locate on the input triangulated surface mesh @@ -1595,9 +1641,11 @@ void build_AABB_tree(const TriangleMesh& tm, /// `boost::vertex_point_t` must be available in `TriangleMesh`. /// \cgalParamEnd /// \cgalParamBegin{geom_traits} -/// a geometric traits class instance, model of `Kernel`. +/// a geometric traits class instance, model of `Kernel` compatible with the point type held +/// in the vertex point property map (either user-provided or internal to the mesh). +/// Must be identical to the traits used in the template parameter of the `AABB_traits`. /// \cgalParamEnd -/// \cgalParamBegin{snapping_tolerance} +/// \cgalParamBegin{snapping_tolerance} /// a tolerance value used to snap barycentric coordinates. Depending on the geometric traits used, /// the computation of the barycentric coordinates might be an inexact construction, thus leading /// to sometimes surprising values (e.g. a triplet `[0.5, 0.5, -1-e17]` for a point at the middle @@ -1606,36 +1654,47 @@ void build_AABB_tree(const TriangleMesh& tm, /// \cgalParamEnd /// \cgalNamedParamsEnd /// +/// \returns a face location. The type `FT` is deduced from the geometric traits, either provided by +/// the user via named parameters (with `geom_traits`) or using `CGAL::Kernel_traits` +/// and the point type of the vertex point property map in use. +/// template -typename Location_traits::Face_location -locate_with_AABB_tree(const typename Location_traits::Point& p, - const AABB_tree< - CGAL::AABB_traits< - typename Location_traits::Geom_traits, - CGAL::AABB_face_graph_triangle_primitive - > >& tree, +#ifdef DOXYGEN_RUNNING +Face_location +locate_with_AABB_tree(const Point& p, + const AABB_tree > >& tree, +#else +typename internal::Location_traits::Face_location +locate_with_AABB_tree(const typename internal::Location_traits::Point& p, + const AABB_tree::type, + CGAL::AABB_face_graph_triangle_primitive > >& tree, +#endif const TriangleMesh& tm, const NamedParameters& np) { - typedef typename Location_traits::Point Point; - typedef internal::Point_to_Point_3 P_to_P3; - typedef typename boost::property_traits::value_type Point_3; + typedef typename internal::Location_traits::Point Point; + typedef internal::Point_to_Point_3 P_to_P3; + typedef typename boost::property_traits::value_type Point_3; CGAL_static_assertion((std::is_same::value)); - typedef typename Location_traits::Geom_traits Geom_traits; - typedef typename CGAL::AABB_face_graph_triangle_primitive Primitive; - typedef typename CGAL::AABB_traits AABB_traits; + typedef typename GetGeomTraits::type Geom_traits; + typedef typename CGAL::AABB_face_graph_triangle_primitive Primitive; + typedef typename CGAL::AABB_traits AABB_traits; - typedef typename GetVertexPointMap::const_type VertexPointMap; - typedef internal::Point_to_Point_3_VPM WrappedVPM; + typedef typename GetVertexPointMap::const_type VertexPointMap; + typedef internal::Point_to_Point_3_VPM WrappedVPM; const Point_3& p3 = P_to_P3()(p); typename AABB_tree::Point_and_primitive_id result = tree.closest_point_and_primitive(p3); + typedef typename GetGeomTraits::type Geom_traits; + using parameters::get_parameter; using parameters::choose_parameter; - // The VPM might return a point of any dimension, but the AABB tree necessarily returns + // The VPM might return a point of any dimension, but the AABB tree necl1671essarily returns // a Point_3. So, wrap the VPM (again) to give a Point_3. Even if it's already wrapped, we're just // forwarding a const& anyway. const VertexPointMap vpm = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point), @@ -1647,8 +1706,8 @@ locate_with_AABB_tree(const typename Location_traits -typename Location_traits::Face_location -locate_with_AABB_tree(const typename Location_traits::Point& p, +typename internal::Location_traits::Face_location +locate_with_AABB_tree(const typename internal::Location_traits::Point& p, const AABB_tree& tree, const TriangleMesh& tm) { @@ -1678,7 +1737,8 @@ locate_with_AABB_tree(const typename Location_traits::Point& p, /// `boost::vertex_point_t` must be available in `TriangleMesh`. /// \cgalParamEnd /// \cgalParamBegin{geom_traits} -/// a geometric traits class instance, model of `Kernel`. +/// a geometric traits class instance, model of `Kernel` compatible with the point type held +/// in the vertex point property map (either user-provided or internal to the mesh). /// \cgalParamEnd /// \cgalParamBegin{snapping_tolerance} /// a tolerance value used to snap barycentric coordinates. Depending on the geometric traits used, @@ -1690,24 +1750,29 @@ locate_with_AABB_tree(const typename Location_traits::Point& p, /// \cgalNamedParamsEnd /// template -typename Location_traits::Face_location -locate(const typename Location_traits::Point& p, +#ifdef DOXYGEN_RUNNING +Face_location +locate(const Point& p, +#else +typename internal::Location_traits::Face_location +locate(const typename internal::Location_traits::Point& p, +#endif const TriangleMesh& tm, const NamedParameters& np) { // Wrap the input VPM with a one converting to 3D (costs nothing if the input VPM // already has value type Kernel::Point_3) - typedef typename GetVertexPointMap::const_type VertexPointMap; - typedef internal::Point_to_Point_3_VPM WrappedVPM; - typedef typename Location_traits::Point Intrinsic_point; + typedef typename GetVertexPointMap::const_type VertexPointMap; + typedef internal::Point_to_Point_3_VPM WrappedVPM; + typedef typename internal::Location_traits::Point Intrinsic_point; + + typedef typename GetGeomTraits::type Geom_traits; - typedef AABB_face_graph_triangle_primitive AABB_face_graph_primitive; - typedef CGAL::AABB_traits< - typename Location_traits::Geom_traits, - AABB_face_graph_primitive> AABB_face_graph_traits; + typedef AABB_face_graph_triangle_primitive AABB_face_graph_primitive; + typedef CGAL::AABB_traits AABB_face_graph_traits; - typedef internal::Point_to_Point_3 P_to_P3; - typedef typename AABB_face_graph_traits::Point_3 Point_3; + typedef internal::Point_to_Point_3 P_to_P3; + typedef typename AABB_face_graph_traits::Point_3 Point_3; using parameters::get_parameter; using parameters::choose_parameter; @@ -1727,7 +1792,7 @@ locate(const typename Location_traits::Point& p, #ifndef DOXYGEN_RUNNING template -typename Location_traits::Face_location +typename internal::Location_traits::Face_location locate(const typename property_map_value::type& p, const TriangleMesh& tm) { @@ -1743,7 +1808,7 @@ locate(const typename property_map_value::t /// /// \tparam TriangleMesh a model of `FaceListGraph`. /// \tparam Point3VPM a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` -/// as key type and the \cgal 3D point type (your kernel's `%Point_3`) as value type. +/// as key type and the \cgal 3D point type (your traits' `%Point_3`) as value type. /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// /// \param ray a ray to intersect with the input triangulated surface mesh @@ -1758,7 +1823,9 @@ locate(const typename property_map_value::t /// `boost::vertex_point_t` must be available in `TriangleMesh`. /// \cgalParamEnd /// \cgalParamBegin{geom_traits} -/// a geometric traits class instance, model of `Kernel`. +/// a geometric traits class instance, model of `Kernel` compatible with the point type held +/// in the vertex point property map (either user-provided or internal to the mesh). +/// Must be identical to the traits used in the template parameter of the `AABB_traits`. /// \cgalParamEnd /// \cgalParamBegin{snapping_tolerance} /// a tolerance value used to snap barycentric coordinates. Depending on the geometric traits used, @@ -1769,34 +1836,42 @@ locate(const typename property_map_value::t /// \cgalParamEnd /// \cgalNamedParamsEnd /// +/// \pre `ray` is an object with the same ambient dimension as the point type (the value type of the vertex point map). +/// template -typename Location_traits::Face_location -locate_with_AABB_tree(const typename Location_traits::Ray& ray, +#ifdef DOXYGEN_RUNNING +Face_location +locate_with_AABB_tree(const Ray& ray, + const AABB_tree > >& tree, +#else +typename internal::Location_traits::Face_location +locate_with_AABB_tree(const typename internal::Location_traits::Ray& ray, const AABB_tree< CGAL::AABB_traits< - typename Location_traits::Geom_traits, + typename GetGeomTraits::type, CGAL::AABB_face_graph_triangle_primitive > >& tree, +#endif const TriangleMesh& tm, const NamedParameters& np) { - typedef typename Location_traits::Geom_traits Geom_traits; + typedef typename GetGeomTraits::type Geom_traits; - typedef typename Geom_traits::FT FT; - typedef typename Geom_traits::Point_3 Point_3; - typedef typename Geom_traits::Ray_3 Ray_3; + typedef typename Geom_traits::FT FT; + typedef typename Geom_traits::Point_3 Point_3; + typedef typename Geom_traits::Ray_3 Ray_3; - typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename GetVertexPointMap::const_type VertexPointMap; - typedef internal::Point_to_Point_3_VPM WrappedVPM; - typedef internal::Ray_to_Ray_3 R_to_R3; + typedef typename GetVertexPointMap::const_type VertexPointMap; + typedef internal::Point_to_Point_3_VPM WrappedVPM; + typedef internal::Ray_to_Ray_3 R_to_R3; - typedef typename CGAL::AABB_face_graph_triangle_primitive Primitive; - typedef typename CGAL::AABB_traits AABB_traits; - typedef AABB_tree AABB_face_graph_tree; + typedef typename CGAL::AABB_face_graph_triangle_primitive Primitive; + typedef typename CGAL::AABB_traits AABB_traits; + typedef AABB_tree AABB_face_graph_tree; typedef typename AABB_face_graph_tree::template Intersection_and_primitive_id::Type Intersection_type; - typedef boost::optional Ray_intersection; + typedef boost::optional Ray_intersection; using parameters::get_parameter; using parameters::choose_parameter; @@ -1849,8 +1924,8 @@ locate_with_AABB_tree(const typename Location_traits -typename Location_traits::Face_location -locate_with_AABB_tree(const typename Location_traits::Ray& ray, +typename internal::Location_traits::Face_location +locate_with_AABB_tree(const typename internal::Location_traits::Ray& ray, const AABB_tree& tree, const TriangleMesh& tm) { @@ -1883,9 +1958,10 @@ locate_with_AABB_tree(const typename Location_traits::Ray& ray, /// `boost::vertex_point_t` must be available in `TriangleMesh`. /// \cgalParamEnd /// \cgalParamBegin{geom_traits} -/// a geometric traits class instance, model of `Kernel`. +/// a geometric traits class instance, model of `Kernel` compatible with the point type held +/// in the vertex point property map (either user-provided or internal to the mesh). /// \cgalParamEnd -/// \cgalParamBegin{snapping_tolerance} +/// \cgalParamBegin{snapping_tolerance} /// a tolerance value used to snap barycentric coordinates. Depending on the geometric traits used, /// the computation of the barycentric coordinates might be an inexact construction, thus leading /// to sometimes surprising values (e.g. a triplet `[0.5, 0.5, -1-e17]` for a point at the middle @@ -1894,9 +1970,16 @@ locate_with_AABB_tree(const typename Location_traits::Ray& ray, /// \cgalParamEnd /// \cgalNamedParamsEnd /// +/// \pre `ray` is an object with the same ambient dimension as the point type (the value type of the vertex point map). +/// template -typename Location_traits::Face_location -locate(const typename Location_traits::Ray& ray, +#ifdef DOXYGEN_RUNNING +Face_location +locate(const Ray& ray, +#else +typename internal::Location_traits::Face_location +locate(const typename internal::Location_traits::Ray& ray, +#endif const TriangleMesh& tm, const NamedParameters& np) { @@ -1906,9 +1989,10 @@ locate(const typename Location_traits::Ray& ray, // already has value type Geom_traits::Point_3) typedef internal::Point_to_Point_3_VPM VPM; + typedef typename GetGeomTraits::type Geom_traits; + typedef AABB_face_graph_triangle_primitive AABB_face_graph_primitive; - typedef CGAL::AABB_traits::Geom_traits, - AABB_face_graph_primitive> AABB_face_graph_traits; + typedef CGAL::AABB_traits AABB_face_graph_traits; using parameters::get_parameter; using parameters::choose_parameter; @@ -1924,9 +2008,9 @@ locate(const typename Location_traits::Ray& ray, #ifndef DOXYGEN_RUNNING template -typename Location_traits::Face_location +typename internal::Location_traits::Face_location locate(const typename internal::Ray_type_selector< - typename Location_traits::Point>::type& ray, + typename internal::Location_traits::Point>::type& ray, const TriangleMesh& tm) { return locate(ray, tm, parameters::all_default()); From 413d4986bcc8e73da58d2e44f55cde71bfafc368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 8 Oct 2019 15:42:27 +0200 Subject: [PATCH 3/7] Add an example showing the usage of PMP::Locate --- .../Polygon_mesh_processing.txt | 2 + .../doc/Polygon_mesh_processing/examples.txt | 1 + .../Polygon_mesh_processing/CMakeLists.txt | 1 + .../locate_example.cpp | 113 ++++++++++++++++++ 4 files changed, 117 insertions(+) create mode 100644 Polygon_mesh_processing/examples/Polygon_mesh_processing/locate_example.cpp diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt index 3cf3d142e12f..e3c97c7e1f7e 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt @@ -535,6 +535,8 @@ finding the nearest point on a mesh given a point or a ray (`CGAL::Polygon_mesh_processing::locate_with_AABB_tree()`, and similar), and location-based predicates (for example, `CGAL::Polygon_mesh_processing::is_on_face_border()`). +The example \ref Polygon_mesh_processing/locate_example.cpp presents a few of these functions. + **************************************** \section PMPOrientation Orientation diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt index 4165c6bf51b9..a9350578648b 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt @@ -25,4 +25,5 @@ \example Polygon_mesh_processing/repair_polygon_soup_example.cpp \example Polygon_mesh_processing/mesh_smoothing_example.cpp \example Polygon_mesh_processing/shape_smoothing_example.cpp +\example Polygon_mesh_processing/locate_example.cpp */ diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt index 88701b9e196b..95a539040ac8 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt @@ -85,6 +85,7 @@ create_single_source_cgal_program( "detect_features_example.cpp" ) create_single_source_cgal_program( "manifoldness_repair_example.cpp" ) create_single_source_cgal_program( "repair_polygon_soup_example.cpp" ) create_single_source_cgal_program( "mesh_smoothing_example.cpp") +create_single_source_cgal_program( "locate_example.cpp") if(OpenMesh_FOUND) create_single_source_cgal_program( "compute_normals_example_OM.cpp" ) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/locate_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/locate_example.cpp new file mode 100644 index 000000000000..2235be77dfda --- /dev/null +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/locate_example.cpp @@ -0,0 +1,113 @@ +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::FT FT; +typedef K::Point_2 Point_2; +typedef K::Ray_2 Ray_2; +typedef K::Point_3 Point_3; +typedef K::Ray_3 Ray_3; + +typedef CGAL::Surface_mesh Mesh; +typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; +typedef typename boost::graph_traits::face_descriptor face_descriptor; + +namespace CP = CGAL::parameters; +namespace PMP = CGAL::Polygon_mesh_processing; + +typedef PMP::Barycentric_coordinates Barycentric_coordinates; +typedef PMP::Face_location Face_location; + +int main(int /*argc*/, char** /*argv*/) +{ + // Generate a simple 3D triangle mesh that with vertices on the plane xOy + Mesh tm; + CGAL::make_grid(10, 10, tm); + PMP::triangulate_faces(tm); + + // Basic usage + Face_location random_location = PMP::random_location_on_mesh(tm); + const face_descriptor f = random_location.first; + const Barycentric_coordinates& coordinates = random_location.second; + + std::cout << "Random location on the mesh: face " << f + << " and with coordinates [" << coordinates[0] << "; " + << coordinates[1] << "; " + << coordinates[2] << "]\n"; + std::cout << "It corresponds to point (" << PMP::construct_point(random_location, tm) << ")\n\n"; + + // Locate a known 3D point in the mesh + const Point_3 query(1.2, 7.4, 0); + Face_location query_location = PMP::locate(query, tm); + + std::cout << "Point (" << query << ") is located in face " << query_location.first + << " with barycentric coordinates [" << query_location.second[0] << "; " + << query_location.second[1] << "; " + << query_location.second[2] << "]\n\n"; + + // Locate a 3D point in the mesh as the intersection of the mesh and a 3D ray. + // The AABB tree can be cached in case many queries are performed (otherwise, it is rebuilt + // on each call, which is expensive). + typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive; + typedef CGAL::AABB_traits AABB_face_graph_traits; + + CGAL::AABB_tree tree; + PMP::build_AABB_tree(tm, tree); + + const Ray_3 ray_3(Point_3(4.2, 6.8, 2.4), Point_3(7.2, 2.3, -5.8)); + Face_location ray_location = PMP::locate_with_AABB_tree(ray_3, tree, tm); + + std::cout << "Intersection of the 3D ray and the mesh is in face " << ray_location.first + << " with barycentric coordinates [" << ray_location.second[0] << " " + << ray_location.second[1] << " " + << ray_location.second[2] << "]\n"; + std::cout << "It corresponds to point (" << PMP::construct_point(ray_location, tm) << ")\n"; + std::cout << "Is it on the face's border? " << (PMP::is_on_face_border(ray_location, tm) ? "Yes" : "No") << "\n\n"; + + // ----------------------------------------------------------------------------------------------- + // Now, we artifically project the mesh to the natural 2D dimensional plane, with a little translation + // via a custom vertex point property map + + typedef CGAL::dynamic_vertex_property_t Point_2_property; + typedef typename boost::property_map::type Projection_pmap; + Projection_pmap projection_pmap = get(Point_2_property(), tm); + + for(vertex_descriptor v : vertices(tm)) + { + const Point_3& p = tm.point(v); + put(projection_pmap, v, Point_2(p.x() + 1, p.y())); // simply ignoring the z==0 coordinate and translating along Ox + } + + // Locate the same 3D point but in a 2D context + const Point_2 query_2(query.x() + 1, query.y()); + Face_location query_location_2 = PMP::locate(query_2, tm, CP::vertex_point_map(projection_pmap)); + + std::cout << "Point (" << query_2 << ") is located in face " << query_location_2.first + << " with barycentric coordinates [" << query_location_2.second[0] << "; " + << query_location_2.second[1] << "; " + << query_location_2.second[2] << "]\n\n"; + + // Shoot a 2D ray and locate the intersection with the mesh in 2D + const Ray_2 ray_2(Point_2(-10, -10), Point_2(10, 10)); + Face_location ray_location_2 = PMP::locate(ray_2, tm, CP::vertex_point_map(projection_pmap)); // This rebuilds an AABB tree on each call + + std::cout << "Intersection of the 2D ray and the mesh is in face " << ray_location_2.first + << " with barycentric coordinates [" << ray_location_2.second[0] << "; " + << ray_location_2.second[1] << "; " + << ray_location_2.second[2] << "]\n"; + std::cout << "It corresponds to point (" << PMP::construct_point(ray_location_2, tm, CP::vertex_point_map(projection_pmap)) << ")\n"; + + if(PMP::is_on_mesh_border(ray_location_2, tm)) + std::cout << "It is on the border of the mesh!\n" << std::endl; + + return EXIT_SUCCESS; +} From 22092a357aa69b78466f3756ff60d0039071630b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 8 Oct 2019 15:42:41 +0200 Subject: [PATCH 4/7] Update tests of PMP::Locate (and fix some VPM usages) --- .../test_pmp_locate.cpp | 383 ++++++++++-------- 1 file changed, 213 insertions(+), 170 deletions(-) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_locate.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_locate.cpp index 5b704de13bbd..03e74b71eecd 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_locate.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_locate.cpp @@ -42,6 +42,7 @@ namespace PMP = CGAL::Polygon_mesh_processing; typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK; typedef CGAL::Exact_predicates_exact_constructions_kernel EPECK; + typedef CGAL::Simple_cartesian::Type> Exact_kernel; template @@ -96,32 +97,31 @@ bool is_equal(const FT& a, const FT& b) return (a == b); } -template +template void test_snappers(const G& g) { std::cout << " test snappers..." << std::endl; - typedef typename PMP::Location_traits::FT FT; + typedef typename K::FT FT; - typename PMP::Location_traits::Barycentric_coordinates coords = CGAL::make_array(FT(1e-6), FT(0.9999999999999999999), FT(1e-7)); - typename PMP::Location_traits::Face_location loc = std::make_pair(*(faces(g).first), coords); + PMP::Barycentric_coordinates coords = CGAL::make_array(FT(1e-6), FT(0.9999999999999999999), FT(1e-7)); + PMP::Face_location loc = std::make_pair(*(faces(g).first), coords); // --------------------------------------------------------------------------- - PMP::internal::snap_coordinates_to_border(coords); // uses numeric_limits' epsilon() + PMP::internal::snap_coordinates_to_border(coords); // uses numeric_limits' epsilon() assert(coords[0] == FT(1e-6) && coords[1] == FT(1) && coords[2] == FT(1e-7)); - PMP::internal::snap_coordinates_to_border(coords, 1e-5); + PMP::internal::snap_coordinates_to_border(coords, FT(1e-5)); assert(coords[0] == FT(0) && coords[1] == FT(1) && coords[2] == FT(0)); // --------------------------------------------------------------------------- - PMP::internal::snap_location_to_border(loc); // uses numeric_limits' epsilon() + PMP::internal::snap_location_to_border(loc, g); // uses numeric_limits' epsilon() assert(!PMP::is_on_face_border(loc, g)); - PMP::internal::snap_location_to_border(loc, 1e-7); + PMP::internal::snap_location_to_border(loc, g, FT(1e-7)); assert(PMP::is_on_face_border(loc, g)); } - template struct Point_to_bare_point { @@ -134,49 +134,48 @@ struct Point_to_bare_point typedef typename K::Point_3 type; }; -template -void test_constructions(const G& g, CGAL::Random& rnd) +template +void test_constructions(const G& g, + const VPM vpm, + CGAL::Random& rnd) { std::cout << " test constructions..." << std::endl; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename PMP::Location_traits::descriptor_variant descriptor_variant; - - typedef typename boost::property_map_value::type Point; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; - typedef typename Point_to_bare_point::type Bare_point; + typedef typename PMP::descriptor_variant descriptor_variant; - typedef typename PMP::Location_traits::Barycentric_coordinates Barycentric_coordinates; - typedef typename PMP::Location_traits::Face_location Face_location; + typedef typename boost::property_traits::value_type Point; + typedef typename boost::property_traits::reference Point_reference; + typedef typename K::FT FT; + typedef typename Point_to_bare_point::type Bare_point; - typedef typename boost::property_map::const_type VPM; - VPM vpm = CGAL::get_const_property_map(boost::vertex_point, g); + typedef typename PMP::Barycentric_coordinates Barycentric_coordinates; + typedef typename PMP::Face_location Face_location; face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); halfedge_descriptor h = halfedge(f, g); vertex_descriptor v = source(h, g); - Point p = get(vpm, v); - Point q = get(vpm, target(h, g)); - Point r = get(vpm, target(next(h, g), g)); + Point_reference p = get(vpm, v); + Point_reference q = get(vpm, target(h, g)); + Point_reference r = get(vpm, target(next(h, g), g)); - Bare_point bp(p); - Bare_point bq(q); - Bare_point br(r); + const Bare_point bp(p); + const Bare_point bq(q); + const Bare_point br(r); Barycentric_coordinates bar; Face_location loc; loc.first = f; // --------------------------------------------------------------------------- - bar = PMP::barycentric_coordinates(p, q, r, p, Kernel()); + bar = PMP::barycentric_coordinates(p, q, r, p, K()); assert(is_equal(bar[0], FT(1)) && is_equal(bar[1], FT(0)) && is_equal(bar[2], FT(0))); - bar = PMP::barycentric_coordinates(p, q, r, q, Kernel()); + bar = PMP::barycentric_coordinates(p, q, r, q, K()); assert(is_equal(bar[0], FT(0)) && is_equal(bar[1], FT(1)) && is_equal(bar[2], FT(0))); - bar = PMP::barycentric_coordinates(p, q, r, r, Kernel()); + bar = PMP::barycentric_coordinates(p, q, r, r, K()); assert(is_equal(bar[0], FT(0)) && is_equal(bar[1], FT(0)) && is_equal(bar[2], FT(1))); Point mp = Point(CGAL::midpoint(bp, bq)); @@ -190,12 +189,18 @@ void test_constructions(const G& g, CGAL::Random& rnd) const FT b = rnd.get_double(-1., 1.); const FT c = 1. - a - b; + // Point to location and inversely Bare_point barycentric_pt = CGAL::barycenter(bp, a, bq, b, br, c); bar = PMP::barycentric_coordinates(p, q, r, Point(barycentric_pt)); assert(is_equal(bar[0], a) && is_equal(bar[1], b) && is_equal(bar[2], c)); loc.second = bar; - const FT sq_dist = CGAL::squared_distance(barycentric_pt, Bare_point(PMP::construct_point(loc, g))); + const Bare_point barycentric_pt_2 = + Bare_point(PMP::construct_point(loc, g, + CGAL::parameters::vertex_point_map(vpm) + .geom_traits(K()))); + + const FT sq_dist = CGAL::squared_distance(barycentric_pt, barycentric_pt_2); assert(is_equal(sq_dist, FT(0))); } @@ -216,13 +221,12 @@ void test_constructions(const G& g, CGAL::Random& rnd) if(const vertex_descriptor* v = boost::get(&dv)) { } else { assert(false); } // --------------------------------------------------------------------------- - - Point s = PMP::construct_point(loc, g, CGAL::parameters::all_default()); - s = PMP::construct_point(loc, g); - assert(s == get(vpm, source(halfedge(f, g), g))); + // just to check the API + PMP::construct_point(loc, g); + PMP::construct_point(loc, g, CGAL::parameters::all_default()); } -template +template void test_random_entities(const G& g, CGAL::Random& rnd) { std::cout << " test random entities..." << std::endl; @@ -230,11 +234,8 @@ void test_random_entities(const G& g, CGAL::Random& rnd) typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename PMP::Location_traits::Face_location Face_location; - - typedef typename boost::property_map_value::type Point; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; + typedef typename K::FT FT; + typedef typename PMP::Face_location Face_location; // --------------------------------------------------------------------------- Face_location loc; @@ -247,19 +248,19 @@ void test_random_entities(const G& g, CGAL::Random& rnd) int nn = 100; while(nn --> 0) // the infamous 'go to zero' operator { - loc = PMP::random_location_on_mesh(g, rnd); + loc = PMP::random_location_on_mesh(g, rnd); assert(loc.first != boost::graph_traits::null_face()); assert(loc.second[0] >= FT(0) && loc.second[0] <= FT(1) && loc.second[1] >= FT(0) && loc.second[1] <= FT(1) && loc.second[2] >= FT(0) && loc.second[2] <= FT(1)); - loc = PMP::random_location_on_face(f, g, rnd); + loc = PMP::random_location_on_face(f, g, rnd); assert(loc.first == f); assert(loc.second[0] >= FT(0) && loc.second[0] <= FT(1) && loc.second[1] >= FT(0) && loc.second[1] <= FT(1) && loc.second[2] >= FT(0) && loc.second[2] <= FT(1)); - loc = PMP::random_location_on_halfedge(h, g, rnd); + loc = PMP::random_location_on_halfedge(h, g, rnd); assert(loc.first == face(h, g)); assert(loc.second[0] >= FT(0) && loc.second[0] <= FT(1) && loc.second[1] >= FT(0) && loc.second[1] <= FT(1) && @@ -269,7 +270,7 @@ void test_random_entities(const G& g, CGAL::Random& rnd) } } -template +template void test_helpers(const G& g, CGAL::Random& rnd) { std::cout << " test helpers..." << std::endl; @@ -278,7 +279,8 @@ void test_helpers(const G& g, CGAL::Random& rnd) typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename PMP::Location_traits::Face_location Face_location; + typedef typename K::FT FT; + typedef typename PMP::Face_location Face_location; face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); halfedge_descriptor h = halfedge(f, g); @@ -302,31 +304,31 @@ void test_helpers(const G& g, CGAL::Random& rnd) // --------------------------------------------------------------------------- // Incident faces - Face_location loc = PMP::random_location_on_face(f, g, rnd); + Face_location loc = PMP::random_location_on_face(f, g, rnd); std::set s; PMP::internal::incident_faces(loc, g, std::inserter(s, s.begin())); assert(PMP::is_on_face_border(loc, g) || s.size() == 1); - loc = PMP::random_location_on_halfedge(h, g, rnd); + loc = PMP::random_location_on_halfedge(h, g, rnd); std::vector vec; PMP::internal::incident_faces(loc, g, std::back_inserter(vec)); - assert(PMP::is_on_vertex(loc, source(h, g), g) || PMP::is_on_vertex(loc, target(h, g), g) || vec.size() == 2); + assert(PMP::is_on_vertex(loc, source(h, g), g) || + PMP::is_on_vertex(loc, target(h, g), g) || + vec.size() == 2); } -template +template void test_predicates(const G& g, CGAL::Random& rnd) { std::cout << " test predicates..." << std::endl; - typedef typename boost::property_map_value::type Point; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; + typedef typename K::FT FT; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename PMP::Location_traits::Face_location Face_location; + typedef typename PMP::Face_location Face_location; face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); halfedge_descriptor h = halfedge(f, g); @@ -334,39 +336,39 @@ void test_predicates(const G& g, CGAL::Random& rnd) // --------------------------------------------------------------------------- Face_location loc(f, CGAL::make_array(FT(1), FT(0), FT(0))); - assert(PMP::is_on_vertex(loc, v, g)); + assert(PMP::is_on_vertex(loc, v, g)); loc = Face_location(f, CGAL::make_array(FT(0), FT(1), FT(0))); - assert(PMP::is_on_vertex(loc, target(h, g), g)); + assert(PMP::is_on_vertex(loc, target(h, g), g)); loc = Face_location(f, CGAL::make_array(FT(0), FT(0), FT(1))); - assert(PMP::is_on_vertex(loc, target(next(h, g), g), g)); + assert(PMP::is_on_vertex(loc, target(next(h, g), g), g)); loc = Face_location(f, CGAL::make_array(FT(-1), FT(1), FT(1))); - assert(!PMP::is_on_vertex(loc, target(next(h, g), g), g)); + assert(!PMP::is_on_vertex(loc, target(next(h, g), g), g)); // --------------------------------------------------------------------------- loc = Face_location(f, CGAL::make_array(FT(0.5), FT(0.5), FT(0))); - assert(PMP::is_on_halfedge(loc, h, g)); + assert(PMP::is_on_halfedge(loc, h, g)); loc = Face_location(f, CGAL::make_array(FT(0), FT(0.5), FT(0.5))); - assert(PMP::is_on_halfedge(loc, next(h, g), g)); + assert(PMP::is_on_halfedge(loc, next(h, g), g)); loc = Face_location(f, CGAL::make_array(FT(-0.5), FT(1.5), FT(0))); - assert(!PMP::is_on_halfedge(loc, h, g)); + assert(!PMP::is_on_halfedge(loc, h, g)); loc = Face_location(f, CGAL::make_array(FT(0.1), FT(-0.6), FT(1.5))); - assert(!PMP::is_on_halfedge(loc, h, g)); + assert(!PMP::is_on_halfedge(loc, h, g)); // --------------------------------------------------------------------------- loc = Face_location(f, CGAL::make_array(FT(0.3), FT(0.3), FT(0.4))); - assert(PMP::is_in_face(loc, g)); + assert(PMP::is_in_face(loc, g)); loc = Face_location(f, CGAL::make_array(FT(0), FT(0), FT(1))); - assert(PMP::is_in_face(loc, g)); + assert(PMP::is_in_face(loc, g)); loc = Face_location(f, CGAL::make_array(FT(0), FT(2), FT(-1))); - assert(!PMP::is_in_face(loc, g)); + assert(!PMP::is_in_face(loc, g)); // --------------------------------------------------------------------------- loc = Face_location(f, CGAL::make_array(FT(0.3), FT(0.3), FT(0.4))); - assert(!PMP::is_on_face_border(loc, g)); + assert(!PMP::is_on_face_border(loc, g)); loc = Face_location(f, CGAL::make_array(FT(0), FT(0.6), FT(0.4))); - assert(PMP::is_on_face_border(loc, g)); + assert(PMP::is_on_face_border(loc, g)); loc = Face_location(f, CGAL::make_array(FT(0), FT(0), FT(1))); - assert(PMP::is_on_face_border(loc, g)); + assert(PMP::is_on_face_border(loc, g)); loc = Face_location(f, CGAL::make_array(FT(-0.2), FT(0), FT(1.2))); assert(!PMP::is_on_face_border(loc, g)); @@ -388,68 +390,69 @@ void test_predicates(const G& g, CGAL::Random& rnd) loc.second[(id_of_h+1)%3] = FT(0); loc.second[(id_of_h+2)%3] = FT(0); boost::optional opt_hd = CGAL::is_border(source(h, g), g); - assert(PMP::is_on_mesh_border(loc, g) == (opt_hd != boost::none)); + assert(PMP::is_on_mesh_border(loc, g) == (opt_hd != boost::none)); loc.second[id_of_h] = FT(0.5); loc.second[(id_of_h+1)%3] = FT(0.5); - assert(PMP::is_on_mesh_border(loc, g) == CGAL::is_border(edge(h, g), g)); + assert(PMP::is_on_mesh_border(loc, g) == CGAL::is_border(edge(h, g), g)); // Even if the point does lie on the border of the mesh, 'false' is returned because // another face descriptor should be used. loc.second[id_of_h] = -0.5; loc.second[(id_of_h+1)%3] = 1.5; - assert(!PMP::is_on_mesh_border(loc, g)); + assert(!PMP::is_on_mesh_border(loc, g)); if(++counter > max) break; } } -template -void test_locate_in_face(const G& g, CGAL::Random& rnd) +template +void test_locate_in_face(const G& g, + const VPM vpm, + CGAL::Random& rnd) { std::cout << " test locate_in_face()..." << std::endl; - typedef typename boost::property_map_value::type Point; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; + typedef typename boost::property_traits::reference Point_reference; + typedef typename K::FT FT; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename PMP::Location_traits::Face_location Face_location; - - typedef typename boost::property_map::const_type VertexPointMap; - VertexPointMap vpm = CGAL::get_const_property_map(boost::vertex_point, g); + typedef typename PMP::Face_location Face_location; const face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); const halfedge_descriptor h = halfedge(f, g); const vertex_descriptor v = target(h, g); Face_location loc; - typename PMP::Location_traits::FT a = 0.1; - Point p = get(vpm, v); + FT a = 0.1; + Point_reference p = get(vpm, v); - loc = PMP::locate_in_face(v, g); + loc = PMP::locate_vertex(v, g); assert(is_equal(loc.second[CGAL::vertex_index_in_face(v, loc.first, g)], FT(1))); assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+1)%3], FT(0))); assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+2)%3], FT(0))); - loc = PMP::locate_in_face(v, f, g); + loc = PMP::locate_vertex(v, f, g); assert(loc.first == f); assert(is_equal(loc.second[0], FT(0)) && is_equal(loc.second[1], FT(1)) && is_equal(loc.second[2], FT(0))); - loc = PMP::locate_in_face(h, a, g); + loc = PMP::locate_on_halfedge(h, a, g); const int h_id = CGAL::halfedge_index_in_face(h, g); assert(loc.first == f && is_equal(loc.second[(h_id+2)%3], FT(0))); - loc = PMP::locate_in_face(p, f, g, CGAL::parameters::all_default()); + loc = PMP::locate_in_face(p, f, g, CGAL::parameters::vertex_point_map(vpm).geom_traits(K())); int v_id = CGAL::vertex_index_in_face(v, f, g); assert(loc.first == f && is_equal(loc.second[v_id], FT(1))); - loc = PMP::locate_in_face(p, f, g); - v_id = CGAL::vertex_index_in_face(v, f, g); + // Internal vertex point pmap + typedef typename boost::property_map_value::type Point; + + Point p2 = get(CGAL::vertex_point, g, v); + PMP::locate_in_face(p2, f, g); assert(loc.first == f && is_equal(loc.second[v_id], FT(1))); // --------------------------------------------------------------------------- @@ -473,84 +476,82 @@ void test_locate_in_face(const G& g, CGAL::Random& rnd) PMP::locate_in_adjacent_face(loc, neigh_f, g); - assert(PMP::locate_in_common_face(loc, neigh_loc, g)); + assert(PMP::locate_in_common_face(loc, neigh_loc, g)); - assert(PMP::locate_in_common_face(loc, p, neigh_loc, g)); - assert(PMP::locate_in_common_face(loc, p, neigh_loc, g, 1e-7)); + assert(PMP::locate_in_common_face(loc, p, neigh_loc, g, CGAL::parameters::vertex_point_map(vpm).geom_traits(K()))); + assert(PMP::locate_in_common_face(loc, p, neigh_loc, g, CGAL::parameters::vertex_point_map(vpm).geom_traits(K()), 1e-7)); } } -template +template ::value_type>::value> struct Locate_with_AABB_tree_Tester // 2D case { template - void operator()(const G& g, CGAL::Random& rnd) const + void test(const G& g, const VPM vpm, CGAL::Random& rnd) const { std::cout << " test locate_with_AABB_tree (2D)..." << std::endl; - typedef typename boost::property_map_value::type Point; + typedef typename boost::property_traits::reference Point_reference; - typedef typename boost::property_map::const_type VertexPointMap; - - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; - typedef typename Kernel::Ray_2 Ray_2; - typedef typename Kernel::Ray_3 Ray_3; - typedef typename Kernel::Point_3 Point_3; + typedef typename K::FT FT; + typedef typename K::Ray_2 Ray_2; + typedef typename K::Ray_3 Ray_3; + typedef typename K::Point_3 Point_3; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename PMP::Location_traits::Face_location Face_location; + typedef typename PMP::Face_location Face_location; face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); halfedge_descriptor h = halfedge(f, g); vertex_descriptor v = target(h, g); // --------------------------------------------------------------------------- - typedef typename boost::property_traits::value_type Intrinsic_point; + typedef typename boost::property_traits::value_type Intrinsic_point; typedef PMP::internal::Point_to_Point_3 Intrinsic_point_to_Point_3; - typedef PMP::internal::Point_to_Point_3_VPM WrappedVertexPointMap; - typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive; - typedef CGAL::AABB_traits AABB_face_graph_traits; + typedef PMP::internal::Point_to_Point_3_VPM WrappedVPM; + typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive; + typedef CGAL::AABB_traits AABB_face_graph_traits; CGAL_static_assertion((std::is_same::value)); Intrinsic_point_to_Point_3 to_p3; CGAL::AABB_tree tree_a; - VertexPointMap vpm_a = CGAL::get_const_property_map(boost::vertex_point, g); - typename boost::property_traits::value_type p_a = get(vpm_a, v); + Point_reference p_a = get(vpm, v); const Point_3& p3_a = to_p3(p_a); CGAL::AABB_tree tree_b; - WrappedVertexPointMap vpm_b(g); + WrappedVPM vpm_b(vpm); // --------------------------------------------------------------------------- - PMP::build_AABB_tree(g, tree_a); - assert(tree_a.size() == num_faces(g)); - + PMP::build_AABB_tree(g, tree_a, CGAL::parameters::vertex_point_map(vpm)); PMP::build_AABB_tree(g, tree_b, CGAL::parameters::vertex_point_map(vpm_b)); assert(tree_b.size() == num_faces(g)); - Face_location loc = PMP::locate_with_AABB_tree(p_a, tree_a, g); + Face_location loc = PMP::locate_with_AABB_tree(p_a, tree_a, g, CGAL::parameters::vertex_point_map(vpm)); // sanitize otherwise some test platforms fail - PMP::internal::snap_location_to_border(loc, 1e-7); + PMP::internal::snap_location_to_border(loc, g, FT(1e-7)); assert(PMP::is_on_vertex(loc, v, g)); // might fail du to precision issues... assert(is_equal(loc.second[CGAL::vertex_index_in_face(v, loc.first, g)], FT(1))); assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+1)%3], FT(0))); assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+2)%3], FT(0))); - assert(is_equal(CGAL::squared_distance(to_p3(PMP::construct_point(loc, g)), p3_a), FT(0))); + assert(is_equal(CGAL::squared_distance(to_p3( + PMP::construct_point(loc, g, CGAL::parameters::vertex_point_map(vpm))), p3_a), FT(0))); - loc = PMP::locate_with_AABB_tree(p_a, tree_a, g, CGAL::parameters::vertex_point_map(vpm_a)); - assert(is_equal(CGAL::squared_distance(to_p3(PMP::construct_point(loc, g)), p3_a), FT(0))); + loc = PMP::locate_with_AABB_tree(p_a, tree_a, g, CGAL::parameters::vertex_point_map(vpm)); + assert(is_equal(CGAL::squared_distance(to_p3( + PMP::construct_point(loc, g, CGAL::parameters::vertex_point_map(vpm))), p3_a), FT(0))); // --------------------------------------------------------------------------- - loc = PMP::locate(p_a, g); - assert(is_equal(CGAL::squared_distance(to_p3(PMP::construct_point(loc, g)), p3_a), FT(0))); + loc = PMP::locate(p_a, g, CGAL::parameters::vertex_point_map(vpm)); + assert(is_equal(CGAL::squared_distance(to_p3( + PMP::construct_point(loc, g, CGAL::parameters::vertex_point_map(vpm))), p3_a), FT(0))); assert(PMP::is_in_face(loc, g)); loc = PMP::locate_with_AABB_tree(CGAL::ORIGIN, tree_b, g, CGAL::parameters::vertex_point_map(vpm_b)); @@ -561,12 +562,13 @@ struct Locate_with_AABB_tree_Tester // 2D case // --------------------------------------------------------------------------- Ray_2 r2 = random_2D_ray >(tree_a, rnd); - loc = PMP::locate_with_AABB_tree(r2, tree_a, g); + loc = PMP::locate_with_AABB_tree(r2, tree_a, g, CGAL::parameters::vertex_point_map(vpm)); if(loc.first != boost::graph_traits::null_face()) assert(PMP::is_in_face(loc, g)); Ray_3 r3 = random_3D_ray >(tree_b, rnd); - loc = PMP::locate_with_AABB_tree(r3, tree_b, g, CGAL::parameters::vertex_point_map(vpm_b)); + loc = PMP::locate_with_AABB_tree(r3, tree_b, g, CGAL::parameters::vertex_point_map(vpm_b) + .geom_traits(K())); } }; @@ -575,7 +577,7 @@ struct My_3D_Point { typedef typename K::FT FT; - typedef K R; + typedef K R; // so that we can use Kernel_traits typedef CGAL::Dimension_tag<3> Ambient_dimension; typedef CGAL::Dimension_tag<0> Feature_dimension; @@ -591,112 +593,117 @@ struct My_3D_Point FT cx, cy, cz; }; -template <> -struct Locate_with_AABB_tree_Tester<3> // 3D +template +struct Locate_with_AABB_tree_Tester // 3D { template - void operator()(const G& g, CGAL::Random& rnd) const + void test(const G& g, const VPM vpm, CGAL::Random& rnd) const { std::cout << " test locate_with_AABB_tree (3D)..." << std::endl; - typedef typename boost::property_map_value::type Point; + typedef typename boost::property_traits::reference Point_reference; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; - typedef typename Kernel::Ray_3 Ray_3; - typedef typename Kernel::Point_3 Point_3; + typedef typename K::FT FT; + typedef typename K::Ray_3 Ray_3; + typedef typename K::Point_3 Point_3; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename PMP::Location_traits::Face_location Face_location; + typedef typename PMP::Face_location Face_location; face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); halfedge_descriptor h = halfedge(f, g); vertex_descriptor v = target(h, g); // --------------------------------------------------------------------------- - typedef typename PMP::Location_traits::VPM VertexPointMap; - typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive; - typedef CGAL::AABB_traits AABB_face_graph_traits; + typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive; + typedef CGAL::AABB_traits AABB_face_graph_traits; CGAL_static_assertion((std::is_same::value)); CGAL::AABB_tree tree_a; - VertexPointMap vpm_a = CGAL::get_const_property_map(boost::vertex_point, g); - typename boost::property_traits::value_type p3_a = get(vpm_a, v); + Point_reference p3_a = get(vpm, v); // below tests the case where the value type of the VPM is not Kernel::Point_3 - typedef My_3D_Point Intrinsic_point; - typedef std::map Custom_map; + typedef My_3D_Point Custom_point; + typedef std::map Custom_map; typedef boost::associative_property_map Custom_VPM; - typedef PMP::internal::Point_to_Point_3_VPM WrappedVertexPointMap; - typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive_with_WVPM; - typedef CGAL::AABB_traits AABB_face_graph_traits_with_WVPM; + typedef PMP::internal::Point_to_Point_3_VPM WrappedVPM; + typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive_with_WVPM; + typedef CGAL::AABB_traits AABB_face_graph_traits_with_WVPM; CGAL::AABB_tree tree_b; Custom_map custom_map; for(vertex_descriptor vd : vertices(g)) { - const Point_3& p = get(vpm_a, vd); - custom_map[vd] = Intrinsic_point(p.x(), p.y(), p.z()); + const Point_reference p = get(vpm, vd); + custom_map[vd] = Custom_point(p.x(), p.y(), p.z()); } Custom_VPM custom_vpm(custom_map); - WrappedVertexPointMap vpm_b(custom_vpm); + WrappedVPM custom_vpm_3D(custom_vpm); // --------------------------------------------------------------------------- - PMP::build_AABB_tree(g, tree_a); + PMP::build_AABB_tree(g, tree_a); // just for the API assert(tree_a.size() == num_faces(g)); - PMP::build_AABB_tree(g, tree_b, CGAL::parameters::vertex_point_map(vpm_b)); + PMP::build_AABB_tree(g, tree_a, CGAL::parameters::vertex_point_map(vpm)); + PMP::build_AABB_tree(g, tree_b, CGAL::parameters::vertex_point_map(custom_vpm_3D)); assert(tree_b.size() == num_faces(g)); - Face_location loc = PMP::locate_with_AABB_tree(p3_a, tree_a, g); + Face_location loc = PMP::locate_with_AABB_tree(p3_a, tree_a, g, CGAL::parameters::vertex_point_map(vpm)); assert(is_equal(loc.second[CGAL::vertex_index_in_face(v, loc.first, g)], FT(1))); assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+1)%3], FT(0))); assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+2)%3], FT(0))); assert(is_equal(CGAL::squared_distance(PMP::construct_point(loc, g), p3_a), FT(0))); - loc = PMP::locate_with_AABB_tree(p3_a, tree_a, g, CGAL::parameters::vertex_point_map(vpm_a)); + loc = PMP::locate_with_AABB_tree(p3_a, tree_a, g, CGAL::parameters::vertex_point_map(vpm)); assert(is_equal(CGAL::squared_distance(PMP::construct_point(loc, g), p3_a), FT(0))); // --------------------------------------------------------------------------- loc = PMP::locate(p3_a, g, CGAL::parameters::snapping_tolerance(1e-7)); - std::cout << "loc: " << loc.second[0] << " " << loc.second[1] << " " << loc.second[2] << std::endl; // @tmp assert(is_equal(CGAL::squared_distance(PMP::construct_point(loc, g), p3_a), FT(0))); assert(PMP::is_in_face(loc, g)); - loc = PMP::locate_with_AABB_tree(CGAL::ORIGIN, tree_b, g, CGAL::parameters::vertex_point_map(vpm_b)); + loc = PMP::locate_with_AABB_tree(CGAL::ORIGIN, tree_b, g, CGAL::parameters::vertex_point_map(custom_vpm_3D)); assert(PMP::is_in_face(loc, g)); - // doesn't necessarily have to wrap with a P_to_P3 here, it'll do it internally + // Doesn't necessarily have to wrap with a P_to_P3: it can be done automatically internally loc = PMP::locate(CGAL::ORIGIN, g, CGAL::parameters::vertex_point_map(custom_vpm)); assert(PMP::is_in_face(loc, g)); // --------------------------------------------------------------------------- Ray_3 r3 = random_3D_ray >(tree_b, rnd); - loc = PMP::locate_with_AABB_tree(r3, tree_b, g, CGAL::parameters::vertex_point_map(vpm_b)); + loc = PMP::locate_with_AABB_tree(r3, tree_b, g, CGAL::parameters::vertex_point_map(custom_vpm_3D)); } }; -template -void test_locate(const G& g, CGAL::Random& rnd) +template +void test_locate(const G& g, + const VPM vpm, + CGAL::Random& rnd) { assert(num_vertices(g) != 0 && num_faces(g) != 0); - test_snappers(g); - test_constructions(g, rnd); - test_random_entities(g, rnd); - test_helpers(g, rnd); - test_predicates(g, rnd); - test_locate_in_face(g, rnd); + test_snappers(g); + test_constructions(g, vpm, rnd); + test_random_entities(g, rnd); + test_helpers(g, rnd); + test_predicates(g, rnd); + test_locate_in_face(g, vpm, rnd); // This test has slight syntax changes between 2D and 3D (e.g. testing ray_2 in 3D makes no sense) - Locate_with_AABB_tree_Tester< - CGAL::Ambient_dimension::Point>::value>()(g, rnd); + Locate_with_AABB_tree_Tester AABB_tester; + AABB_tester.test(g, vpm, rnd); +} + +template +void test_locate(const G& g, CGAL::Random& rnd) +{ + return test_locate(g, CGAL::get_const_property_map(boost::vertex_point, g), rnd); } template @@ -737,7 +744,7 @@ void test_2D_triangulation(const char* fname, CGAL::Random& rnd) std::cout << " (" << tr.number_of_vertices() << " vertices)..." << std::endl; std::cout << "Kernel: " << typeid(K()).name() << std::endl; - test_locate(tr, rnd); + test_locate(tr, rnd); } template @@ -759,16 +766,16 @@ void test_2D_surface_mesh(const char* fname, CGAL::Random& rnd) return; } - test_locate(tm, rnd); + test_locate(tm, rnd); } template -void test_3D_surface_mesh(const char* fname, CGAL::Random& rnd) +void test_surface_mesh_3D(const char* fname, CGAL::Random& rnd) { typedef typename K::Point_3 Point; typedef CGAL::Surface_mesh Mesh; - std::cout << "Testing Surface_mesh " << fname << "..." << std::endl; + std::cout << "Testing (3D) Surface_mesh " << fname << "..." << std::endl; std::cout << "Kernel: " << typeid(K()).name() << std::endl; std::ifstream input(fname); @@ -779,7 +786,42 @@ void test_3D_surface_mesh(const char* fname, CGAL::Random& rnd) return; } - test_locate(tm, rnd); + typedef typename boost::property_map::const_type VertexPointMap; + VertexPointMap vpm = CGAL::get_const_property_map(boost::vertex_point, tm); + + test_locate(tm, vpm, rnd); +} + +template +void test_surface_mesh_projection(const char* fname, CGAL::Random& rnd) +{ + typedef typename K::Point_3 Point; + typedef CGAL::Surface_mesh Mesh; + typedef typename K::Point_2 Projected_point; + + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + + std::cout << "Testing Projected Surface_mesh " << fname << "..." << std::endl; + std::cout << "Kernel: " << typeid(K()).name() << std::endl; + + std::ifstream input(fname); + Mesh tm; + if(!input || !(input >> tm)) + { + std::cerr << "Error: cannot read file."; + return; + } + + const auto& proj_vpm = tm.template add_property_map("P2", Projected_point()).first; + + for(vertex_descriptor v : vertices(tm)) + { + const Point& p = tm.point(v); + put(proj_vpm, v, Projected_point(p.x(), p.y())); + } + + test_locate(tm, proj_vpm, rnd); } template @@ -798,15 +840,16 @@ void test_polyhedron(const char* fname, CGAL::Random& rnd) return; } - test_locate(poly, rnd); + test_locate(poly, rnd); } template void test(CGAL::Random& rnd) { test_2D_triangulation("data/stair.xy", rnd); -// test_2D_surface_mesh("data/blobby_2D.off", rnd); // temporarily, until Surface_mesh's IO is "fixed" - test_3D_surface_mesh("data/mech-holes-shark.off", rnd); +// test_2D_surface_mesh("data/blobby_2D.off", rnd); // temporarily disabled, until Surface_mesh's IO is "fixed" + test_surface_mesh_3D("data/mech-holes-shark.off", rnd); + test_surface_mesh_projection("data/unit-grid.off", rnd); test_polyhedron("data-coref/elephant_split_2.off", rnd); } From d9328b1131604541baf338b74a4bd3c08aba8967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 8 Oct 2019 15:57:34 +0200 Subject: [PATCH 5/7] Data file for PMP Location tests --- .../data/unit-grid.off | 323 ++++++++++++++++++ 1 file changed, 323 insertions(+) create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data/unit-grid.off diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/unit-grid.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/unit-grid.off new file mode 100644 index 000000000000..22af0f9741fe --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/unit-grid.off @@ -0,0 +1,323 @@ +OFF +121 200 0 +0 0 0 +0.10000000000000001 0 0 +0.20000000000000001 0 0 +0.29999999999999999 0 0 +0.40000000000000002 0 0 +0.5 0 0 +0.59999999999999998 0 0 +0.69999999999999996 0 0 +0.80000000000000004 0 0 +0.90000000000000002 0 0 +1 0 0 +0 0.10000000000000001 0 +0.10000000000000001 0.10000000000000001 0 +0.20000000000000001 0.10000000000000001 0 +0.29999999999999999 0.10000000000000001 0 +0.40000000000000002 0.10000000000000001 0 +0.5 0.10000000000000001 0 +0.59999999999999998 0.10000000000000001 0 +0.69999999999999996 0.10000000000000001 0 +0.80000000000000004 0.10000000000000001 0 +0.90000000000000002 0.10000000000000001 0 +1 0.10000000000000001 0 +0 0.20000000000000001 0 +0.10000000000000001 0.20000000000000001 0 +0.20000000000000001 0.20000000000000001 0 +0.29999999999999999 0.20000000000000001 0 +0.40000000000000002 0.20000000000000001 0 +0.5 0.20000000000000001 0 +0.59999999999999998 0.20000000000000001 0 +0.69999999999999996 0.20000000000000001 0 +0.80000000000000004 0.20000000000000001 0 +0.90000000000000002 0.20000000000000001 0 +1 0.20000000000000001 0 +0 0.29999999999999999 0 +0.10000000000000001 0.29999999999999999 0 +0.20000000000000001 0.29999999999999999 0 +0.29999999999999999 0.29999999999999999 0 +0.40000000000000002 0.29999999999999999 0 +0.5 0.29999999999999999 0 +0.59999999999999998 0.29999999999999999 0 +0.69999999999999996 0.29999999999999999 0 +0.80000000000000004 0.29999999999999999 0 +0.90000000000000002 0.29999999999999999 0 +1 0.29999999999999999 0 +0 0.40000000000000002 0 +0.10000000000000001 0.40000000000000002 0 +0.20000000000000001 0.40000000000000002 0 +0.29999999999999999 0.40000000000000002 0 +0.40000000000000002 0.40000000000000002 0 +0.5 0.40000000000000002 0 +0.59999999999999998 0.40000000000000002 0 +0.69999999999999996 0.40000000000000002 0 +0.80000000000000004 0.40000000000000002 0 +0.90000000000000002 0.40000000000000002 0 +1 0.40000000000000002 0 +0 0.5 0 +0.10000000000000001 0.5 0 +0.20000000000000001 0.5 0 +0.29999999999999999 0.5 0 +0.40000000000000002 0.5 0 +0.5 0.5 0 +0.59999999999999998 0.5 0 +0.69999999999999996 0.5 0 +0.80000000000000004 0.5 0 +0.90000000000000002 0.5 0 +1 0.5 0 +0 0.59999999999999998 0 +0.10000000000000001 0.59999999999999998 0 +0.20000000000000001 0.59999999999999998 0 +0.29999999999999999 0.59999999999999998 0 +0.40000000000000002 0.59999999999999998 0 +0.5 0.59999999999999998 0 +0.59999999999999998 0.59999999999999998 0 +0.69999999999999996 0.59999999999999998 0 +0.80000000000000004 0.59999999999999998 0 +0.90000000000000002 0.59999999999999998 0 +1 0.59999999999999998 0 +0 0.69999999999999996 0 +0.10000000000000001 0.69999999999999996 0 +0.20000000000000001 0.69999999999999996 0 +0.29999999999999999 0.69999999999999996 0 +0.40000000000000002 0.69999999999999996 0 +0.5 0.69999999999999996 0 +0.59999999999999998 0.69999999999999996 0 +0.69999999999999996 0.69999999999999996 0 +0.80000000000000004 0.69999999999999996 0 +0.90000000000000002 0.69999999999999996 0 +1 0.69999999999999996 0 +0 0.80000000000000004 0 +0.10000000000000001 0.80000000000000004 0 +0.20000000000000001 0.80000000000000004 0 +0.29999999999999999 0.80000000000000004 0 +0.40000000000000002 0.80000000000000004 0 +0.5 0.80000000000000004 0 +0.59999999999999998 0.80000000000000004 0 +0.69999999999999996 0.80000000000000004 0 +0.80000000000000004 0.80000000000000004 0 +0.90000000000000002 0.80000000000000004 0 +1 0.80000000000000004 0 +0 0.90000000000000002 0 +0.10000000000000001 0.90000000000000002 0 +0.20000000000000001 0.90000000000000002 0 +0.29999999999999999 0.90000000000000002 0 +0.40000000000000002 0.90000000000000002 0 +0.5 0.90000000000000002 0 +0.59999999999999998 0.90000000000000002 0 +0.69999999999999996 0.90000000000000002 0 +0.80000000000000004 0.90000000000000002 0 +0.90000000000000002 0.90000000000000002 0 +1 0.90000000000000002 0 +0 1 0 +0.10000000000000001 1 0 +0.20000000000000001 1 0 +0.29999999999999999 1 0 +0.40000000000000002 1 0 +0.5 1 0 +0.59999999999999998 1 0 +0.69999999999999996 1 0 +0.80000000000000004 1 0 +0.90000000000000002 1 0 +1 1 0 +3 0 1 11 +3 1 12 11 +3 11 12 22 +3 12 23 22 +3 22 23 33 +3 23 34 33 +3 33 34 44 +3 34 45 44 +3 44 45 55 +3 45 56 55 +3 55 56 66 +3 56 67 66 +3 66 67 77 +3 67 78 77 +3 77 78 88 +3 78 89 88 +3 88 89 99 +3 89 100 99 +3 99 100 110 +3 100 111 110 +3 1 2 12 +3 2 13 12 +3 12 13 23 +3 13 24 23 +3 23 24 34 +3 24 35 34 +3 34 35 45 +3 35 46 45 +3 45 46 56 +3 46 57 56 +3 56 57 67 +3 57 68 67 +3 67 68 78 +3 68 79 78 +3 78 79 89 +3 79 90 89 +3 89 90 100 +3 90 101 100 +3 100 101 111 +3 101 112 111 +3 2 3 13 +3 3 14 13 +3 13 14 24 +3 14 25 24 +3 24 25 35 +3 25 36 35 +3 35 36 46 +3 36 47 46 +3 46 47 57 +3 47 58 57 +3 57 58 68 +3 58 69 68 +3 68 69 79 +3 69 80 79 +3 79 80 90 +3 80 91 90 +3 90 91 101 +3 91 102 101 +3 101 102 112 +3 102 113 112 +3 3 4 14 +3 4 15 14 +3 14 15 25 +3 15 26 25 +3 25 26 36 +3 26 37 36 +3 36 37 47 +3 37 48 47 +3 47 48 58 +3 48 59 58 +3 58 59 69 +3 59 70 69 +3 69 70 80 +3 70 81 80 +3 80 81 91 +3 81 92 91 +3 91 92 102 +3 92 103 102 +3 102 103 113 +3 103 114 113 +3 4 5 15 +3 5 16 15 +3 15 16 26 +3 16 27 26 +3 26 27 37 +3 27 38 37 +3 37 38 48 +3 38 49 48 +3 48 49 59 +3 49 60 59 +3 59 60 70 +3 60 71 70 +3 70 71 81 +3 71 82 81 +3 81 82 92 +3 82 93 92 +3 92 93 103 +3 93 104 103 +3 103 104 114 +3 104 115 114 +3 5 6 16 +3 6 17 16 +3 16 17 27 +3 17 28 27 +3 27 28 38 +3 28 39 38 +3 38 39 49 +3 39 50 49 +3 49 50 60 +3 50 61 60 +3 60 61 71 +3 61 72 71 +3 71 72 82 +3 72 83 82 +3 82 83 93 +3 83 94 93 +3 93 94 104 +3 94 105 104 +3 104 105 115 +3 105 116 115 +3 6 7 17 +3 7 18 17 +3 17 18 28 +3 18 29 28 +3 28 29 39 +3 29 40 39 +3 39 40 50 +3 40 51 50 +3 50 51 61 +3 51 62 61 +3 61 62 72 +3 62 73 72 +3 72 73 83 +3 73 84 83 +3 83 84 94 +3 84 95 94 +3 94 95 105 +3 95 106 105 +3 105 106 116 +3 106 117 116 +3 7 8 18 +3 8 19 18 +3 18 19 29 +3 19 30 29 +3 29 30 40 +3 30 41 40 +3 40 41 51 +3 41 52 51 +3 51 52 62 +3 52 63 62 +3 62 63 73 +3 63 74 73 +3 73 74 84 +3 74 85 84 +3 84 85 95 +3 85 96 95 +3 95 96 106 +3 96 107 106 +3 106 107 117 +3 107 118 117 +3 8 9 19 +3 9 20 19 +3 19 20 30 +3 20 31 30 +3 30 31 41 +3 31 42 41 +3 41 42 52 +3 42 53 52 +3 52 53 63 +3 53 64 63 +3 63 64 74 +3 64 75 74 +3 74 75 85 +3 75 86 85 +3 85 86 96 +3 86 97 96 +3 96 97 107 +3 97 108 107 +3 107 108 118 +3 108 119 118 +3 9 10 20 +3 10 21 20 +3 20 21 31 +3 21 32 31 +3 31 32 42 +3 32 43 42 +3 42 43 53 +3 43 54 53 +3 53 54 64 +3 54 65 64 +3 64 65 75 +3 65 76 75 +3 75 76 86 +3 76 87 86 +3 86 87 97 +3 87 98 97 +3 97 98 108 +3 98 109 108 +3 108 109 119 +3 109 120 119 From 3801a35eb3272d710b1396d22dce47dcd6411e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 8 Oct 2019 16:03:51 +0200 Subject: [PATCH 6/7] Tiny fixes --- .../include/CGAL/Polygon_mesh_processing/locate.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h index f82daed743b1..5616b9e3c7f0 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h @@ -427,7 +427,7 @@ random_location_on_halfedge(typename boost::graph_traits::halfedge std::array coordinates; coordinates[h_id] = t; - coordinates[(h_id+1)%3] = FT(1-t); + coordinates[(h_id+1)%3] = FT(1)-t; coordinates[(h_id+2)%3] = FT(0); return std::make_pair(face(hd, tm), coordinates); @@ -1208,7 +1208,7 @@ locate_in_adjacent_face(const std::pair::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::face_descriptor face_descriptor; + CGAL_assertion_code(typedef typename boost::graph_traits::face_descriptor face_descriptor;) if(loc.first == fd) return loc; From 77e0937fb29ef49e97f851c06538d277713f5250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 15 Oct 2019 13:13:16 +0200 Subject: [PATCH 7/7] Uniformize tparam formulation --- .../CGAL/Polygon_mesh_processing/locate.h | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h index 5616b9e3c7f0..688599e16bef 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h @@ -408,7 +408,7 @@ barycentric_coordinates(const Point& p, const Point& q, const Point& r, const Po /// and `0` for respetively the source and target of `hd`, and the third vertex. /// /// \tparam FT must be a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param hd a halfedge of `tm` /// \param tm a triangulated surface mesh @@ -443,7 +443,7 @@ random_location_on_halfedge(typename boost::graph_traits::halfedge /// `1-u-v` for respectively the source and target of `halfedge(fd, tm)`, and the third point. /// /// \tparam FT must be a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param fd a face of `tm` /// \param tm a triangulated surface mesh @@ -475,7 +475,7 @@ random_location_on_face(typename boost::graph_traits::face_descrip /// are thus all positive. Note that all faces have the same probability to be chosen. /// /// \tparam FT must be a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param tm a triangulated surface mesh /// \param rnd optional random number generator @@ -510,7 +510,7 @@ random_location_on_mesh(const TriangleMesh& tm, /// `fd` (equal to `loc.first`). /// /// \tparam FT must be a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` /// \param tm a triangulated surface mesh @@ -570,7 +570,7 @@ get_descriptor_from_location(const std::pair::face /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` /// \param vd a vertex of `tm` @@ -702,8 +702,8 @@ is_on_vertex(const std::pair::face_de /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` /// \param hd a halfedge of `tm` @@ -751,8 +751,8 @@ is_on_halfedge(const std::pair::face_ /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param bar an array of barycentric coordinates /// \param tm a triangulated surface mesh @@ -791,8 +791,8 @@ is_in_face(const std::array& bar, /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` /// \param tm a triangulated surface mesh @@ -823,8 +823,8 @@ is_in_face(const std::pair::face_desc /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` /// \param tm a triangulated surface mesh @@ -864,8 +864,8 @@ is_on_face_border(const std::pair::fa /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` /// \param tm a triangulated surface mesh @@ -933,8 +933,8 @@ is_on_mesh_border(const std::pair::fa /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param vd a vertex of `tm` /// \param tm a triangulated surface mesh @@ -995,8 +995,8 @@ locate_vertex(typename boost::graph_traits::vertex_descriptor vd, /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param vd a vertex of `tm` and a vertex of the face `fd` /// \param fd a face of `tm` @@ -1034,8 +1034,8 @@ locate_vertex(const typename boost::graph_traits::vertex_descripto /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param hd a halfedge of `tm` /// \param t the parametric distance of the desired point along `hd` @@ -1074,7 +1074,7 @@ locate_on_halfedge(const typename boost::graph_traits::halfedge_de /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// /// \param query a point, whose type is equal to the value type of the vertex point property map @@ -1186,8 +1186,8 @@ locate_in_face(const typename internal::Location_traits::Point& qu /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param loc the first location, with `loc.first` being a face of `tm` /// \param fd the second face, adjacent to `loc.first` @@ -1562,8 +1562,8 @@ void build_AABB_tree(const TriangleMesh& tm, /// `locate_with_AABB_tree()` that takes as parameter an AABB tree, instead of calling `locate()` /// multiple times, which will build a new AABB tree on every call. /// -/// \tparam TriangleMesh a model of `FaceListGraph` -/// \tparam Point3VPM a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` +/// \tparam TriangleMesh must be a model of `FaceListGraph` +/// \tparam Point3VPM must be a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` /// as key type and the \cgal 3D point type (your traits' `%Point_3`) as value type. /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// @@ -1624,8 +1624,8 @@ void build_AABB_tree(const TriangleMesh& tm, AABB_tree& outTree) /// is a 2D triangulation, or a CGAL::Surface_mesh >), as long as an appropriate /// vertex point property map is passed in the AABB tree, which will convert from 2D to 3D. /// -/// \tparam TriangleMesh a model of `FaceListGraph` -/// \tparam Point3VPM a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` +/// \tparam TriangleMesh must be a model of `FaceListGraph` +/// \tparam Point3VPM must be a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` /// as key type and the \cgal 3D point type (your traits' `%Point_3`) as value type. /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// @@ -1723,7 +1723,7 @@ locate_with_AABB_tree(const typename internal::Location_traits::Po /// to call this function more than once, first use `build_AABB_tree()` to create a /// an AABB tree that you can store and use the function `locate_with_AABB_tree()`. /// -/// \tparam TriangleMesh a model of `FaceListGraph`. +/// \tparam TriangleMesh must be a model of `FaceListGraph`. /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// /// \param p the point to locate on the input triangulated surface mesh @@ -1806,8 +1806,8 @@ locate(const typename property_map_value::t /// /// If the ray does not intersect the mesh, a default constructed location is returned. /// -/// \tparam TriangleMesh a model of `FaceListGraph`. -/// \tparam Point3VPM a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` +/// \tparam TriangleMesh must be a model of `FaceListGraph`. +/// \tparam Point3VPM must be a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` /// as key type and the \cgal 3D point type (your traits' `%Point_3`) as value type. /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// @@ -1944,7 +1944,7 @@ locate_with_AABB_tree(const typename internal::Location_traits::Ra /// copy of the `AABB_tree`, and use the overloads of this function /// that accept a reference to an AABB tree as input. /// -/// \tparam TriangleMesh a model of `FaceListGraph`. +/// \tparam TriangleMesh must be a model of `FaceListGraph`. /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// /// \param ray a ray to intersect with the input triangulated surface mesh