From c746425f8ccce7abe3e073bb9bf4fa3fef9f994e Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 19 Nov 2015 14:22:03 +0100 Subject: [PATCH] Authalic parametrization works with a Surface_mesh with border --- BGL/examples/BGL_surface_mesh/seam_mesh.cpp | 2 + BGL/include/CGAL/boost/graph/Seam_mesh.h | 5 + .../CGAL/boost/graph/graph_traits_Seam_mesh.h | 2 +- .../CGAL/boost/graph/properties_Seam_mesh.h | 58 +++ .../CMakeLists.txt | 1 + .../CGAL/Circular_border_parameterizer_3.h | 347 +++++++++--------- .../CGAL/Discrete_authalic_parameterizer_3.h | 19 +- .../CGAL/Fixed_border_parameterizer_3.h | 316 ++++++++-------- .../include/CGAL/Parameterizer_traits_3.h | 20 +- .../include/CGAL/parameterize.h | 9 +- 10 files changed, 430 insertions(+), 349 deletions(-) create mode 100644 BGL/include/CGAL/boost/graph/properties_Seam_mesh.h diff --git a/BGL/examples/BGL_surface_mesh/seam_mesh.cpp b/BGL/examples/BGL_surface_mesh/seam_mesh.cpp index 742120918e8..f274de43ab1 100644 --- a/BGL/examples/BGL_surface_mesh/seam_mesh.cpp +++ b/BGL/examples/BGL_surface_mesh/seam_mesh.cpp @@ -85,6 +85,8 @@ int main(int argc, char* argv[]) std::cout << source(hd.tmhd,sm) << std::endl; } + boost::property_map::type vpm = get(CGAL::vertex_point,ssm); + std::cout << get(vpm, source(hd,ssm)) << std::endl; return 0; } diff --git a/BGL/include/CGAL/boost/graph/Seam_mesh.h b/BGL/include/CGAL/boost/graph/Seam_mesh.h index ac5031a4c2d..8044b24d5aa 100644 --- a/BGL/include/CGAL/boost/graph/Seam_mesh.h +++ b/BGL/include/CGAL/boost/graph/Seam_mesh.h @@ -18,6 +18,11 @@ template public: typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + const TM& mesh()const + { + return tm; + } + struct halfedge_descriptor { TM_halfedge_descriptor tmhd; bool seam; diff --git a/BGL/include/CGAL/boost/graph/graph_traits_Seam_mesh.h b/BGL/include/CGAL/boost/graph/graph_traits_Seam_mesh.h index 633cd02bd37..93ed18e828f 100644 --- a/BGL/include/CGAL/boost/graph/graph_traits_Seam_mesh.h +++ b/BGL/include/CGAL/boost/graph/graph_traits_Seam_mesh.h @@ -25,7 +25,7 @@ #include -//#include +#include #include #include diff --git a/BGL/include/CGAL/boost/graph/properties_Seam_mesh.h b/BGL/include/CGAL/boost/graph/properties_Seam_mesh.h new file mode 100644 index 00000000000..7802ec9bf77 --- /dev/null +++ b/BGL/include/CGAL/boost/graph/properties_Seam_mesh.h @@ -0,0 +1,58 @@ +// Copyright (c) 2015 GeometryFactory (France). All rights reserved. +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 3 of the License, +// or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Andreas Fabri + + +#ifndef CGAL_PROPERTIES_SEAM_MESH_H +#define CGAL_PROPERTIES_SEAM_MESH_H + +#include + +#include + +namespace CGAL { + +template +class Seam_mesh; + +} // namespace CGAL + + +namespace boost { + +template +struct property_map, CGAL::vertex_point_t > +{ + typedef CGAL::Seam_mesh

SM; + + typedef typename property_map::type type; + + typedef type const_type; + +}; + +template +typename property_map, CGAL::vertex_point_t >::const_type +get(CGAL::vertex_point_t, const CGAL::Seam_mesh& g) { + return get(CGAL::vertex_point_t(), const_cast(g.mesh())); +} + + +} // namespace boost + +#endif // CGAL_PROPERTIES_SEAM_MESH_H diff --git a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/CMakeLists.txt b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/CMakeLists.txt index ec4e5e8ff11..3200311a10b 100644 --- a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/CMakeLists.txt +++ b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/CMakeLists.txt @@ -58,6 +58,7 @@ if ( CGAL_FOUND ) # Executables that require Eigen 3.1 include( ${EIGEN3_USE_FILE} ) + create_single_source_cgal_program( "debug.cpp" ) create_single_source_cgal_program( "Authalic_parameterization.cpp" ) create_single_source_cgal_program( "Mesh_cutting_parameterization.cpp" ) create_single_source_cgal_program( "Simple_parameterization.cpp" ) diff --git a/Surface_mesh_parameterization/include/CGAL/Circular_border_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Circular_border_parameterizer_3.h index 13db0acfac6..971b3fda109 100644 --- a/Surface_mesh_parameterization/include/CGAL/Circular_border_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Circular_border_parameterizer_3.h @@ -62,16 +62,20 @@ class Circular_border_parameterizer_3 // Public types public: /// Export ParameterizationMesh_3 template parameter - typedef ParameterizationMesh_3 Adaptor; - typedef typename Adaptor::Polyhedron TriangleMesh; + typedef ParameterizationMesh_3 TriangleMesh; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; // Private types private: - // Mesh_Adaptor_3 subtypes: - typedef typename Adaptor::Point_2 Point_2; - typedef typename Adaptor::Vector_3 Vector_3; + typedef Parameterizer_traits_3 Traits; + typedef typename Traits::VPM VPM; + typedef typename Traits::Point_3 Point_3; + typedef typename Traits::Vector_3 Vector_3; + typedef typename Traits::Point_2 Point_2; + typedef typename Traits::Error_code Error_code; + VPM vpm; // Public operations public: @@ -82,198 +86,185 @@ public: /// Assign to mesh's border vertices a 2D position (i.e.\ a (u,v) pair) /// on border's shape. Mark them as parameterized. - typename Parameterizer_traits_3::Error_code - parameterize_border(Adaptor& mesh); - - /// Indicate if border's shape is convex. - bool is_border_convex () { return true; } - -// Protected operations -protected: - /// Compute the length of an edge. - virtual double compute_edge_length(const Adaptor& mesh, - vertex_descriptor source, - vertex_descriptor target) = 0; - -// Private operations -private: - /// Compute the total length of the border - double compute_border_length(const Adaptor& mesh); -}; - - -// Compute the total length of the border -template -inline -double Circular_border_parameterizer_3::compute_border_length( - const Adaptor& mesh) -{ - const TriangleMesh& tmesh = mesh.get_adapted_mesh(); - double len = 0.0; - BOOST_FOREACH(halfedge_descriptor hd, mesh.main_border()) - { - CGAL_surface_mesh_parameterization_assertion(mesh.is_vertex_on_main_border(target(hd, tmesh))); - // Add 'length' of it -> next vector to 'len' - len += compute_edge_length(mesh, source(hd,tmesh), target(hd,tmesh)); - } - return len; -} - -// Assign to mesh's border vertices a 2D position (i.e.\ a (u,v) pair) -// on border's shape. Mark them as "parameterized". -template -inline -typename Parameterizer_traits_3::Error_code -Circular_border_parameterizer_3::parameterize_border(Adaptor& mesh) -{ -#ifdef DEBUG_TRACE - std::cerr << " map on a circle" << std::endl; -#endif - const TriangleMesh& tmesh = mesh.get_adapted_mesh(); - // Nothing to do if no border - if (mesh.main_border().empty()) - return Parameterizer_traits_3::ERROR_BORDER_TOO_SHORT; - + template + Error_code + parameterize_border(ParameterizationMesh_3& mesh, halfedge_descriptor bhd, HalfedgeUVmap uvmap) + { + // TODO Nothing to do if no border + //if (! is_border(bhd,tmesh)){ + // return Parameterizer_traits_3::ERROR_BORDER_TOO_SHORT; + //} // Compute the total border length - double total_len = compute_border_length(mesh); + double total_len = compute_border_length(mesh,bhd); if (total_len == 0) - return Parameterizer_traits_3::ERROR_BORDER_TOO_SHORT; - - const double PI = 3.14159265359; - const double tmp = 2*PI/total_len; + return Parameterizer_traits_3::ERROR_BORDER_TOO_SHORT; + + const double tmp = 2*CGAL_PI/total_len; double len = 0.0; // current position on circle in [0, total_len] - - BOOST_FOREACH(halfedge_descriptor hd, mesh.main_border()) - { - vertex_descriptor vd = target(hd,tmesh); - CGAL_surface_mesh_parameterization_assertion(mesh.is_vertex_on_main_border(vd)); - - double angle = len*tmp; // current position on the circle in radians - - // map vertex on unit circle - Point_2 uv; - uv = Point_2(0.5+0.5*std::cos(-angle),0.5+0.5*std::sin(-angle)); - mesh.set_vertex_uv(hd, uv); - - // Mark vertex as "parameterized" - mesh.set_vertex_parameterized(hd, true); - - len += compute_edge_length(mesh, source(hd,tmesh), vd); + + BOOST_FOREACH(halfedge_descriptor hd, halfedges_around_face(bhd,mesh)){ + vertex_descriptor vd = target(hd,mesh); + + double angle = len*tmp; // current position on the circle in radians + + // map vertex on unit circle + Point_2 uv; + uv = Point_2(0.5+0.5*std::cos(-angle),0.5+0.5*std::sin(-angle)); + BOOST_FOREACH(halfedge_descriptor hat, halfedges_around_target(hd,mesh)){ + // We do not set the uv value of halfedges on the main border or seam edges + if(hat != hd){ + put(uvmap, hat, uv); + } + } + // Mark vertex as "parameterized" + // TODO + // mesh.set_vertex_parameterized(hd, true); + + len += CGAL::sqrt(squared_distance(get(vpm, source(hd,mesh)), get(vpm,vd))); } - - return Parameterizer_traits_3::OK; -} - - -// -// Class Circular_border_uniform_parameterizer_3 -// - -/// \ingroup PkgSurfaceParameterizationBorderParameterizationMethods -/// -/// This class parameterizes the border of a 3D surface onto a circle -/// in a uniform manner: points are equally spaced. -/// Circular_border_parameterizer_3 implements most of the border parameterization -/// algorithm. This class implements only `compute_edge_length()` to compute a -/// segment's length. -/// -/// \cgalModels `BorderParameterizer_3` -/// -/// \sa `CGAL::Circular_border_arc_length_parameterizer_3` -/// \sa `CGAL::Circular_border_parameterizer_3` - -template //< 3D surface -class Circular_border_uniform_parameterizer_3 - : public Circular_border_parameterizer_3 -{ -// Public types -public: - // We have to repeat the types exported by superclass - /// @cond SKIP_IN_MANUAL - typedef ParameterizationMesh_3 Adaptor; - /// @endcond - -// Private types -private: - // Mesh_Adaptor_3 subtypes: - typedef typename Adaptor::NT NT; - typedef typename Adaptor::Point_2 Point_2; - typedef typename Adaptor::Vector_3 Vector_3; - -// Public operations -public: - // Default constructor, copy constructor and operator =() are fine - -// Protected operations -protected: + + return Parameterizer_traits_3::OK; + } + + + /// Indicate if border's shape is convex. + bool is_border_convex () { return true; } + + // Protected operations + protected: /// Compute the length of an edge. - virtual double compute_edge_length(const Adaptor& /* mesh */, - vertex_descriptor /* source */, - vertex_descriptor /* target */) + /// virtual double compute_edge_length(const Adaptor& mesh, + /// vertex_descriptor source, + /// vertex_descriptor target) = 0; + + // Private operations + private: + /// Compute the total length of the border + double compute_border_length(const ParameterizationMesh_3& tmesh, halfedge_descriptor bhd){ + + vpm = get(CGAL::vertex_point,tmesh); + double len = 0.0; + BOOST_FOREACH(halfedge_descriptor hd, halfedges_around_face(bhd,tmesh)){ + len += CGAL::sqrt(squared_distance(get(vpm, source(hd,tmesh)), get(vpm, target(hd,tmesh)))); + } + return len; + } + }; + + +#if 0 + + + + + // + // Class Circular_border_uniform_parameterizer_3 + // + + /// \ingroup PkgSurfaceParameterizationBorderParameterizationMethods + /// + /// This class parameterizes the border of a 3D surface onto a circle + /// in a uniform manner: points are equally spaced. + /// Circular_border_parameterizer_3 implements most of the border parameterization + /// algorithm. This class implements only `compute_edge_length()` to compute a + /// segment's length. + /// + /// \cgalModels `BorderParameterizer_3` + /// + /// \sa `CGAL::Circular_border_arc_length_parameterizer_3` + /// \sa `CGAL::Circular_border_parameterizer_3` + + template //< 3D surface + class Circular_border_uniform_parameterizer_3 + : public Circular_border_parameterizer_3 { + // Public types + public: + // We have to repeat the types exported by superclass + /// @cond SKIP_IN_MANUAL + typedef ParameterizationMesh_3 Adaptor; + /// @endcond + + // Private types + private: + // Mesh_Adaptor_3 subtypes: + typedef typename Parameterizer_traits_3::Point_2 Point_2; + typedef typename Parameterizer_traits_3::Vector_3 Vector_3; + + // Public operations + public: + // Default constructor, copy constructor and operator =() are fine + + // Protected operations + protected: + /// Compute the length of an edge. + virtual double compute_edge_length(const Adaptor& /* mesh */, + vertex_descriptor /* source */, + vertex_descriptor /* target */) + { /// Uniform border parameterization: points are equally spaced. return 1; - } -}; + } + }; +#endif -// -// Class Circular_border_arc_length_parameterizer_3 -// + // + // Class Circular_border_arc_length_parameterizer_3 + // -/// \ingroup PkgSurfaceParameterizationBorderParameterizationMethods -/// -/// This class parameterizes the border of a 3D surface onto a circle, -/// with an arc-length parameterization: (u,v) values are -/// proportional to the length of border edges. -/// `Circular_border_parameterizer_3` implements most of the border parameterization -/// algorithm. This class implements only `compute_edge_length()` to compute a -/// segment's length. -/// -/// \cgalModels `BorderParameterizer_3` -/// -/// \sa `CGAL::Circular_border_parameterizer_3` -/// \sa `CGAL::Circular_border_uniform_parameterizer_3` + /// \ingroup PkgSurfaceParameterizationBorderParameterizationMethods + /// + /// This class parameterizes the border of a 3D surface onto a circle, + /// with an arc-length parameterization: (u,v) values are + /// proportional to the length of border edges. + /// `Circular_border_parameterizer_3` implements most of the border parameterization + /// algorithm. This class implements only `compute_edge_length()` to compute a + /// segment's length. + /// + /// \cgalModels `BorderParameterizer_3` + /// + /// \sa `CGAL::Circular_border_parameterizer_3` + /// \sa `CGAL::Circular_border_uniform_parameterizer_3` -template //< 3D surface -class Circular_border_arc_length_parameterizer_3 - : public Circular_border_parameterizer_3 -{ -// Public types -public: - // We have to repeat the types exported by superclass - /// @cond SKIP_IN_MANUAL - typedef ParameterizationMesh_3 Adaptor; - /// @endcond + template //< 3D surface + class Circular_border_arc_length_parameterizer_3 + : public Circular_border_parameterizer_3 + { + // Public types + public: + // We have to repeat the types exported by superclass + /// @cond SKIP_IN_MANUAL + typedef ParameterizationMesh_3 Adaptor; + /// @endcond -// Private types -private: - // Mesh_Adaptor_3 subtypes: - typedef typename Adaptor::NT NT; - typedef typename Adaptor::Point_2 Point_2; - typedef typename Adaptor::Vector_3 Vector_3; + // Private types + private: + // Mesh_Adaptor_3 subtypes: + typedef typename Parameterizer_traits_3::Point_2 Point_2; + typedef typename Parameterizer_traits_3::Vector_3 Vector_3; -// Public operations -public: - // Default constructor, copy constructor and operator =() are fine + // Public operations + public: + // Default constructor, copy constructor and operator =() are fine -// Protected operations -protected: - /// Compute the length of an edge. - virtual double compute_edge_length(const Adaptor& mesh, - vertex_descriptor source, - vertex_descriptor target) - { - typedef typename boost::property_map::const_type PPmap; - PPmap ppmap = get(vertex_point, mesh.get_adapted_mesh()); + // Protected operations + protected: + /// Compute the length of an edge. + virtual double compute_edge_length(const ParameterizationMesh_3 & mesh, + vertex_descriptor source, + vertex_descriptor target) + { + typedef typename boost::property_map::const_type PPmap; + PPmap ppmap = get(vertex_point, mesh); /// Arc-length border parameterization: (u,v) values are /// proportional to the length of border edges. - Vector_3 v = get(ppmap, target) - - get(ppmap,source); + Vector_3 v = get(ppmap, target) - get(ppmap,source); return std::sqrt(v*v); - } -}; + } + }; + } //namespace CGAL diff --git a/Surface_mesh_parameterization/include/CGAL/Discrete_authalic_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Discrete_authalic_parameterizer_3.h index 967d4a30f6e..6b7efb6c3c6 100644 --- a/Surface_mesh_parameterization/include/CGAL/Discrete_authalic_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Discrete_authalic_parameterizer_3.h @@ -26,6 +26,7 @@ #include +#include #include #include @@ -88,7 +89,7 @@ public: // We have to repeat the types exported by superclass /// @cond SKIP_IN_MANUAL typedef typename Base::Error_code Error_code; - typedef ParameterizationMesh_3 Adaptor; + typedef ParameterizationMesh_3 TriangleMesh; typedef BorderParameterizer_3 Border_param; typedef SparseLinearAlgebraTraits_d Sparse_LA; /// @endcond @@ -96,13 +97,12 @@ public: // Private types private: - typedef typename Adaptor::Polyhedron TriangleMesh; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef CGAL::Halfedge_around_target_circulator halfedge_around_target_circulator; // Mesh_Adaptor_3 subtypes: - typedef typename Adaptor::NT NT; - typedef typename Adaptor::Point_3 Point_3; - typedef typename Adaptor::Vector_3 Vector_3; + typedef typename Parameterizer_traits_3::NT NT; + typedef typename Parameterizer_traits_3::Point_3 Point_3; + typedef typename Parameterizer_traits_3::Vector_3 Vector_3; // SparseLinearAlgebraTraits_d subtypes: typedef typename Sparse_LA::Vector Vector; @@ -117,7 +117,7 @@ public: ///< Object that maps the surface's border to 2D space. Sparse_LA sparse_la = Sparse_LA()) ///< Traits object to access a sparse linear system. - : Fixed_border_parameterizer_3(border_param, sparse_la) {} @@ -127,13 +127,12 @@ public: // Protected operations protected: /// Compute w_ij = (i, j) coefficient of matrix A for j neighbor vertex of i. - virtual NT compute_w_ij(const Adaptor& mesh, + virtual NT compute_w_ij(const TriangleMesh& tmesh, vertex_descriptor main_vertex_v_i, halfedge_around_target_circulator neighbor_vertex_v_j) { - const TriangleMesh& tmesh = mesh.get_adapted_mesh(); - typedef typename boost::property_map::const_type PPmap; - typedef typename boost::property_traits::reference Point_3; + + typedef typename Parameterizer_traits_3::VPM PPmap; PPmap ppmap = get(vertex_point, tmesh); diff --git a/Surface_mesh_parameterization/include/CGAL/Fixed_border_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Fixed_border_parameterizer_3.h index 11d09820e38..29844922e30 100644 --- a/Surface_mesh_parameterization/include/CGAL/Fixed_border_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Fixed_border_parameterizer_3.h @@ -32,10 +32,10 @@ #include #include -#include #include #include #include +#include /// \file Fixed_border_parameterizer_3.h @@ -91,16 +91,14 @@ class Fixed_border_parameterizer_3 { // Private types private: - // Superclass - typedef Parameterizer_traits_3 - Base; + typedef Parameterizer_traits_3 Base; // Public types public: // We have to repeat the types exported by superclass /// @cond SKIP_IN_MANUAL typedef typename Base::Error_code Error_code; - typedef ParameterizationMesh_3 Adaptor; + typedef ParameterizationMesh_3 TriangleMesh; /// @endcond /// Export BorderParameterizer_3 template parameter. @@ -111,9 +109,9 @@ public: // Private types private: - typedef typename Adaptor::Polyhedron TriangleMesh; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_iterator face_iterator; typedef typename boost::graph_traits::vertex_iterator vertex_iterator; @@ -122,10 +120,10 @@ private: typedef CGAL::Halfedge_around_target_circulator halfedge_around_target_circulator; // Mesh_Adaptor_3 subtypes: - typedef typename Adaptor::NT NT; - typedef typename Adaptor::Point_2 Point_2; - typedef typename Adaptor::Point_3 Point_3; - typedef typename Adaptor::Vector_3 Vector_3; + typedef typename Base::NT NT; + typedef typename Base::Point_2 Point_2; + typedef typename Base::Point_3 Point_3; + typedef typename Base::Vector_3 Vector_3; // SparseLinearAlgebraTraits_d subtypes: @@ -157,7 +155,12 @@ public: /// \pre `mesh` must be a surface with one connected component. /// \pre `mesh` must be a triangular mesh. /// \pre The mesh border must be mapped onto a convex polygon. - virtual Error_code parameterize(Adaptor& mesh); + + template + Error_code parameterize(TriangleMesh& mesh, + halfedge_descriptor, + HalfedgeUVmap, + HalfedgeAsVertexIndexMap hvimap); // Protected operations protected: @@ -165,7 +168,7 @@ protected: /// - `mesh` must be a surface with one connected component. /// - `mesh` must be a triangular mesh. /// - The mesh border must be mapped onto a convex polygon. - virtual Error_code check_parameterize_preconditions(Adaptor& mesh); + /// virtual Error_code check_parameterize_preconditions(TriangleMesh& mesh); /// Initialize A, Bu and Bv after border parameterization. /// Fill the border vertices' lines in both linear systems: @@ -174,15 +177,37 @@ protected: /// \pre Vertices must be indexed. /// \pre A, Bu and Bv must be allocated. /// \pre Border vertices must be parameterized. + template void initialize_system_from_mesh_border (Matrix& A, Vector& Bu, Vector& Bv, - const Adaptor& mesh); + const TriangleMesh& tmesh, + halfedge_descriptor bhd, + HalfedgeUVmap uvmap, + HalfedgeAsVertexIndexMap hvimap) +{ + // AF: loop over border halfedges + BOOST_FOREACH(halfedge_descriptor hd, halfedges_around_face(bhd,tmesh)){ + // AF not written for halfedge CGAL_surface_mesh_parameterization_assertion(mesh.is_vertex_parameterized(target(hd,tmesh))); + + // AF: get the halfedge-as-vertex index + // Get vertex index in sparse linear system + int index = get(hvimap,hd); + + // Write a diagonal coefficient of A + A.set_coef(index, index, 1, true /*new*/); + //std::cerr << index << " " << index << " 1" << std::endl; + // get the halfedge uv + // Write constant in Bu and Bv + Point_2 uv = get(uvmap, opposite(next(hd,tmesh),tmesh)); + Bu[index] = uv.x(); + Bv[index] = uv.y(); + } +} /// Compute w_ij = (i, j) coefficient of matrix A for j neighbor vertex of i. /// Implementation note: Subclasses must at least implement compute_w_ij(). - virtual NT compute_w_ij(const Adaptor& mesh, + virtual NT compute_w_ij(const TriangleMesh& mesh, vertex_descriptor main_vertex_v_i, - // vertex_around_target_circulator neighbor_vertex_v_j) - halfedge_around_target_circulator neighbor_vertex_v_j) + halfedge_around_target_circulator neighbor_vertex_v_j) = 0; /// Compute the line i of matrix A for i inner vertex: @@ -192,29 +217,70 @@ protected: /// \pre Vertices must be indexed. /// \pre Vertex i musn't be already parameterized. /// \pre Line i of A must contain only zeros. - virtual Error_code setup_inner_vertex_relations(Matrix& A, - Vector& Bu, - Vector& Bv, - const Adaptor& mesh, - vertex_descriptor vertex); + // TODO: check if this must be virtual + // virtual + template + Error_code setup_inner_vertex_relations(Matrix& A, + Vector& Bu, + Vector& Bv, + const TriangleMesh& mesh, + vertex_descriptor vertex, + HalfedgeAsVertexIndexMap hvimap) +{ + // CGAL_surface_mesh_parameterization_assertion( ! amesh.is_vertex_on_main_border(vertex) ); + // CGAL_surface_mesh_parameterization_assertion( ! amesh.is_vertex_parameterized(vertex) ); - /// Copy Xu and Xv coordinates into the (u,v) pair of each surface vertex. - void set_mesh_uv_from_system (Adaptor& mesh, - const Vector& Xu, const Vector& Xv); + int i = get(hvimap,halfedge(vertex,mesh)); + // circulate over vertices around 'vertex' to compute w_ii and w_ijs + // use halfedge_around_target to get the right "vertex" if it is on a seam + NT w_ii = 0; + int vertexIndex = 0; + + halfedge_around_target_circulator v_j(halfedge(vertex,mesh), mesh), + end = v_j; + CGAL_For_all(v_j, end) + { + // Call to virtual method to do the actual coefficient computation + NT w_ij = -1.0 * compute_w_ij(mesh, vertex, v_j); + + // w_ii = - sum of w_ijs + w_ii -= w_ij; + + // Get j index + int j = get(hvimap, opposite(*v_j,mesh)); + + // Set w_ij in matrix + A.set_coef(i,j, w_ij, true /*new*/); + + vertexIndex++; + } + if (vertexIndex < 2) + return Base::ERROR_NON_TRIANGULAR_MESH; + + // Set w_ii in matrix + A.set_coef(i,i, w_ii, true /*new*/); + + return Base::OK; +} + + + +#if 0 /// Check parameterize() postconditions: /// - 3D -> 2D mapping is one-to-one. - virtual Error_code check_parameterize_postconditions(const Adaptor& mesh, + virtual Error_code check_parameterize_postconditions(const TriangleMesh& mesh, const Matrix& A, const Vector& Bu, const Vector& Bv); /// Check if 3D -> 2D mapping is one-to-one. /// The default implementation checks each normal. - virtual bool is_one_to_one_mapping(const Adaptor& mesh, + virtual bool is_one_to_one_mapping(const TriangleMesh& mesh, const Matrix& A, const Vector& Bu, const Vector& Bv); +#endif // Protected accessors protected: @@ -247,13 +313,12 @@ private: // - `mesh` must be a surface with one connected component. // - `mesh` must be a triangular mesh. // - The mesh border must be mapped onto a convex polygon. -template -inline -typename Fixed_border_parameterizer_3::Error_code -Fixed_border_parameterizer_3:: -parameterize(Adaptor& amesh) +template +template +typename Fixed_border_parameterizer_3::Error_code +Fixed_border_parameterizer_3:: +parameterize(TriangleMesh& mesh, halfedge_descriptor bhd, HalfedgeUVmap uvmap, HalfedgeAsVertexIndexMap hvimap) { - const TriangleMesh& mesh = amesh.get_adapted_mesh(); #ifdef DEBUG_TRACE // Create timer for traces @@ -271,18 +336,19 @@ parameterize(Adaptor& amesh) return status; // Count vertices - int nbVertices = amesh.count_mesh_vertices(); + int nbVertices = num_vertices(mesh); + // AF: mark all halfedges as not parameterized // Mark all vertices as *not* "parameterized" - BOOST_FOREACH(vertex_descriptor v, vertices(mesh)) - { - amesh.set_vertex_parameterized(v, false); - } - + // BOOST_FOREACH(vertex_descriptor v, vertices(mesh)) + // { + // amesh.set_vertex_parameterized(v, false); + // } + // Compute (u,v) for border vertices // and mark them as "parameterized" - status = get_border_parameterizer().parameterize_border(amesh); + status = get_border_parameterizer().parameterize_border(mesh,bhd,uvmap); #ifdef DEBUG_TRACE std::cerr << " border vertices parameterization: " << timer.time() << " seconds." << std::endl; timer.reset(); @@ -301,23 +367,30 @@ parameterize(Adaptor& amesh) // @todo Fixed_border_parameterizer_3 should remove border vertices // from the linear systems in order to have a symmetric positive definite // matrix for Tutte Barycentric Mapping and Discrete Conformal Map algorithms. - initialize_system_from_mesh_border (A, Bu, Bv, amesh); + initialize_system_from_mesh_border (A, Bu, Bv, mesh, bhd, uvmap, hvimap); // AF: no change, as this are only concerns inner vertices // Fill the matrix for the inner vertices v_i: compute A's coefficient // w_ij for each neighbor j; then w_ii = - sum of w_ijs + std::set main_border; + + BOOST_FOREACH(vertex_descriptor v, vertices_around_face(bhd,mesh)){ + main_border.insert(v); + } + BOOST_FOREACH(vertex_descriptor v, vertices(mesh)) { // CGAL_surface_mesh_parameterization_assertion(amesh.is_vertex_on_main_border(v) // == amesh.is_vertex_parameterized(v)); // inner vertices only - if( ! amesh.is_vertex_on_main_border(v) ) + if( main_border.find(v) == main_border.end() ) { // Compute the line i of matrix A for i inner vertex status = setup_inner_vertex_relations(A, Bu, Bv, - amesh, - v); + mesh, + v, + hvimap); if (status != Base::OK) return status; } @@ -349,7 +422,18 @@ parameterize(Adaptor& amesh) CGAL_surface_mesh_parameterization_assertion(Dv == 1.0); // Copy Xu and Xv coordinates into the (u,v) pair of each vertex - set_mesh_uv_from_system (amesh, Xu, Xv); + + BOOST_FOREACH(vertex_descriptor v, vertices(mesh)) + { + // inner vertices only + if( main_border.find(v) == main_border.end() ) + { + BOOST_FOREACH(halfedge_descriptor hd, halfedges_around_target(v,mesh)){ + int index = get(hvimap,hd); + put(uvmap,hd,Point_2(Xu[index],Xv[index])); + } + } + } #ifdef DEBUG_TRACE std::cerr << " copy computed UVs to mesh :" << timer.time() << " seconds." << std::endl; @@ -367,16 +451,16 @@ parameterize(Adaptor& amesh) return status; } - +#if 0 // Check parameterize() preconditions: // - `mesh` must be a surface with one connected component. // - `mesh` must be a triangular mesh. // - The mesh border must be mapped onto a convex polygon. -template +template inline -typename Fixed_border_parameterizer_3::Error_code -Fixed_border_parameterizer_3:: -check_parameterize_preconditions(Adaptor& amesh) +typename Fixed_border_parameterizer_3::Error_code +Fixed_border_parameterizer_3:: +check_parameterize_preconditions(TriangleMesh& amesh) { const TriangleMesh& mesh = amesh.get_adapted_mesh(); @@ -384,9 +468,9 @@ check_parameterize_preconditions(Adaptor& amesh) Error_code status = Base::OK; // returned value // Helper class to compute genus or count borders, vertices, ... - typedef Parameterization_mesh_feature_extractor - Mesh_feature_extractor; - Mesh_feature_extractor feature_extractor(amesh); + //typedef Parameterization_mesh_feature_extractor + // Mesh_feature_extractor; + //Mesh_feature_extractor feature_extractor(amesh); // Check that mesh is not empty vertex_iterator b, e; @@ -423,7 +507,9 @@ check_parameterize_preconditions(Adaptor& amesh) return status; } +#endif +#if 0 // Initialize A, Bu and Bv after border parameterization. // Fill the border vertices' lines in both linear systems: "u = constant" and "v = constant". // @@ -431,34 +517,17 @@ check_parameterize_preconditions(Adaptor& amesh) // - Vertices must be indexed. // - A, Bu and Bv must be allocated. // - Border vertices must be parameterized. -template +template inline -void Fixed_border_parameterizer_3:: +template +void Fixed_border_parameterizer_3:: initialize_system_from_mesh_border (Matrix& A, Vector& Bu, Vector& Bv, - const Adaptor& mesh) -{ - const TriangleMesh& tmesh = mesh.get_adapted_mesh(); - - // AF: loop over border halfedges - BOOST_FOREACH(halfedge_descriptor hd, mesh.main_border()) - { - // AF not written for halfedge CGAL_surface_mesh_parameterization_assertion(mesh.is_vertex_parameterized(target(hd,tmesh))); - - // AF: get the halfedge-as-vertex index - // Get vertex index in sparse linear system - int index = mesh.get_vertex_index(hd); - - // Write a diagonal coefficient of A - A.set_coef(index, index, 1, true /*new*/); - - // get the halfedge uv - // Write constant in Bu and Bv - Point_2 uv = mesh.get_vertex_uv(hd); - Bu[index] = uv.x(); - Bv[index] = uv.y(); - } -} + const TriangleMesh& tmesh, + halfedge_descriptor bhd, + HalfedgeUVmap uvmap) +#endif +#if 0 // Compute the line i of matrix A for i inner vertex: // - call compute_w_ij() to compute the A coefficient w_ij for each neighbor v_j. // - compute w_ii = - sum of w_ijs. @@ -467,87 +536,32 @@ initialize_system_from_mesh_border (Matrix& A, Vector& Bu, Vector& Bv, // - Vertices must be indexed. // - Vertex i must not be already parameterized. // - Line i of A must contain only zeros. -template +template inline -typename Fixed_border_parameterizer_3::Error_code -Fixed_border_parameterizer_3:: +template +typename Fixed_border_parameterizer_3::Error_code +Fixed_border_parameterizer_3:: setup_inner_vertex_relations(Matrix& A, Vector& , Vector& , - const Adaptor& amesh, - vertex_descriptor vertex) -{ - const TriangleMesh& mesh = amesh.get_adapted_mesh(); - CGAL_surface_mesh_parameterization_assertion( ! amesh.is_vertex_on_main_border(vertex) ); - CGAL_surface_mesh_parameterization_assertion( ! amesh.is_vertex_parameterized(vertex) ); - - int i = amesh.get_vertex_index(vertex); - - // circulate over vertices around 'vertex' to compute w_ii and w_ijs - // use halfedge_around_target to get the right "vertex" if it is on a seam - NT w_ii = 0; - int vertexIndex = 0; - - halfedge_around_target_circulator v_j(halfedge(vertex,mesh), mesh), - end = v_j; - CGAL_For_all(v_j, end) - { - // Call to virtual method to do the actual coefficient computation - NT w_ij = -1.0 * compute_w_ij(amesh, vertex, v_j); - - // w_ii = - sum of w_ijs - w_ii -= w_ij; - - // Get j index - int j= amesh.get_vertex_index(opposite(*v_j,mesh)); - - // Set w_ij in matrix - A.set_coef(i,j, w_ij, true /*new*/); - - vertexIndex++; - } - if (vertexIndex < 2) - return Base::ERROR_NON_TRIANGULAR_MESH; - - // Set w_ii in matrix - A.set_coef(i,i, w_ii, true /*new*/); - - return Base::OK; -} + const TriangleMesh& mesh, + vertex_descriptor vertex, + HalfedgeAsVertexIndexMap hvimap) // Copy Xu and Xv coordinates into the (u,v) pair of each surface vertex. // AF: this only concerns vertices NOT on the border -template -inline -void Fixed_border_parameterizer_3:: -set_mesh_uv_from_system(Adaptor& amesh, - const Vector& Xu, const Vector& Xv) -{ - const TriangleMesh& mesh = amesh.get_adapted_mesh(); - - // AF: do that for halfedges - BOOST_FOREACH(vertex_descriptor vd, vertices(mesh)) - { - int index = amesh.get_vertex_index(vd); +template +#endif - if(index != -1){ - NT u = Xu[index]; - NT v = Xv[index]; - - // Fill vertex (u,v) and mark it as "parameterized" - amesh.set_vertex_uv(vd, Point_2(u,v)); - amesh.set_vertex_parameterized(vd, true); - } - } -} +#if 0 // Check parameterize() postconditions: // - 3D -> 2D mapping is one-to-one. -template +template inline -typename Fixed_border_parameterizer_3::Error_code -Fixed_border_parameterizer_3:: -check_parameterize_postconditions(const Adaptor& mesh, +typename Fixed_border_parameterizer_3::Error_code +Fixed_border_parameterizer_3:: +check_parameterize_postconditions(const TriangleMesh& mesh, const Matrix& A, const Vector& Bu, const Vector& Bv) @@ -566,16 +580,14 @@ check_parameterize_postconditions(const Adaptor& mesh, // Check if 3D -> 2D mapping is one-to-one. // The default implementation checks each normal. -template +template inline -bool Fixed_border_parameterizer_3:: -is_one_to_one_mapping(const Adaptor& amesh, +bool Fixed_border_parameterizer_3:: +is_one_to_one_mapping(const TriangleMesh& mesh, const Matrix& , const Vector& , const Vector& ) { - const TriangleMesh& mesh = amesh.get_adapted_mesh(); - Vector_3 first_triangle_normal = NULL_VECTOR; // initialize to avoid warning BOOST_FOREACH(face_descriptor f, faces(mesh)) @@ -625,7 +637,7 @@ is_one_to_one_mapping(const Adaptor& amesh, return true; // OK if we reach this point } - +#endif } //namespace CGAL diff --git a/Surface_mesh_parameterization/include/CGAL/Parameterizer_traits_3.h b/Surface_mesh_parameterization/include/CGAL/Parameterizer_traits_3.h index 47f86be5872..c8d0cc9c454 100644 --- a/Surface_mesh_parameterization/include/CGAL/Parameterizer_traits_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Parameterizer_traits_3.h @@ -77,19 +77,29 @@ public: ERROR_WRONG_PARAMETER ///< A method received an unexpected parameter }; - /// Export ParameterizationMesh_3 template parameter - typedef ParameterizationMesh_3 Adaptor; + /// Export ParameterizationMesh_3 template parameter + /// typedef ParameterizationMesh_3 Adaptor; + + typedef typename boost::property_map::type VPM; + typedef typename boost::property_traits::value_type Point_3; + typedef typename Kernel_traits::Kernel Kernel; + + // Mesh_Adaptor_3 subtypes: + typedef typename Kernel::Point_2 Point_2; + typedef typename Kernel::Vector_3 Vector_3; + typedef typename Kernel::FT NT; + // Protected types protected: - +#if 0 // Mesh_Adaptor_3 subtypes: typedef typename Adaptor::NT NT; typedef typename Adaptor::Point_2 Point_2; typedef typename Adaptor::Point_3 Point_3; typedef typename Adaptor::Vector_2 Vector_2; typedef typename Adaptor::Vector_3 Vector_3; -#if 0 + typedef typename Adaptor::Facet Facet; typedef typename Adaptor::Facet_handle Facet_handle; typedef typename Adaptor::Facet_const_handle @@ -132,7 +142,7 @@ public: /// /// \pre `mesh` must be a surface with one connected component. /// \pre `mesh` must be a triangular mesh. - virtual Error_code parameterize (Adaptor& mesh) = 0; + //virtual Error_code parameterize (Adaptor& mesh) = 0; /// Get message corresponding to an error code /// \param error_code The code returned by `parameterize()` diff --git a/Surface_mesh_parameterization/include/CGAL/parameterize.h b/Surface_mesh_parameterization/include/CGAL/parameterize.h index 1de22d5b2ff..a3a233e7c71 100644 --- a/Surface_mesh_parameterization/include/CGAL/parameterize.h +++ b/Surface_mesh_parameterization/include/CGAL/parameterize.h @@ -67,12 +67,15 @@ parameterize(ParameterizationMesh_3& mesh) ///< 3D mesh, model of Parameterizat /// \pre The mesh border must be mapped onto a convex polygon /// (for fixed border parameterizations). /// -template + template typename Parameterizer_traits_3::Error_code parameterize(ParameterizationMesh_3& mesh, ///< 3D mesh, model of ParameterizationMesh_3 - ParameterizerTraits_3 parameterizer) ///< Parameterization method for `mesh` + ParameterizerTraits_3 parameterizer, ///< Parameterization method for `mesh` + HD bhd, + Huvmap huvm, + HalfedgeAsVertexIndexMap himap) { - return parameterizer.parameterize(mesh); + return parameterizer.parameterize(mesh, bhd, huvm, himap); }