From cb3393ccaa191def6a1e5c9e7f68797170d67f69 Mon Sep 17 00:00:00 2001 From: Lingjie Zhu Date: Mon, 3 Jul 2017 17:29:56 +0800 Subject: [PATCH] add comment --- .../internal/Surface_mesh_approximation/VSA.h | 214 ++++++++++++++---- 1 file changed, 164 insertions(+), 50 deletions(-) diff --git a/Surface_mesh_approximation/include/CGAL/internal/Surface_mesh_approximation/VSA.h b/Surface_mesh_approximation/include/CGAL/internal/Surface_mesh_approximation/VSA.h index d2f2550079c..52bb42cb9dc 100644 --- a/Surface_mesh_approximation/include/CGAL/internal/Surface_mesh_approximation/VSA.h +++ b/Surface_mesh_approximation/include/CGAL/internal/Surface_mesh_approximation/VSA.h @@ -26,19 +26,17 @@ namespace CGAL namespace internal { /** - * @brief Main entry point for VSA mesh approximation algorithm. - * - * blah blah... + * @brief Main class for Variational Shape Approximation algorithm. * * @tparam Polyhedron a CGAL polyhedron * @tparam GeomTraits a model of ApproximationGeomTraits */ template class VSA { + // type definitions private: typedef typename GeomTraits::FT FT; typedef typename GeomTraits::Point_3 Point; @@ -60,7 +58,6 @@ private: typedef typename boost::graph_traits::edge_descriptor edge_descriptor; typedef typename boost::graph_traits::edge_iterator edge_iterator; - //typedef boost::associative_property_map > FacetSegmentMap; typedef boost::associative_property_map > FacetNormalMap; typedef boost::associative_property_map > FacetAreaMap; typedef boost::associative_property_map > VertexStatusPMap; @@ -69,22 +66,26 @@ private: typedef std::vector ChordVector; typedef typename ChordVector::iterator ChordVectorIterator; + // The attached anchor index of a vertex. enum Vertex_status { - NO_ANCHOR = -1 // vertex v has no anchor attached + NO_ANCHOR = -1 // No anchor attached }; + // Halfedge status. enum Halfedge_status { - OFF_BORDER, // halfedge h is off proxy border - CANDIDATE, // halfedge h is on proxy border, waiting to be visited - ON_BORDER // halfedge h is on proxy border + OFF_BORDER, // In the inside of a region. + CANDIDATE, // On the region border, waiting to be visited. + ON_BORDER // On proxy border, already visited. }; public: + // The approximated plane proxy. struct PlaneProxy { Vector normal; face_descriptor seed; }; + // The facet candidate to be queued. struct FacetToIntegrate { face_descriptor f; std::size_t i; @@ -95,14 +96,8 @@ public: } }; - /*template >, - typename FacetAreaMap = boost::associative_property_map >>*/ - /*template */ + // The l21 metric, compute the fitting error from a facet to a plane proxy. struct L21Metric { - //L21Metric() {} - L21Metric(GeomTraits traits, const FacetNormalMap &normal_pmap, const FacetAreaMap &area_pmap) @@ -125,25 +120,26 @@ public: Construct_sum_of_vectors_3 sum_functor; }; - // Anchor + // The average positioned anchor attached to a vertex. struct Anchor { Anchor(const vertex_descriptor &vtx_, const Point &pos_) : vtx(vtx_), pos(pos_) {} - vertex_descriptor vtx; // The associated vertex - Point pos; // The position of the anchor + vertex_descriptor vtx; // The associated vertex. + Point pos; // The position of the anchor. }; - // Border + // The border cycle of a region. + // One region may have multiple border cycles. struct Border { Border(const halfedge_descriptor &h) : he_head(h), num_anchors(0) {} - halfedge_descriptor he_head; // The heading halfedge of the border - std::size_t num_anchors; // The number of anchors of the border + halfedge_descriptor he_head; // The heading halfedge of the border cylce. + std::size_t num_anchors; // The number of anchors on the border. }; -// member variables + // member variables private: const Polyhedron &mesh; const VertexPointPmap &vertex_point_pmap; @@ -155,40 +151,40 @@ private: Compute_scalar_product_3 scalar_product_functor; Compute_squared_area_3 area_functor; + // Proxy and its auxiliary information. std::vector proxies; - // proxy auxiliary information - std::vector proxies_center; // proxy center - std::vector proxies_area; // proxy area + std::vector proxies_center; // The proxy center. + std::vector proxies_area; // The proxy area. - // the lifetime of the container must encompass the use of the adaptor + // Mesh facet normal and area map. std::map facet_normals; FacetNormalMap normal_pmap; std::map facet_areas; FacetAreaMap area_pmap; + // Mesh vertex anchor map and halfedge status map. std::map vertex_status_map; VertexStatusPMap vertex_status_pmap; std::map halfedge_status_map; HalfedgeStatusPMap halfedge_status_pmap; - // All anchors + // All anchors. std::vector anchors; - // All borders, some regions may have multiple borders + // All borders cycles. std::vector borders; + // The error metric. L21Metric fit_error; - //L21Metric fit_error; - //L21Metric fit_error; - //boost::associative_property_map > seg_pmap; - //boost::property_map &seg_pmap; - -//member functions + //member functions public: /** + * Initialize and prepare for the approximation. * @pre @a polyhedron.is_pure_triangle() - * @param mesh `CGAL Polyhedron` on which other functions operate. + * @param _mesh `CGAL Polyhedron` on which approximation operate. + * @param _vertex_point_map vertex point map of the input mesh. + * @param _traits geometric trait object. */ VSA(const Polyhedron &_mesh, VertexPointPmap _vertex_point_map, @@ -235,6 +231,13 @@ public: } } + /** + * Partitions the mesh into the designated number of regions, and stores them in @a seg_map. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param number_of_segments number of designated proxies + * @param number_of_iterations number of iterations when fitting the proxy + * @param[out] seg_map facet partition index + */ template void partition(const std::size_t number_of_segments, const std::size_t number_of_iterations, FacetSegmentMap &seg_pmap) { random_seed(number_of_segments); @@ -245,6 +248,13 @@ public: } } + /** + * Partitions the mesh incrementally into the designated number of regions, and stores them in @a seg_map. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param number_of_segments number of designated proxies + * @param number_of_iterations number of iterations when fitting the proxy + * @param[out] seg_map facet partition index + */ template void partition_incre(const std::size_t number_of_segments, const std::size_t number_of_iterations, FacetSegmentMap &seg_pmap) { // random_seed(number_of_segments); @@ -264,7 +274,12 @@ public: } } - // extract the approximated mesh from a partition + /** + * Extracts the approximated triangle mesh from a partition @a seg_pmap, and stores the triangles in @a tris. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param seg_map facet partition index + * @tris[out] indexed triangles + */ template void extract_mesh(FacetSegmentMap &seg_pmap, std::vector &tris) { compute_proxy_area(seg_pmap); @@ -277,10 +292,20 @@ public: pseudo_CDT(seg_pmap, tris); } + /** + * Collect the anchors. + * @return vector of anchors + */ std::vector collect_anchors() { return anchors; } + /** + * Collect the partition @a seg_pmap approximated borders. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param seg_map facet partition index + * @return anchor indexes of each border + */ template std::vector > collect_borders(const FacetSegmentMap &seg_pmap) { @@ -301,6 +326,10 @@ public: } private: + /** + * Random initialize proxies. + * @param initial_px number of proxies + */ void random_seed(const std::size_t initial_px) { proxies.clear(); std::size_t number_of_faces = num_faces(mesh); @@ -322,6 +351,11 @@ private: std::cerr << initial_px << ' ' << proxies.size() << std::endl; } + /** + * Propagates the proxy seed facets and floods the whole mesh to minimize the fitting error. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param[out] seg_map facet partition index + */ template void flooding(FacetSegmentMap &seg_pmap) { typedef std::multiset CandidateSet; @@ -365,6 +399,11 @@ private: } } + /** + * Calculates and updates the best fitting proxies of a given partition @a seg_pmap. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param seg_map facet partition index + */ template void fitting(FacetSegmentMap &seg_pmap) { // update normal @@ -411,7 +450,11 @@ private: } } - // insert proxy at the facet with the maximum fitting error in the proxy with maximum error + /** + * Inserts a proxy of a given partition @a seg_pmap at the furthest facet of the region with the maximum fitting error. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param seg_map facet partition index + */ template void insert_proxy(FacetSegmentMap &seg_pmap) { std::vector px_error(proxies.size(), FT(0.0)); @@ -445,6 +488,11 @@ private: proxies.push_back(new_px); } + /** + * Finds the anchors of a given partition @a seg_pmap. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param seg_map facet partition index + */ template void find_anchors(FacetSegmentMap &seg_pmap) { anchors.clear(); @@ -469,6 +517,11 @@ private: } } + /** + * Finds and approximates the edges connecting the anchors of a given partition @a seg_pmap. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param seg_map facet partition index + */ template void find_edges(FacetSegmentMap &seg_pmap) { // tag all proxy border halfedges as candidate @@ -512,7 +565,11 @@ private: } } - // add anchors to the borders with only 2 anchors + /** + * Adds anchors to the border cycles with only 2 anchors of a given partition @a seg_pmap. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param seg_map facet partition index + */ template void add_anchors(const FacetSegmentMap &seg_pmap) { typedef typename std::vector::iterator BorderIterator; @@ -575,6 +632,12 @@ private: } } + /** + * Runs the pseudo Constrained Delaunay Triangulation at each region of a given partition @a seg_pmap, and stores the extracted indexed triangles in @a tris. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param seg_map facet partition index + * @param tris extracted tirangles, index of anchors + */ template void pseudo_CDT(const FacetSegmentMap &seg_pmap, std::vector &tris) { @@ -712,6 +775,11 @@ private: } } + /** + * Computes and updates the proxy centers of a given partition @a seg_pmap. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param seg_map facet partition index + */ template void compute_proxy_center(const FacetSegmentMap &seg_pmap) { proxies_center = std::vector(proxies.size()); @@ -737,6 +805,11 @@ private: } } + /** + * Computes and updates the proxy areas of a given partition @a seg_pmap. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param seg_map facet partition index + */ template void compute_proxy_area(const FacetSegmentMap &seg_pmap) { std::vector areas(proxies.size(), FT(0)); @@ -746,6 +819,11 @@ private: proxies_area.swap(areas); } + /** + * Tags all the region border halfedges of a given partition @a seg_pmap to CANDIDATE states. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param seg_map facet partition index + */ template void tag_halfedges_status(FacetSegmentMap &seg_pmap) { BOOST_FOREACH(halfedge_descriptor h, halfedges(mesh)) { @@ -758,7 +836,12 @@ private: } } - // walk along the proxy border to the first halfedge pointing to a vertex associated with an anchor + /** + * Walks along the region border to the first halfedge pointing to a vertex associated with an anchor of a given partition @a seg_pmap. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param[in/out] he_start region border halfedge + * @param seg_map facet partition index + */ template void walk_to_first_anchor(halfedge_descriptor &he_start, const FacetSegmentMap &seg_pmap) { const halfedge_descriptor start_mark = he_start; @@ -770,8 +853,13 @@ private: } } - // starting at a border halfedge pointing to a vertex associated with an anchor - // walk along the proxy border to the next anchor, which may be itself + /** + * Walks along the region border to the next anchor and records the path as @a chord of a given partition @a seg_pmap. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param[in/out] he_start starting region border halfedge pointing to a vertex associated with an anchor + * @param[out] chord recorded path chord + * @param seg_map facet partition index + */ template void walk_to_next_anchor( halfedge_descriptor &he_start, @@ -783,7 +871,12 @@ private: } while (!is_anchor_attached(he_start)); } - // walk to next border halfedge, the input halfedge must be a border halfedge + /** + * Walks to next border halfedge of a given partition @a seg_pmap. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param[in/out] he_start region border halfedge + * @param seg_map facet partition index + */ template void walk_to_next_border_halfedge(halfedge_descriptor &he_start, const FacetSegmentMap &seg_pmap) { const std::size_t px_idx = seg_pmap[face(he_start, mesh)]; @@ -795,8 +888,14 @@ private: } } - // subdivide a chord in range [chord_begin, chord_end) - // returns the number of anchors of the chord apart from the first one + /** + * Subdivides a chord recursively in range [@a chord_begin, @a chord_end) of a given partition @a seg_pmap. + * @tparam FacetSegmentMap `WritablePropertyMap` with `boost::graph_traits::face_handle` as key and `std::size_t` as value type + * @param chord_begin begin iterator of the chord + * @param chord_end end iterator of the chord + * @param seg_map facet partition index + * @return the number of anchors of the chord apart from the first one + */ template std::size_t subdivide_chord( const ChordVectorIterator &chord_begin, @@ -878,13 +977,20 @@ private: return 1; } - // check if halfedge target vertex is attached with an anchor + /** + * Check if the target vertex of a halfedge is attached with an anchor. + * @param he halfedge + */ bool is_anchor_attached(const halfedge_descriptor &he) { return is_anchor_attached(target(he, mesh), vertex_status_pmap); } - // check if a vertex is attached with an anchor - // suppose anchor index starts with 0 + /** + * Check if a vertex is attached with an anchor. + * @tparam VertexAnchorIndexMap `WritablePropertyMap` with `boost::graph_traights::vertex_descriptor` as key and `std::size_t` as value type + * @param v vertex + * @param vertex_anchor_map vertex anchor index map + */ template bool is_anchor_attached( const typename boost::property_traits::key_type &v, @@ -892,7 +998,11 @@ private: return vertex_anchor_map[v] >= 0; } - // attach anchor to vertex + /** + * Attachs an anchor to the vertex, the position is area weighted average. + * @param vtx vertex + * @param px_set proxies around the vertex + */ void attach_anchor(const vertex_descriptor &vtx, const std::set &px_set) { // construct an anchor from vertex and the incident proxies FT avgx(0), avgy(0), avgz(0), sum_area(0); @@ -913,7 +1023,11 @@ private: anchors.push_back(Anchor(vtx, pos)); } - // attach anchor to the target vertex of the halfedge + /** + * Attachs an anchor to the target vertex of the halfedge. + * @param he halfedge + * @param px_set proxies around the target vertex + */ void attach_anchor(const halfedge_descriptor &he, const std::set &px_set) { vertex_descriptor vtx = target(he, mesh); attach_anchor(vtx, px_set);