From 3f87e9d4fbd0028e380d0392ea5e7519dab2d830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 20 Jan 2017 17:18:19 +0100 Subject: [PATCH] Updated SMP's doc to include Orbifold-Tutte Embeddings --- Documentation/doc/biblio/cgal_manual.bib | 10 +++ .../Concepts/Parameterizer_3.h | 1 + .../PackageDescription.txt | 3 + .../Surface_mesh_parameterization.txt | 36 ++++++++-- .../ARAP_parameterizer_3.h | 3 +- .../Barycentric_mapping_parameterizer_3.h | 2 +- .../Discrete_authalic_parameterizer_3.h | 1 + .../Discrete_conformal_map_parameterizer_3.h | 1 + .../Error_code.h | 2 + .../Fixed_border_parameterizer_3.h | 1 - .../LSCM_parameterizer_3.h | 7 +- .../Mean_value_coordinates_parameterizer_3.h | 1 + .../Orbifold_Tutte_parameterizer_3.h | 69 ++++++++++++++----- .../internal/orbifold_cone_helper.h | 18 ++++- 14 files changed, 127 insertions(+), 28 deletions(-) diff --git a/Documentation/doc/biblio/cgal_manual.bib b/Documentation/doc/biblio/cgal_manual.bib index bcf2b50f896..f1cad81d781 100644 --- a/Documentation/doc/biblio/cgal_manual.bib +++ b/Documentation/doc/biblio/cgal_manual.bib @@ -2761,6 +2761,16 @@ pages = "207--221" organization={IEEE} } +@article{aigerman2015orbifold, + title={Orbifold Tutte embeddings}, + author={Aigerman, Noam and Lipman, Yaron}, + journal={ACM Transactions on Graphics}, + volume={34}, + number={6}, + pages={190}, + year={2015} +} + % ---------------------------------------------------------------------------- % END OF BIBFILE % ---------------------------------------------------------------------------- diff --git a/Surface_mesh_parameterization/doc/Surface_mesh_parameterization/Concepts/Parameterizer_3.h b/Surface_mesh_parameterization/doc/Surface_mesh_parameterization/Concepts/Parameterizer_3.h index 7691097412b..b6aef0bbb80 100644 --- a/Surface_mesh_parameterization/doc/Surface_mesh_parameterization/Concepts/Parameterizer_3.h +++ b/Surface_mesh_parameterization/doc/Surface_mesh_parameterization/Concepts/Parameterizer_3.h @@ -20,6 +20,7 @@ Construction and destruction are undefined. \cgalHasModel `CGAL::Surface_mesh_parameterization::Discrete_conformal_map_parameterizer_3` \cgalHasModel `CGAL::Surface_mesh_parameterization::LSCM_parameterizer_3` \cgalHasModel `CGAL::Surface_mesh_parameterization::Mean_value_coordinates_parameterizer_3` +\cgalHasModel `CGAL::Surface_mesh_parameterization::Orbifold_Tutte_parameterizer_3` \cgalHasModel `CGAL::Surface_mesh_parameterization::Circular_border_parameterizer_3` \cgalHasModel `CGAL::Surface_mesh_parameterization::Square_border_parameterizer_3` \cgalHasModel `CGAL::Surface_mesh_parameterization::Two_vertices_parameterizer_3` diff --git a/Surface_mesh_parameterization/doc/Surface_mesh_parameterization/PackageDescription.txt b/Surface_mesh_parameterization/doc/Surface_mesh_parameterization/PackageDescription.txt index 75b57808e33..a71fc081194 100644 --- a/Surface_mesh_parameterization/doc/Surface_mesh_parameterization/PackageDescription.txt +++ b/Surface_mesh_parameterization/doc/Surface_mesh_parameterization/PackageDescription.txt @@ -104,6 +104,9 @@ The package performs the next checks: /// \defgroup PkgSurfaceParameterizationMainFunction Main Function /// \ingroup PkgSurfaceParameterization +/// \defgroup PkgSurfaceParameterizationEnums Enums +/// \ingroup PkgSurfaceParameterization + /// \defgroup PkgSurfaceParameterizationConcepts Concepts /// \ingroup PkgSurfaceParameterization diff --git a/Surface_mesh_parameterization/doc/Surface_mesh_parameterization/Surface_mesh_parameterization.txt b/Surface_mesh_parameterization/doc/Surface_mesh_parameterization/Surface_mesh_parameterization.txt index ea428228aa9..cd36dc299f5 100644 --- a/Surface_mesh_parameterization/doc/Surface_mesh_parameterization/Surface_mesh_parameterization.txt +++ b/Surface_mesh_parameterization/doc/Surface_mesh_parameterization/Surface_mesh_parameterization.txt @@ -272,7 +272,7 @@ Least squares conformal maps. `Surface_mesh_parameterization::ARAP_parameterizer_3` An as rigid as possible parameterization was introduced by Liu et al. \cgalCite{liu2008local}. -shape-preserving method based on an iterative energy minimization process. +It is a shape-preserving method based on an iterative energy minimization process. Each step alternates a local optimization technique to find the best local mapping and a global stitching technique equivalent to the resolution of a linear system to guarantee that the parameterized mesh is a triangulation. @@ -300,6 +300,27 @@ in the current version of this package. +\subsection Surface_mesh_parameterizationBorderless Borderless Parameterizations + +\subsubsection Surface_mesh_parameterizationOrbi Orbifold Tutte Embedding + +`Surface_mesh_parameterization::Orbifold_Tutte_parameterizer_3` + +Orbifold-Tutte Planar Embedding was introduced by Aigerman and Lipman \cgalCite{aigerman2015orbifold} +and is a generalization of Tutte’s embedding to other topologies, and in particular +spheres. The orbifold-Tutte embedding bijectively maps the original surface to +a canonical, topologically equivalent, two-dimensional flat surface called +a Euclidean orbifold. There are 17 Euclidean orbifolds, of which only the 4 sphere +orbifolds are implemented here. + +The orbifold-Tutte embedding yields a seamless, globally bijective parameterization that, +similarly to the classic Tutte embedding, only requires solving a sparse linear system +for its computation. + +The parameterization process intrinsically requires the uses of seams, but whose choice +have no influence on the result. The `Seam_mesh` structure (see also next Section) +is used for this purpose. + \section secCuttingaMesh Cutting a Mesh The surface parameterization methods proposed in this package only @@ -365,11 +386,18 @@ and is therefore non-singular (Gram theorem). +
  • Boundaryless + +
      + +
    • One-to-one mapping + +The Orbifold-Tutte embedding is guaranteed to exist and to be computable +via a sparse linear system. +
    - - - + \section Surface_mesh_parameterizationExtendingthe Implementation History diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/ARAP_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/ARAP_parameterizer_3.h index 7a9f9710f65..841b418281d 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/ARAP_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/ARAP_parameterizer_3.h @@ -111,7 +111,8 @@ namespace Surface_mesh_parameterization { /// \sa `CGAL::Surface_mesh_parameterization::Discrete_conformal_map_parameterizer_3` /// \sa `CGAL::Surface_mesh_parameterization::LSCM_parameterizer_3` /// \sa `CGAL::Surface_mesh_parameterization::Mean_value_coordinates_parameterizer_3` - +/// \sa `CGAL::Surface_mesh_parameterization::Orbifold_Tutte_parameterizer_3` +/// template < class TriangleMesh, diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Barycentric_mapping_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Barycentric_mapping_parameterizer_3.h index 80ec2b31c9c..c339f1745b7 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Barycentric_mapping_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Barycentric_mapping_parameterizer_3.h @@ -66,8 +66,8 @@ namespace Surface_mesh_parameterization { \sa `CGAL::Surface_mesh_parameterization::Discrete_conformal_map_parameterizer_3` \sa `CGAL::Surface_mesh_parameterization::LSCM_parameterizer_3` \sa `CGAL::Surface_mesh_parameterization::Mean_value_coordinates_parameterizer_3` +\sa `CGAL::Surface_mesh_parameterization::Orbifold_Tutte_parameterizer_3` */ - template < class TriangleMesh, diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Discrete_authalic_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Discrete_authalic_parameterizer_3.h index d1900289ed1..fadd08d7010 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Discrete_authalic_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Discrete_authalic_parameterizer_3.h @@ -69,6 +69,7 @@ namespace Surface_mesh_parameterization { /// \sa `CGAL::Surface_mesh_parameterization::Discrete_conformal_map_parameterizer_3` /// \sa `CGAL::Surface_mesh_parameterization::LSCM_parameterizer_3` /// \sa `CGAL::Surface_mesh_parameterization::Mean_value_coordinates_parameterizer_3` +/// \sa `CGAL::Surface_mesh_parameterization::Orbifold_Tutte_parameterizer_3` /// template < diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Discrete_conformal_map_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Discrete_conformal_map_parameterizer_3.h index ab80115115c..b41797d982d 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Discrete_conformal_map_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Discrete_conformal_map_parameterizer_3.h @@ -69,6 +69,7 @@ namespace Surface_mesh_parameterization { /// \sa `CGAL::Surface_mesh_parameterization::Discrete_authalic_parameterizer_3` /// \sa `CGAL::Surface_mesh_parameterization::LSCM_parameterizer_3` /// \sa `CGAL::Surface_mesh_parameterization::Mean_value_coordinates_parameterizer_3` +/// \sa `CGAL::Surface_mesh_parameterization::Orbifold_Tutte_parameterizer_3` /// template < diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Error_code.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Error_code.h index 186424026c1..e3f52cfa19d 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Error_code.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Error_code.h @@ -27,6 +27,8 @@ namespace CGAL { namespace Surface_mesh_parameterization { +/// \ingroup PkgSurfaceParameterizationEnums +/// /// List of errors detected by this package enum Error_code { diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Fixed_border_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Fixed_border_parameterizer_3.h index bde4559f0d4..07413626f30 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Fixed_border_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Fixed_border_parameterizer_3.h @@ -83,7 +83,6 @@ namespace Surface_mesh_parameterization { /// \sa `CGAL::Surface_mesh_parameterization::Barycentric_mapping_parameterizer_3` /// \sa `CGAL::Surface_mesh_parameterization::Discrete_authalic_parameterizer_3` /// \sa `CGAL::Surface_mesh_parameterization::Discrete_conformal_map_parameterizer_3` -/// \sa `CGAL::Surface_mesh_parameterization::LSCM_parameterizer_3` /// \sa `CGAL::Surface_mesh_parameterization::Mean_value_coordinates_parameterizer_3` /// template diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/LSCM_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/LSCM_parameterizer_3.h index 781ca9493f2..86a01056fb1 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/LSCM_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/LSCM_parameterizer_3.h @@ -56,7 +56,7 @@ namespace Surface_mesh_parameterization { /// \ingroup PkgSurfaceParameterizationMethods /// /// The class `LSCM_parameterizer_3` implements the -/// *Least Squares Conformal Maps (LSCM)* parameterization \cgalCite{cgal:lprm-lscm-02}. +/// *Least Squares Conformal Maps (LSCM)* parameterization \cgalCite{cgal:lprm-lscm-02}. /// /// This is a conformal parameterization, i.e. it attempts to preserve angles. /// @@ -74,13 +74,14 @@ namespace Surface_mesh_parameterization { /// Note: We may use a symmetric definite positive solver because LSCM /// solves the system in the least squares sense. /// -/// \sa `CGAL::Surface_mesh_parameterization::Fixed_border_parameterizer_3` +/// \sa `CGAL::Surface_mesh_parameterization::Two_vertices_parameterizer_3` /// \sa `CGAL::Surface_mesh_parameterization::ARAP_parameterizer_3` /// \sa `CGAL::Surface_mesh_parameterization::Barycentric_mapping_parameterizer_3` /// \sa `CGAL::Surface_mesh_parameterization::Discrete_authalic_parameterizer_3` /// \sa `CGAL::Surface_mesh_parameterization::Discrete_conformal_map_parameterizer_3` /// \sa `CGAL::Surface_mesh_parameterization::Mean_value_coordinates_parameterizer_3` - +/// \sa `CGAL::Surface_mesh_parameterization::Orbifold_Tutte_parameterizer_3` +/// template < class TriangleMesh, diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Mean_value_coordinates_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Mean_value_coordinates_parameterizer_3.h index 798f95558ad..ae9d6401550 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Mean_value_coordinates_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Mean_value_coordinates_parameterizer_3.h @@ -69,6 +69,7 @@ namespace Surface_mesh_parameterization { /// \sa `CGAL::Surface_mesh_parameterization::Discrete_authalic_parameterizer_3` /// \sa `CGAL::Surface_mesh_parameterization::Discrete_conformal_map_parameterizer_3` /// \sa `CGAL::Surface_mesh_parameterization::LSCM_parameterizer_3` +/// \sa `CGAL::Surface_mesh_parameterization::Orbifold_Tutte_parameterizer_3` /// template < diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Orbifold_Tutte_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Orbifold_Tutte_parameterizer_3.h index 8868d4f6be7..fd9abeb0435 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Orbifold_Tutte_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Orbifold_Tutte_parameterizer_3.h @@ -57,8 +57,6 @@ /// \file Orbifold_Tutte_parameterizer_3.h -#define CGAL_SMP_OUTPUT_ORBIFOLD_MATRICES - // @todo checks that cones are different, are on seams, seam is one connected // component // @todo Should the order of cones provided in entry matter ? Map the first cone @@ -68,12 +66,40 @@ namespace CGAL { namespace Surface_mesh_parameterization { +/// \ingroup PkgSurfaceParameterizationEnums +/// +/// Weight type used in the parameterization computation. +/// +/// MVC weights are guaranteed to generate positive edge weights, and the parameterization +/// is guaranteed to be injective. +/// +/// In case the cotangent weights are used, the orbifold-Tutte embedding globally +/// minimizes the Dirichlet energy and approximates conformal mappings. enum Weight_type { Cotangent = 0, Mean_value }; +/// \ingroup PkgSurfaceParameterizationMethods +/// +/// The class `Orbifold_Tutte_parameterizer_3` implements Orbifold Tutte Planar +/// Embeddings \cgalCite{aigerman2015orbifold}. +/// +/// This is a borderless parameterization. A one-to-one mapping is guaranteed. +/// +/// \cgalModels `Parameterizer_3` +/// +/// \tparam SeamMesh must be a `Seam_mesh`, with underlying mesh any model of `FaceGraph` +/// \tparam SparseLinearAlgebraTraits_d Traits class to solve a sparse linear system.
    +/// +/// \sa `CGAL::Surface_mesh_parameterization::ARAP_parameterizer_3` +/// \sa `CGAL::Surface_mesh_parameterization::Barycentric_mapping_parameterizer_3` +/// \sa `CGAL::Surface_mesh_parameterization::Discrete_authalic_parameterizer_3` +/// \sa `CGAL::Surface_mesh_parameterization::Discrete_conformal_map_parameterizer_3` +/// \sa `CGAL::Surface_mesh_parameterization::LSCM_parameterizer_3` +/// \sa `CGAL::Surface_mesh_parameterization::Mean_value_coordinates_parameterizer_3` +/// template < typename SeamMesh, @@ -100,8 +126,8 @@ private: typedef typename Sparse_LA::Matrix Matrix; // Kernel subtypes - typedef typename internal::Kernel_traits::Kernel Kernel; - typedef typename internal::Kernel_traits::PPM PPM; + typedef typename internal::Kernel_traits::Kernel Kernel; + typedef typename internal::Kernel_traits::PPM PPM; typedef typename Kernel::FT NT; typedef typename Kernel::Vector_2 Vector_2; typedef typename Kernel::Vector_3 Vector_3; @@ -112,7 +138,7 @@ private: const Weight_type weight_type; private: - /// check input's correctness. + /// Check input's correctness. template Error_code check_cones(ConeMap cmap) const { @@ -203,6 +229,7 @@ private: ++id_r; // current line index in A is increased } + /// Add the constraints from a seam segment to the linear system. void constrain_seam_segment(const std::vector >& seam_segment, NT ang, int& current_line_id_in_A, Matrix& A, Vector& B) const @@ -427,6 +454,7 @@ private: } } + /// Compute the system weights using a Cotangent Laplacian. template void cotangent_laplacien(SeamMesh& mesh, VertexIndexMap vimap, @@ -594,22 +622,29 @@ private: } public: - /// Flattens the mesh to one of the orbifolds. In the end, the - /// position of each vertex is stored in the property map `uvmap`. + /// Compute a one-to-one mapping from a triangular 3D surface mesh + /// to a piece of the 2D space. + /// The mapping is piecewise linear (linear in each triangle). + /// The result is the (u,v) pair image of each vertex of the 3D surface. + /// + /// + /// \tparam VertexUVmap must be a model of `ReadWritePropertyMap` with + /// `boost::graph_traits::%vertex_descriptor` as key type and + /// %Point_2 (type deduced from `TriangleMesh` using `Kernel_traits`) + /// as value type. + /// \tparam VertexIndexMap must be a model of `ReadablePropertyMap` with + /// `boost::graph_traits::%vertex_descriptor` as key type and + /// a unique integer as value type. + /// \tparam VertexParameterizedMap must be a model of `ReadWritePropertyMap` with + /// `boost::graph_traits::%vertex_descriptor` as key type and + /// a Boolean as value type. /// /// \param mesh a model of the `FaceGraph` concept /// \param bhd a halfedge on the border of the seam mesh - /// \param cmap + /// \param cmap a mapping of 4 (or 6) `vertex_descriptor`s that are cones + /// to their respective `Cone_type`. /// \param uvmap an instanciation of the class `VertexUVmap`. /// \param vimap an instanciation of the class `VertexIndexMap`. - /// \param orb the type of orbifold mapping - /// \param convexBoundary - omitted or false for free boundary, of one of - /// the 4 sphere orbifolds as specified in the constructor; true - /// for the classic Tutte embedding with fixed boundary into a disk; - /// 'square' for "classic" Tutte on a square with prefixed boundary - /// map; 'freesquare' for the square disk orbifold; 'freetri' for - /// the triangle disk orbifold. - /// \param wt weight type (cotan weights or MVC weights). /// /// \pre cones and seams must be valid. template #include +/// \file Orbifold_cone_helper.h + namespace CGAL { namespace Surface_mesh_parameterization { +/// \ingroup PkgSurfaceParameterizationEnums +/// +/// The types of cones used in Orbifold Tutte parameterization. +/// +/// `Unique_cones` are found at the beginning and the end of the seam. All other +/// cones are duplicated in the sense that when the seam is `opened`, the vertex +/// is duplicated at two different positions. enum Cone_type { First_unique_cone = 0, @@ -48,6 +57,9 @@ enum Cone_type Duplicated_cone }; +/// \ingroup PkgSurfaceParameterizationEnums +/// +/// The four Orbifold types available in the Orbifold Tutte parameterization. enum Orbifold_type { Square = 0, @@ -56,6 +68,9 @@ enum Orbifold_type Parallelogram }; +/// Get message corresponding to an error code +/// \param orb_type The integer value in the enum +/// \return The string describing the Orbifold type const char* get_orbifold_type(int orb_type) { // Messages corresponding to Error_code list above. Must be kept in sync! @@ -94,10 +109,10 @@ Point_container get_cones_parameterized_coordinates(const Orbifold_type orb_type return tcoords; } -/// Angles are minus as we go around the seam border in a counterclockwise manner template NT_container get_angles_at_cones(const Orbifold_type orb_type) { + // Note that angles are minus as we go around the seam border in a counterclockwise manner NT_container angs; if(orb_type == Square) { angs.push_back(4.); @@ -183,6 +198,7 @@ void find_start_cone(const ConeMap& cmap, CGAL_postcondition(false); } +/// Check the validity of the input cones in the `Seam_mesh` mesh. template