From 92c479921b9234cfeb737a57031aba01397c8cc2 Mon Sep 17 00:00:00 2001 From: Lingjie Zhu Date: Mon, 24 Jul 2017 23:29:32 +0800 Subject: [PATCH] add default L21 metric API --- .../include/CGAL/vsa_mesh_approximation.h | 229 ++++++++++++++++++ 1 file changed, 229 insertions(+) diff --git a/Surface_mesh_approximation/include/CGAL/vsa_mesh_approximation.h b/Surface_mesh_approximation/include/CGAL/vsa_mesh_approximation.h index bb7a5cdd609..ca56c94e3e6 100644 --- a/Surface_mesh_approximation/include/CGAL/vsa_mesh_approximation.h +++ b/Surface_mesh_approximation/include/CGAL/vsa_mesh_approximation.h @@ -2,7 +2,9 @@ #define CGAL_SURFACE_MESH_APPROXIMATION_VSA_MESH_APPROXIMATION_H #include +#include #include +#include namespace CGAL { @@ -262,6 +264,233 @@ void vsa_approximate_and_extract( BOOST_FOREACH(const typename VSA_mesh_extraction::Anchor &a, extractor.collect_anchors()) pos.push_back(a.pos); } + +/*! + * \ingroup PkgTSMA + * @brief Using the VSA algorithm to approximate a triangle mesh. + * This function approximate the input mesh by fitting it with proxies. + * Facet proxy index output only. + * Use default L21 metric. + * + * @tparam TriangleMesh model of `FaceGraph`. + * @tparam FacetProxyMap a property map containing the approximated facet patch id, + and `boost::graph_traits::%face_descriptor` as key type, + std::size_t as value type + + * @param tm a triangle mesh + * @param[out] f_proxy_pmap facet proxy patch id property map + * @param init select seed initialization + * @param number_of_segments target number of approximation patches + * @param number_of_iterations number of fitting iterations + */ +template +void vsa_approximate( + const TriangleMesh &tm, + FacetProxyMap f_proxy_pmap, + const int init, + const std::size_t number_of_segments, + const std::size_t number_of_iterations) { + // CGAL_precondition(is_pure_triangle(tm)); + + typedef typename TriangleMesh::Traits GeomTraits; + typedef typename GeomTraits::FT FT; + typedef typename GeomTraits::Vector_3 Vector_3; + typedef typename GeomTraits::Point_3 Point_3; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef boost::associative_property_map > FacetNormalMap; + typedef boost::associative_property_map > FacetAreaMap; + typedef boost::property_map::type VertexPointMap; + + typedef CGAL::PlaneProxy PlaneProxy; + typedef CGAL::L21Metric L21Metric; + typedef CGAL::L21ProxyFitting L21ProxyFitting; + typedef CGAL::PlaneFitting PlaneFitting; + typedef CGAL::L21ApproximationTrait L21ApproximationTrait; + + VertexPointMap point_pmap = get(boost::vertex_point, const_cast(tm)); + // construct facet normal & area map + std::map facet_normals; + std::map facet_areas; + BOOST_FOREACH(face_descriptor f, faces(tm)) { + const halfedge_descriptor he = halfedge(f, tm); + const Point_3 p0 = point_pmap[source(he, tm)]; + const Point_3 p1 = point_pmap[target(he, tm)]; + const Point_3 p2 = point_pmap[target(next(he, tm), tm)]; + Vector_3 normal = CGAL::unit_normal(p0, p1, p2); + facet_normals.insert(std::pair(f, normal)); + FT area(std::sqrt(CGAL::to_double(CGAL::squared_area(p0, p1, p2)))); + facet_areas.insert(std::pair(f, area)); + } + FacetNormalMap normal_pmap(facet_normals); + FacetAreaMap area_pmap(facet_areas); + + vsa_approximate(tm, + f_proxy_pmap, + L21ApproximationTrait(tm, point_pmap, normal_pmap, area_pmap), + init, + number_of_segments, + number_of_iterations); +} + +/*! + * \ingroup PkgTSMA + * @brief Using the VSA algorithm to extract the approximated surface mesh. + * This function approximate the input triangulated mesh by fitting it with proxies. + * Approximated triangle mesh output only. + * Use default L21 metric. + * + * @tparam TriangleMesh model of `FaceGraph`. + * @tparam AnchorIndexContainer a container of approximated indexed triangle soup + * @tparam AnchorPositionContainer a container of extracted anchor position + + * @param tm a triangle mesh + * @param[out] tris approximation indexed triangle soup + * @param[out] pos anchor position container + * @param init select seed initialization + * @param number_of_segments target number of approximation patches + * @param number_of_iterations number of fitting iterations + */ +template +void vsa_extract( + const TriangleMesh &tm, + AnchorIndexContainer &tris, + AnchorPositionContainer &pos, + const int init, + const std::size_t number_of_segments, + const std::size_t number_of_iterations) { + // CGAL_precondition(is_pure_triangle(tm)); + + typedef typename TriangleMesh::Traits GeomTraits; + typedef typename GeomTraits::FT FT; + typedef typename GeomTraits::Vector_3 Vector_3; + typedef typename GeomTraits::Point_3 Point_3; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef boost::associative_property_map > FacetNormalMap; + typedef boost::associative_property_map > FacetAreaMap; + typedef boost::property_map::type VertexPointMap; + + typedef CGAL::PlaneProxy PlaneProxy; + typedef CGAL::L21Metric L21Metric; + typedef CGAL::L21ProxyFitting L21ProxyFitting; + typedef CGAL::PlaneFitting PlaneFitting; + typedef CGAL::L21ApproximationTrait L21ApproximationTrait; + + VertexPointMap point_pmap = get(boost::vertex_point, const_cast(tm)); + // construct facet normal & area map + std::map facet_normals; + std::map facet_areas; + BOOST_FOREACH(face_descriptor f, faces(tm)) { + const halfedge_descriptor he = halfedge(f, tm); + const Point_3 p0 = point_pmap[source(he, tm)]; + const Point_3 p1 = point_pmap[target(he, tm)]; + const Point_3 p2 = point_pmap[target(next(he, tm), tm)]; + Vector_3 normal = CGAL::unit_normal(p0, p1, p2); + facet_normals.insert(std::pair(f, normal)); + FT area(std::sqrt(CGAL::to_double(CGAL::squared_area(p0, p1, p2)))); + facet_areas.insert(std::pair(f, area)); + } + FacetNormalMap normal_pmap(facet_normals); + FacetAreaMap area_pmap(facet_areas); + + typedef typename boost::associative_property_map > FacetProxyMap; + std::map facet_proxy_map; + BOOST_FOREACH(face_descriptor f, faces(tm)) + facet_proxy_map.insert(std::pair(f, 0)); + FacetProxyMap f_proxy_pmap(facet_proxy_map); + + vsa_extract(tm, + tris, + pos, + L21ApproximationTrait(tm, point_pmap, normal_pmap, area_pmap), + init, + number_of_segments, + number_of_iterations); +} + +/*! + * \ingroup PkgTSMA + * @brief Triangle mesh variational shape approximation. + * This function approximate the input triangulated mesh by fitting it with proxies. + * Facet proxy index and approximated triangle mesh output. + * Use default L21 metric. + * + * @tparam TriangleMesh model of `FaceGraph`. + * @tparam FacetProxyMap a property map containing the approximated facet patch id, + and `boost::graph_traits::%face_descriptor` as key type, + std::size_t as value type + * @tparam AnchorIndexContainer a container of approximated indexed triangle soup + * @tparam AnchorPositionContainer a container of extracted anchor position + + * @param tm a triangle mesh + * @param[out] f_proxy_pmap facet proxy patch id property map + * @param[out] tris approximation indexed triangle soup + * @param[out] pos anchor position container + * @param init select seed initialization + * @param number_of_segments target number of approximation patches + * @param number_of_iterations number of fitting iterations + */ +template +void vsa_approximate_and_extract( + const TriangleMesh &tm, + FacetProxyMap f_proxy_pmap, + AnchorIndexContainer &tris, + AnchorPositionContainer &pos, + const int init, + const std::size_t number_of_segments, + const std::size_t number_of_iterations) { + // CGAL_precondition(is_pure_triangle(tm)); + + typedef typename TriangleMesh::Traits GeomTraits; + typedef typename GeomTraits::FT FT; + typedef typename GeomTraits::Vector_3 Vector_3; + typedef typename GeomTraits::Point_3 Point_3; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef boost::associative_property_map > FacetNormalMap; + typedef boost::associative_property_map > FacetAreaMap; + typedef boost::property_map::type VertexPointMap; + + typedef CGAL::PlaneProxy PlaneProxy; + typedef CGAL::L21Metric L21Metric; + typedef CGAL::L21ProxyFitting L21ProxyFitting; + typedef CGAL::PlaneFitting PlaneFitting; + typedef CGAL::L21ApproximationTrait L21ApproximationTrait; + + VertexPointMap point_pmap = get(boost::vertex_point, const_cast(tm)); + // construct facet normal & area map + std::map facet_normals; + std::map facet_areas; + BOOST_FOREACH(face_descriptor f, faces(tm)) { + const halfedge_descriptor he = halfedge(f, tm); + const Point_3 p0 = point_pmap[source(he, tm)]; + const Point_3 p1 = point_pmap[target(he, tm)]; + const Point_3 p2 = point_pmap[target(next(he, tm), tm)]; + Vector_3 normal = CGAL::unit_normal(p0, p1, p2); + facet_normals.insert(std::pair(f, normal)); + FT area(std::sqrt(CGAL::to_double(CGAL::squared_area(p0, p1, p2)))); + facet_areas.insert(std::pair(f, area)); + } + FacetNormalMap normal_pmap(facet_normals); + FacetAreaMap area_pmap(facet_areas); + + L21ApproximationTrait app_trait(tm, point_pmap, normal_pmap, area_pmap); + vsa_approximate_and_extract(tm, + f_proxy_pmap, + tris, + pos, + app_trait, + init, + number_of_segments, + number_of_iterations); +} } // end namespace CGAL #endif // CGAL_SURFACE_MESH_APPROXIMATION_VSA_MESH_APPROXIMATION_H