diff --git a/BGL/doc/BGL/NamedParameters.txt b/BGL/doc/BGL/NamedParameters.txt index 224d94b25a9..4bde1971424 100644 --- a/BGL/doc/BGL/NamedParameters.txt +++ b/BGL/doc/BGL/NamedParameters.txt @@ -114,6 +114,67 @@ as result of a partition algorithm; if it is not provided, this information is simply inaccessible. \cgalNPEnd + +\cgalNPBegin{vertex_to_vertex_output_iterator} \anchor BGL_vertex_to_vertex_output_iterator +is a model of `OutputIterator` accepting `std::pair` +A typical use case is mapping the vertices from a source mesh to its copy's after a `copy_face_graph()` +operation.\n +Type:a class model of `OutputIterator` accepting +`std::pair<`boost::graph_traits::%vertex_descriptor, `boost::graph_traits::%vertex_descriptor>`.\n +Default: Emptyset_iterator +\cgalNPEnd + +\cgalNPBegin{halfedge_to_halfedge_output_iterator} \anchor BGL_halfedge_to_halfedge_output_iterator +is a model of `OutputIterator` accepting `std::pair` +A typical use case is mapping the halfedges from a source mesh to its copy's after a `copy_face_graph()` +operation.\n +Type:a class model of `OutputIterator` accepting +`std::pair<`boost::graph_traits::%halfedge_descriptor, `boost::graph_traits::%halfedge_descriptor>`.\n +Default: Emptyset_iterator +\cgalNPEnd + + +\cgalNPBegin{face_to_face_output_iterator} \anchor BGL_face_to_face_output_iterator +is a model of `OutputIterator` accepting `std::pair` +A typical use case is mapping the faces from a source mesh to its copy's after a `copy_face_graph()` +operation.\n +Type:a class model of `OutputIterator` accepting +`std::pair<`boost::graph_traits::%face_descriptor, `boost::graph_traits::%face_descriptor>`.\n +Default: Emptyset_iterator +\cgalNPEnd + +\cgalNPBegin{vertex_to_vertex_map} \anchor BGL_vertex_to_vertex_map +is a property map storing for each vertex of a source mesh the corresponding vertex of another mesh.\n +A typical use case is mapping the vertices from a source mesh to its copy's after a `copy_face_graph()` +operation.\n +Type:a class model of `ReadWritePropertyMap` with +`boost::graph_traits::%vertex_descriptor` as key type and +`boost::graph_traits::%vertex_descriptor` as value type.\n +Default: None. +\cgalNPEnd + +\cgalNPBegin{halfedge_to_halfedge_map} \anchor BGL_halfedge_to_halfedge_map +is a property map storing for each halfedge of a source mesh the corresponding halfedge of another mesh.\n +A typical use case is mapping the vertices from a source mesh to its copy's after a `copy_face_graph()` +operation.\n +Type:a class model of `ReadWritePropertyMap` with +`boost::graph_traits::%halfedge_descriptor` as key type and +`boost::graph_traits::%halfedge_descriptor` as value type.\n +Default: None. +\cgalNPEnd + +\cgalNPBegin{face_to_face_map} \anchor BGL_face_to_face_map +is a property map storing for each face of a source mesh the corresponding face of another mesh.\n +A typical use case is mapping the vertices from a source mesh to its copy's after a `copy_face_graph()` +operation.\n +Type:a class model of `ReadWritePropertyMap` with +`boost::graph_traits::%face_descriptor` as key type and +`boost::graph_traits::%face_descriptor` as value type.\n +Default: None. +\cgalNPEnd + + + \cgalNPTableEnd */ diff --git a/BGL/examples/BGL_LCC/copy_lcc.cpp b/BGL/examples/BGL_LCC/copy_lcc.cpp index 0def9a59b53..d47c0216fbb 100644 --- a/BGL/examples/BGL_LCC/copy_lcc.cpp +++ b/BGL/examples/BGL_LCC/copy_lcc.cpp @@ -52,7 +52,8 @@ int main(int argc, char* argv[]) boost::unordered_map v2v; boost::unordered_map h2h; - CGAL::copy_face_graph(T1, S, std::inserter(v2v, v2v.end()), std::inserter(h2h, h2h.end())); + CGAL::copy_face_graph(T1, S, CGAL::parameters::vertex_to_vertex_output_iterator(std::inserter(v2v, v2v.end())) + .halfedge_to_halfedge_output_iterator(std::inserter(h2h, h2h.end()))); std::ofstream out("reverse.off"); out << S; } diff --git a/BGL/examples/BGL_polyhedron_3/copy_polyhedron.cpp b/BGL/examples/BGL_polyhedron_3/copy_polyhedron.cpp index bdbe9bed40e..5a60cba7406 100644 --- a/BGL/examples/BGL_polyhedron_3/copy_polyhedron.cpp +++ b/BGL/examples/BGL_polyhedron_3/copy_polyhedron.cpp @@ -17,6 +17,7 @@ #include #include + typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; typedef CGAL::Polyhedron_3 Source; @@ -57,9 +58,9 @@ int main(int argc, char* argv[]) boost::unordered_map h2h; boost::unordered_map f2f; - CGAL::copy_face_graph(S, T2, std::inserter(v2v, v2v.end()), - std::inserter(h2h, h2h.end()), - std::inserter(f2f, f2f.end())); + CGAL::copy_face_graph(S, T2, CGAL::parameters::vertex_to_vertex_output_iterator(std::inserter(v2v, v2v.end())) + .halfedge_to_halfedge_output_iterator(std::inserter(h2h, h2h.end())) + .face_to_face_output_iterator(std::inserter(f2f, f2f.end()))); OpenMesh::IO::write_mesh(T2, "om.off"); } #endif @@ -67,16 +68,22 @@ int main(int argc, char* argv[]) { typedef boost::graph_traits::vertex_descriptor source_vertex_descriptor; typedef boost::graph_traits::halfedge_descriptor source_halfedge_descriptor; + typedef boost::graph_traits::face_descriptor source_face_descriptor; typedef boost::graph_traits::vertex_descriptor tm_vertex_descriptor; typedef boost::graph_traits::halfedge_descriptor tm_halfedge_descriptor; + typedef boost::graph_traits::face_descriptor tm_face_descriptor; + boost::unordered_map v2v; boost::unordered_map h2h; - + boost::unordered_map f2f; CGAL::copy_face_graph(T1, S, std::inserter(v2v, v2v.end()), std::inserter(h2h, h2h.end())); std::ofstream out("reverse.off"); out << S; + CGAL::copy_face_graph(T1, S, CGAL::parameters::vertex_to_vertex_map(boost::make_assoc_property_map(v2v)) + .halfedge_to_halfedge_output_iterator(std::inserter(h2h, h2h.end())) + .face_to_face_map(boost::make_assoc_property_map(f2f))); } return 0; } diff --git a/BGL/include/CGAL/boost/graph/copy_face_graph.h b/BGL/include/CGAL/boost/graph/copy_face_graph.h index 2517d5ee982..6a26be5b4f4 100644 --- a/BGL/include/CGAL/boost/graph/copy_face_graph.h +++ b/BGL/include/CGAL/boost/graph/copy_face_graph.h @@ -29,8 +29,12 @@ #include #include #include +#include +#include #include #include +#include +#include namespace CGAL { @@ -208,7 +212,39 @@ void copy_face_graph(const SourceMesh& sm, TargetMesh& tm, sm_vpm, tm_vpm); } + + } // end of namespace internal +namespace impl +{ +template +struct Output_iterator_functor +{ + typedef typename boost::property_traits::key_type input_t; + typedef typename boost::property_traits::value_type output_t; + PMAP map; + Output_iterator_functor(PMAP map) + :map(map) + { + } + void operator()(const typename std::pair& pair) + { + put(map, pair.first, pair.second); + } + +}; + +template +boost::function_output_iterator > make_functor(PMAP map) +{ + return boost::make_function_output_iterator(Output_iterator_functor(map)); +} + +inline Emptyset_iterator make_functor(const boost::param_not_found&) +{ + return Emptyset_iterator(); +} +}//end of impl /*! \ingroup PkgBGLHelperFct @@ -223,50 +259,115 @@ void copy_face_graph(const SourceMesh& sm, TargetMesh& tm, and `boost::graph_traits::%face_descriptor` must be models of `Hashable`. \tparam TargetMesh a model of `FaceListGraph` - \tparam V2V a model of `OutputIterator` accepting `std::pair` - \tparam H2H a model of `OutputIterator` accepting `std::pair` - \tparam F2F a model of `OutputIterator` accepting `std::pair` - \tparam Src_vpm a model of `ReadablePropertyMap` with `sm_vertex_descriptor` as key - \tparam Tgt_vpm a model of `WritablePropertyMap` with `tm_vertex_descriptor` as key - where the prefix `sm_` and `tm_` mean belonging to the source and - target mesh respectively. - + \tparam NamedParameters1 a sequence of \ref pmp_namedparameters "Named Parameters" + \tparam NamedParameters2 a sequence of \ref pmp_namedparameters "Named Parameters" + The types `sm_vertex_descriptor` and `sm_face_descriptor` must be models of the concept `Hashable`. \param sm the source mesh \param tm the target mesh - \param v2v pairs of `vertex_descriptors` from `sm` and corresponding `vertex_descriptors` in `tm` are added to `v2v` - \param h2h pairs of `halfedge_descriptors` from `sm` and corresponding `halfedge_descriptors` in `tm` are added to `h2h` - \param f2f pairs of `face_descriptors` from `sm` and corresponding `face_descriptors` in `tm` are added to `f2f` - \param sm_vpm vertex point map for `sm` - \param tm_vpm vertex point map for `tm` + \param np1 optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below + + \cgalNamedParamsBegin + \cgalParamBegin{vertex_point_map} + the property map with the points associated to the vertices of `sm` . + If this parameter is omitted, an internal property map for + `CGAL::vertex_point_t` should be available in `SourceMesh` + \cgalParamEnd + \cgalParamBegin{vertex_to_vertex_output_iterator} an `OutputIterator` containing the + pairs source-vertex, target-vertex. If this parameter is given, then + `vertex_to_vertex_map` cannot be used. + \cgalParamEnd + \cgalParamBegin{halfedge_to_halfedge_output_iterator} an `OutputIterator` containing the + pairs source-halfedge, target-halfedge. If this parameter is given, then + `halfedge_to_halfedge_map` cannot be used. + \cgalParamEnd + \cgalParamBegin{face_to_face_output_iterator} an `OutputIterator` containing the + pairs source-face, target-face. If this parameter is given, then + `face_to_face_map` cannot be used. + \cgalParamEnd + \cgalParamBegin{vertex_to_vertex_map} a `ReadWritePropertyMap` containing the + pairs source-vertex, target-vertex. + \cgalParamEnd + \cgalParamBegin{halfedge_to_halfedge_map} a `ReadWritePropertyMap` containing the + pairs source-halfedge, target-halfedge. + \cgalParamEnd + \cgalParamBegin{face_to_face_map} a `ReadWritePropertyMap` containing the + pairs source-face, target-face. + \cgalParamEnd + \cgalNamedParamsEnd + + \param np2 optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below + + \cgalNamedParamsBegin + \cgalParamBegin{vertex_point_map} + the property map with the points associated to the vertices of `tm`. + If this parameter is omitted, an internal property map for + `CGAL::vertex_point_t` should be available in `TargetMesh` + \cgalParamEnd + \cgalNamedParamsEnd The points from `sm` to `tm` are converted using `CGAL::Cartesian_converter`. `SourceKernel` and `TargetKernel` are deduced using `CGAL::Kernel_traits` - from the value types of `Src_vpm` and `Tgt_vpm`. + from the value types of the vertex_point_maps. Other properties are not copied. */ -#if defined(DOXYGEN_RUNNING) // Use template default arguments template ::const_type, - typename Tgt_vpm = typename boost::property_map::type> + #ifndef DOXYGEN_RUNNING + typename T1, typename Tag1, typename Base1, + typename T2, typename Tag2, typename Base2 + #else + typename NamedParameters1, typename NamedParameters2 + #endif + > void copy_face_graph(const SourceMesh& sm, TargetMesh& tm, - V2V v2v = V2V(), H2H h2h = H2H(), F2F f2f = F2F(), - Src_vpm sm_vpm = get(vertex_point, sm), - Tgt_vpm tm_vpm = get(vertex_point, tm) ) -#else // use the overloads + #ifndef DOXYGEN_RUNNING + const CGAL::cgal_bgl_named_params& np1, + const CGAL::cgal_bgl_named_params& np2 + #else + const NamedParameters1& np1, + const NamedParameters2& np2 + #endif + ) +{ + using boost::choose_param; + internal::copy_face_graph(sm, tm, + CGAL::graph_has_property(), + choose_param(get_param(np1, internal_np::vertex_to_vertex_output_iterator), + impl::make_functor(get_param(np1, internal_np::vertex_to_vertex_map))), + choose_param(get_param(np1, internal_np::halfedge_to_halfedge_output_iterator), + impl::make_functor(get_param(np1, internal_np::halfedge_to_halfedge_map))), + choose_param(get_param(np1, internal_np::face_to_face_output_iterator), + impl::make_functor(get_param(np1, internal_np::face_to_face_map))), + choose_param(get_param(np1, internal_np::vertex_point), + get(vertex_point, sm)), + choose_param(get_param(np2, internal_np::vertex_point), + get(vertex_point, tm))); +} + +template +void copy_face_graph(const SourceMesh& sm, TargetMesh& tm) +{ + copy_face_graph(sm, tm, parameters::all_default(), parameters::all_default()); +} + +template +void copy_face_graph(const SourceMesh& sm, TargetMesh& tm, + const CGAL::cgal_bgl_named_params& np) +{ + copy_face_graph(sm, tm, np, parameters::all_default()); +} + +#if !defined(DOXYGEN_RUNNING) template void copy_face_graph(const SourceMesh& sm, TargetMesh& tm, V2V v2v, H2H h2h, F2F f2f, Src_vpm sm_vpm, Tgt_vpm tm_vpm ) -#endif { internal::copy_face_graph(sm, tm, CGAL::graph_has_property(), @@ -274,11 +375,6 @@ void copy_face_graph(const SourceMesh& sm, TargetMesh& tm, sm_vpm, tm_vpm); } -#if !defined(DOXYGEN_RUNNING) -template -void copy_face_graph(const SourceMesh& sm, TargetMesh& tm) -{ copy_face_graph(sm, tm, Emptyset_iterator(), Emptyset_iterator(), Emptyset_iterator(), - get(vertex_point, sm), get(vertex_point, tm)); } template void copy_face_graph(const SourceMesh& sm, TargetMesh& tm, V2V v2v) diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index 16357cb39dd..1ec0f1504de 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -33,6 +33,14 @@ CGAL_add_named_parameter(metis_options_t, METIS_options, METIS_options) CGAL_add_named_parameter(vertex_partition_id_t, vertex_partition_id, vertex_partition_id_map) CGAL_add_named_parameter(face_partition_id_t, face_partition_id, face_partition_id_map) +CGAL_add_named_parameter(vertex_to_vertex_output_iterator_t, vertex_to_vertex_output_iterator, vertex_to_vertex_output_iterator) +CGAL_add_named_parameter(halfedge_to_halfedge_output_iterator_t, halfedge_to_halfedge_output_iterator, halfedge_to_halfedge_output_iterator) +CGAL_add_named_parameter(face_to_face_output_iterator_t, face_to_face_output_iterator, face_to_face_output_iterator) + +CGAL_add_named_parameter(vertex_to_vertex_map_t, vertex_to_vertex_map, vertex_to_vertex_map) +CGAL_add_named_parameter(halfedge_to_halfedge_map_t, halfedge_to_halfedge_map, halfedge_to_halfedge_map) +CGAL_add_named_parameter(face_to_face_map_t, face_to_face_map, face_to_face_map) + // List of named parameters that we use in the package 'Mesh_3' CGAL_add_named_parameter(vertex_feature_degree_t, vertex_feature_degree, vertex_feature_degree_map) diff --git a/BGL/test/BGL/test_cgal_bgl_named_params.cpp b/BGL/test/BGL/test_cgal_bgl_named_params.cpp index 4bb47789fde..019ad98dedf 100644 --- a/BGL/test/BGL/test_cgal_bgl_named_params.cpp +++ b/BGL/test/BGL/test_cgal_bgl_named_params.cpp @@ -43,6 +43,15 @@ void test(const NamedParameters& np) assert(get_param(np, CGAL::internal_np::METIS_options).v == 800000001); assert(get_param(np, CGAL::internal_np::vertex_partition_id).v == 800000002); assert(get_param(np, CGAL::internal_np::face_partition_id).v == 800000003); + + assert(get_param(np, CGAL::internal_np::vertex_to_vertex_output_iterator).v == 800000004); + assert(get_param(np, CGAL::internal_np::halfedge_to_halfedge_output_iterator).v == 800000005); + assert(get_param(np, CGAL::internal_np::face_to_face_output_iterator).v == 800000006); + + assert(get_param(np, CGAL::internal_np::vertex_to_vertex_map).v == 800000007); + assert(get_param(np, CGAL::internal_np::halfedge_to_halfedge_map).v == 800000008); + assert(get_param(np, CGAL::internal_np::face_to_face_map).v == 800000009); + // Named parameters that we use in the package 'Mesh_3' assert(get_param(np, CGAL::internal_np::vertex_feature_degree).v == 9); @@ -113,6 +122,12 @@ void test(const NamedParameters& np) check_same_type<800000001>(get_param(np, CGAL::internal_np::METIS_options)); check_same_type<800000002>(get_param(np, CGAL::internal_np::vertex_partition_id)); check_same_type<800000003>(get_param(np, CGAL::internal_np::face_partition_id)); + check_same_type<800000004>(get_param(np, CGAL::internal_np::vertex_to_vertex_output_iterator)); + check_same_type<800000005>(get_param(np, CGAL::internal_np::halfedge_to_halfedge_output_iterator)); + check_same_type<800000006>(get_param(np, CGAL::internal_np::face_to_face_output_iterator)); + check_same_type<800000007>(get_param(np, CGAL::internal_np::vertex_to_vertex_map)); + check_same_type<800000008>(get_param(np, CGAL::internal_np::halfedge_to_halfedge_map)); + check_same_type<800000009>(get_param(np, CGAL::internal_np::face_to_face_map)); // Named parameters that we use in the package 'Mesh_3' check_same_type<9>(get_param(np, CGAL::internal_np::vertex_feature_degree)); @@ -178,6 +193,12 @@ int main() .METIS_options(A<800000001>(800000001)) .vertex_partition_id_map(A<800000002>(800000002)) .face_partition_id_map(A<800000003>(800000003)) + .vertex_to_vertex_output_iterator(A<800000004>(800000004)) + .halfedge_to_halfedge_output_iterator(A<800000005>(800000005)) + .face_to_face_output_iterator(A<800000006>(800000006)) + .vertex_to_vertex_map(A<800000007>(800000007)) + .halfedge_to_halfedge_map(A<800000008>(800000008)) + .face_to_face_map(A<800000009>(800000009)) .vertex_feature_degree_map(A<9>(9)) .geom_traits(A<10>(10)) .vertex_incident_patches_map(A<11>(11)) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index fadfc0b67a8..abadba22acf 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -66,6 +66,7 @@ Release date: September 2018 to reflect the real needs of the code (some types and operators were used in the code but did not appear in the concepts). + ### Point Set Processing - Added a callback mechanism to the following functions: @@ -77,7 +78,6 @@ Release date: September 2018 `CGAL::pca_estimate_normals()`, `CGAL::remove_outliers()` and `CGAL::wlop_simplify_and_regularize_point_set()`. - ### Polygon Mesh Processing - Added a named parameter in stitching functions that allows to choose whether the operation should @@ -100,6 +100,8 @@ Release date: September 2018 - Constrained vertices are now guaranteed to be kept in the mesh after calling `isotropic_remeshing()` (and not only the points associated to constrained vertices, as it was before). +- Added a function, `CGAL::Polygon_mesh_processing::extrude_mesh()`, to perform an extrusion of an open polygon mesh. + ### 3D Mesh Generation - **Breaking change:** The template parameters of the class template @@ -143,6 +145,7 @@ Release date: September 2018 - Added the function `Mesh_domain_with_polyline_features_3::add_corner()`, which allows users to add a single corner (that is not incident to any polyline) to the mesh complex. + - **Breaking change**: `CGAL::lloyd_optimize_mesh_3` now depends on the _Eigen_ library. @@ -164,6 +167,17 @@ Release date: September 2018 - Improved the function `CGAL::Euler::collapse_edge` such that the target vertex of the collapsed edge is now always kept after the collapse. +- The function `copy_face_graph()` now uses named parameters, some allowing it + to use property maps instead of output iterators. + +- Addition of the following named parameters : + - vertex_to_vertex_output_iterator + - halfedge_to_halfedge_output_iterator + - face_to_face_output_iterator + - vertex_to_vertex_map + - halfedge_to_halfedge_map + - face_to_face_map + ### CGAL and Solvers - **Breaking change**: `CGAL::Diagonalize_traits` is now deprecated diff --git a/Interpolation/doc/Interpolation/CGAL/sibson_gradient_fitting.h b/Interpolation/doc/Interpolation/CGAL/sibson_gradient_fitting.h index bd616271d4e..b3e70f96ca1 100644 --- a/Interpolation/doc/Interpolation/CGAL/sibson_gradient_fitting.h +++ b/Interpolation/doc/Interpolation/CGAL/sibson_gradient_fitting.h @@ -86,8 +86,7 @@ function \ref PkgInterpolationNaturalNeighborCoordinates2. \tparam OutputFunctor must be a functor with argument type `std::pair`. Note that the result type of the functor is not specified and is chosen by users to fit their needs. \tparam ValueFunctor must be a functor where: -- `ValueFunctor::argument_type` must be either `std::pair` -or `std::pair`. +- `ValueFunctor::argument_type` must be either `Dt::Vertex_handle` or `Dt::Point`. - `ValueFunctor::result_type` is a pair of the function value type and a Boolean. The function value type must provide a multiplication and addition operation with the type `Traits::FT` as well as a constructor with argument `0`. @@ -124,8 +123,7 @@ functions \ref PkgInterpolationRegularNeighborCoordinates2. \tparam OutputFunctor must be a functor with argument type `std::pair`. Note that the result type of the functor is not specified and is chosen by users to fit their needs. \tparam ValueFunctor must be a functor where: -- `ValueFunctor::argument_type` must be either `std::pair` -or `std::pair`. +- `ValueFunctor::argument_type` must be either `Rt::Vertex_handle` or `Rt::Weighted_point`. - `ValueFunctor::result_type` is a pair of the function value type and a Boolean. The function value type must provide a multiplication and addition operation with the type `Traits::FT` as well as a constructor with argument `0`. diff --git a/Interpolation/examples/Interpolation/interpolation_vertex_with_info_2.cpp b/Interpolation/examples/Interpolation/interpolation_vertex_with_info_2.cpp index 99a58929525..b43a2b1535e 100644 --- a/Interpolation/examples/Interpolation/interpolation_vertex_with_info_2.cpp +++ b/Interpolation/examples/Interpolation/interpolation_vertex_with_info_2.cpp @@ -94,6 +94,7 @@ int main() Delaunay_triangulation T; + // Note that a supported alternative to creating the functors below is to use lambdas Value_function value_function; Gradient_function gradient_function; diff --git a/Interpolation/examples/Interpolation/sibson_interpolation_rn_vertex_with_info_2.cpp b/Interpolation/examples/Interpolation/sibson_interpolation_rn_vertex_with_info_2.cpp index 434b911d9fd..d86378ebf04 100644 --- a/Interpolation/examples/Interpolation/sibson_interpolation_rn_vertex_with_info_2.cpp +++ b/Interpolation/examples/Interpolation/sibson_interpolation_rn_vertex_with_info_2.cpp @@ -73,6 +73,7 @@ int main() { Regular_triangulation rt; + // Note that a supported alternative to creating the functors below is to use lambdas Value_function value_function; Gradient_function gradient_function; diff --git a/Interpolation/examples/Interpolation/sibson_interpolation_vertex_with_info_2.cpp b/Interpolation/examples/Interpolation/sibson_interpolation_vertex_with_info_2.cpp index d5373c62e1b..8e74eab6aa1 100644 --- a/Interpolation/examples/Interpolation/sibson_interpolation_vertex_with_info_2.cpp +++ b/Interpolation/examples/Interpolation/sibson_interpolation_vertex_with_info_2.cpp @@ -74,6 +74,7 @@ int main() { Delaunay_triangulation dt; + // Note that a supported alternative to creating the functors below is to use lambdas Value_function value_function; Gradient_function gradient_function; diff --git a/Interpolation/include/CGAL/interpolation_functions.h b/Interpolation/include/CGAL/interpolation_functions.h index 3efe93387d3..cac67d5aa40 100644 --- a/Interpolation/include/CGAL/interpolation_functions.h +++ b/Interpolation/include/CGAL/interpolation_functions.h @@ -27,6 +27,8 @@ #include #include +#include + #include #include #include @@ -58,17 +60,21 @@ struct Data_access //the interpolation functions: template < class ForwardIterator, class ValueFunctor > -typename ValueFunctor::result_type::first_type +typename boost::result_of< + ValueFunctor(typename std::iterator_traits::value_type::first_type)> + ::type::first_type linear_interpolation(ForwardIterator first, ForwardIterator beyond, const typename std::iterator_traits::value_type::second_type& norm, ValueFunctor value_function) { CGAL_precondition(norm > 0); - typedef typename ValueFunctor::result_type::first_type Value_type; + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type result_type; + typedef typename result_type::first_type Value_type; Value_type result(0); - typename ValueFunctor::result_type val; + result_type val; for(; first!=beyond; ++first) { val = value_function(first->first); @@ -78,9 +84,12 @@ linear_interpolation(ForwardIterator first, ForwardIterator beyond, return result; } - template < class ForwardIterator, class ValueFunctor, class GradFunctor, class Traits, class Point > -std::pair< typename ValueFunctor::result_type::first_type, bool> +std::pair< + typename boost::result_of< + ValueFunctor(typename std::iterator_traits::value_type::first_type)> + ::type::first_type, + bool> quadratic_interpolation(ForwardIterator first, ForwardIterator beyond, const typename std::iterator_traits::value_type::second_type& norm, const Point& p, @@ -89,15 +98,20 @@ quadratic_interpolation(ForwardIterator first, ForwardIterator beyond, const Traits& traits) { CGAL_precondition(norm > 0); - typedef typename ValueFunctor::result_type::first_type Value_type; - typedef typename Traits::Point_d Bare_point; + + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + typedef typename boost::result_of::type gradient_functor_result_type; + typedef typename value_functor_result_type::first_type Value_type; + + typedef typename Traits::Point_d Bare_point; Interpolation::internal::Extract_bare_point cp(traits); const Bare_point& bp = cp(p); Value_type result(0); - typename ValueFunctor::result_type f; - typename GradFunctor::result_type grad; + value_functor_result_type f; + gradient_functor_result_type grad; for(; first!=beyond; ++first) { @@ -119,7 +133,11 @@ quadratic_interpolation(ForwardIterator first, ForwardIterator beyond, template < class ForwardIterator, class ValueFunctor, class GradFunctor, class Traits, class Point > -std::pair< typename ValueFunctor::result_type::first_type, bool > +std::pair< + typename boost::result_of< + ValueFunctor(typename std::iterator_traits::value_type::first_type)> + ::type::first_type, + bool> sibson_c1_interpolation(ForwardIterator first, ForwardIterator beyond, const typename std::iterator_traits::value_type::second_type& norm, const Point& p, @@ -129,17 +147,21 @@ sibson_c1_interpolation(ForwardIterator first, ForwardIterator beyond, { CGAL_precondition(norm >0); - typedef typename ValueFunctor::result_type::first_type Value_type; - typedef typename Traits::FT Coord_type; - typedef typename Traits::Point_d Bare_point; + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + typedef typename boost::result_of::type gradient_functor_result_type; + typedef typename value_functor_result_type::first_type Value_type; + + typedef typename Traits::FT Coord_type; + typedef typename Traits::Point_d Bare_point; Interpolation::internal::Extract_bare_point cp(traits); const Bare_point& bp = cp(p); Coord_type term1(0), term2(term1), term3(term1), term4(term1); Value_type linear_int(0), gradient_int(0); - typename ValueFunctor::result_type f; - typename GradFunctor::result_type grad; + value_functor_result_type f; + gradient_functor_result_type grad; for(; first!=beyond; ++first) { @@ -193,7 +215,11 @@ sibson_c1_interpolation(ForwardIterator first, ForwardIterator beyond, // gradient_int += (coeff/inv_weight) * (vh->get_value()+ vh->get_gradient() * (p - vh->point())); template < class ForwardIterator, class ValueFunctor, class GradFunctor, class Traits, class Point > -std::pair< typename ValueFunctor::result_type::first_type, bool > +std::pair< + typename boost::result_of< + ValueFunctor(typename std::iterator_traits::value_type::first_type)> + ::type::first_type, + bool> sibson_c1_interpolation_square(ForwardIterator first, ForwardIterator beyond, const typename std::iterator_traits::value_type::second_type& norm, const Point& p, @@ -203,17 +229,21 @@ sibson_c1_interpolation_square(ForwardIterator first, ForwardIterator beyond, { CGAL_precondition(norm > 0); - typedef typename ValueFunctor::result_type::first_type Value_type; - typedef typename Traits::FT Coord_type; - typedef typename Traits::Point_d Bare_point; + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + typedef typename boost::result_of::type gradient_functor_result_type; + typedef typename value_functor_result_type::first_type Value_type; + + typedef typename Traits::FT Coord_type; + typedef typename Traits::Point_d Bare_point; Interpolation::internal::Extract_bare_point cp(traits); const Bare_point& bp = cp(p); Coord_type term1(0), term2(term1), term3(term1), term4(term1); Value_type linear_int(0), gradient_int(0); - typename ValueFunctor::result_type f; - typename GradFunctor::result_type grad; + value_functor_result_type f; + gradient_functor_result_type grad; for(; first!=beyond; ++first) { @@ -257,7 +287,11 @@ sibson_c1_interpolation_square(ForwardIterator first, ForwardIterator beyond, template < class RandomAccessIterator, class ValueFunctor, class GradFunctor, class Traits, class Point_> -std::pair< typename ValueFunctor::result_type::first_type, bool> +std::pair< + typename boost::result_of< + ValueFunctor(typename std::iterator_traits::value_type::first_type)> + ::type::first_type, + bool> farin_c1_interpolation(RandomAccessIterator first, RandomAccessIterator beyond, const typename std::iterator_traits::value_type::second_type& norm, @@ -268,14 +302,16 @@ farin_c1_interpolation(RandomAccessIterator first, { CGAL_precondition(norm >0); - // the function value is available for all points - // if a gradient value is not availble: function returns false - typedef typename ValueFunctor::result_type::first_type Value_type; - typedef typename Traits::FT Coord_type; + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + typedef typename boost::result_of::type gradient_functor_result_type; + typedef typename value_functor_result_type::first_type Value_type; + + typedef typename Traits::FT Coord_type; Interpolation::internal::Extract_bare_point cp(traits); - typename ValueFunctor::result_type f; - typename GradFunctor::result_type grad; + value_functor_result_type f; + gradient_functor_result_type grad; int n = static_cast(beyond - first); if(n == 1) diff --git a/Interpolation/include/CGAL/sibson_gradient_fitting.h b/Interpolation/include/CGAL/sibson_gradient_fitting.h index 04830e4845c..5590130edba 100644 --- a/Interpolation/include/CGAL/sibson_gradient_fitting.h +++ b/Interpolation/include/CGAL/sibson_gradient_fitting.h @@ -29,14 +29,22 @@ #include #include +#include +#include #include -#include +#include +#include #include #include #include +#ifdef CGAL_CXX11 + #include + #include +#endif + namespace CGAL { template < class ForwardIterator, class ValueFunctor, class Traits, class Point > @@ -45,12 +53,17 @@ sibson_gradient_fitting(ForwardIterator first, ForwardIterator beyond, const typename std::iterator_traits::value_type::second_type& norm, const Point& p, - const typename ValueFunctor::result_type::first_type fn, + const typename boost::result_of< + ValueFunctor(typename std::iterator_traits::value_type::first_type)> + ::type::first_type fn, ValueFunctor value_function, const Traits& traits) { CGAL_precondition( first != beyond && norm != 0); + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + typedef typename Traits::Aff_transformation_d Aff_transformation; typedef typename Traits::FT Coord_type; typedef typename Traits::Point_d Bare_point; @@ -69,7 +82,7 @@ sibson_gradient_fitting(ForwardIterator first, typename Traits::Vector_d d = traits.construct_vector_d_object()(bp, bare_f); // compute the vector pn: - typename ValueFunctor::result_type f = value_function(first->first); + value_functor_result_type f = value_function(first->first); CGAL_assertion(f.second); // function value of first->first is valid pn = pn + traits.construct_scaled_vector_d_object()(d, scale * (f.first - fn)); @@ -91,7 +104,10 @@ sibson_gradient_fitting(ForwardIterator first, ValueFunctor value_function, const Traits& traits) { - typename ValueFunctor::result_type fn = value_function(p); + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + + value_functor_result_type fn = value_function(p); CGAL_assertion(fn.second); return sibson_gradient_fitting(first, beyond, norm, p, fn.first, value_function, traits); @@ -101,17 +117,20 @@ sibson_gradient_fitting(ForwardIterator first, // types of arguments and pass a final (bare) point + value to the function above. template < class ForwardIterator, class ValueFunctor, class Traits, class VH > typename Traits::Vector_d -sibson_gradient_fitting_internal(ForwardIterator first, - ForwardIterator beyond, - const typename std::iterator_traits< - ForwardIterator>::value_type::second_type& norm, - VH vh, - ValueFunctor value_function, - const Traits& traits, - const typename Traits::Point_d& /*dummy*/) +sibson_gradient_fitting_internal_with_dummy(ForwardIterator first, + ForwardIterator beyond, + const typename std::iterator_traits< + ForwardIterator>::value_type::second_type& norm, + VH vh, + ValueFunctor value_function, + const Traits& traits, + const typename Traits::Point_d& /*dummy*/) { + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + const typename Traits::Point_d& bare_p = traits.construct_point_d_object()(vh->point()); - typename ValueFunctor::result_type fn = value_function(bare_p); + value_functor_result_type fn = value_function(bare_p); CGAL_assertion(fn.second); return sibson_gradient_fitting(first, beyond, norm, bare_p, fn.first, value_function, traits); @@ -120,16 +139,19 @@ sibson_gradient_fitting_internal(ForwardIterator first, template < class ForwardIterator, class ValueFunctor, class Traits, class VH > typename Traits::Vector_d -sibson_gradient_fitting_internal(ForwardIterator first, - ForwardIterator beyond, - const typename std::iterator_traits< - ForwardIterator>::value_type::second_type& norm, - VH vh, - ValueFunctor value_function, - const Traits& traits, - const typename Traits::Weighted_point_d& /*dummy*/) +sibson_gradient_fitting_internal_with_dummy(ForwardIterator first, + ForwardIterator beyond, + const typename std::iterator_traits< + ForwardIterator>::value_type::second_type& norm, + VH vh, + ValueFunctor value_function, + const Traits& traits, + const typename Traits::Weighted_point_d& /*dummy*/) { - typename ValueFunctor::result_type fn = value_function(vh->point()); + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + + value_functor_result_type fn = value_function(vh->point()); CGAL_assertion(fn.second); return sibson_gradient_fitting(first, beyond, norm, vh->point(), fn.first, value_function, traits); @@ -138,24 +160,28 @@ sibson_gradient_fitting_internal(ForwardIterator first, template < class ForwardIterator, class ValueFunctor, class Traits, class VH > typename Traits::Vector_d -sibson_gradient_fitting_internal(ForwardIterator first, - ForwardIterator beyond, - const typename std::iterator_traits< - ForwardIterator>::value_type::second_type& norm, - VH vh, - ValueFunctor value_function, - const Traits& traits, - VH /*dummy*/) +sibson_gradient_fitting_internal_with_dummy(ForwardIterator first, + ForwardIterator beyond, + const typename std::iterator_traits< + ForwardIterator>::value_type::second_type& norm, + VH vh, + ValueFunctor value_function, + const Traits& traits, + VH /*dummy*/) { + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + const typename Traits::Point_d& bare_p = traits.construct_point_d_object()(vh->point()); - typename ValueFunctor::result_type fn = value_function(vh); + value_functor_result_type fn = value_function(vh); CGAL_assertion(fn.second); return sibson_gradient_fitting(first, beyond, norm, bare_p, fn.first, value_function, traits); } -template < class Tr, class OutputIterator, class OutputFunctor, +template < class ValueFunctorArgType, + class Tr, class OutputIterator, class OutputFunctor, class ValueFunctor, class CoordFunctor, class Traits > OutputIterator sibson_gradient_fitting_internal(const Tr& tr, @@ -170,7 +196,7 @@ sibson_gradient_fitting_internal(const Tr& tr, typedef typename Tr::Vertex_handle Vertex_handle; Coord_type norm; - std::vector > coords; + std::vector > coords; typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(); for(; vit != tr.finite_vertices_end(); ++vit) @@ -181,13 +207,13 @@ sibson_gradient_fitting_internal(const Tr& tr, norm = compute_coordinates(tr, vit, std::back_inserter(coords), Coord_OutputFunctor()).second; *out++ = fct(std::make_pair(vit, - sibson_gradient_fitting_internal(coords.begin(), - coords.end(), - norm, - Vertex_handle(vit), - value_function, - traits, - typename ValueFunctor::argument_type()))); + sibson_gradient_fitting_internal_with_dummy(coords.begin(), + coords.end(), + norm, + Vertex_handle(vit), + value_function, + traits, + ValueFunctorArgType()))); coords.clear(); } @@ -196,12 +222,73 @@ sibson_gradient_fitting_internal(const Tr& tr, return out; } - // The following functions allow to fit the gradients for all points in // a triangulation except the convex hull points. // -> _nn2: natural_neighbor_coordinates_2 // -> _rn2: regular_neighbor_coordinates_2 // -> _sn2_3: surface_neighbor_coordinates_2_3 + +// The ugly distinction below is needed to make it work with lambdas for C++11 because std::is_constructible +// is used, which is C++11 (there is a boost equivalent, but it is said (by boost) to be relying on C++11 features +// to properly work...) +#ifdef CGAL_CXX11 + +template < class Dt, class OutputIterator, class OutputFunctor, class ValueFunctor, class Traits > +OutputIterator +sibson_gradient_fitting_nn_2(const Dt& dt, + OutputIterator out, + OutputFunctor fct, + ValueFunctor value_function, + const Traits& traits, + // Some SFINAE to distinguish whether the argument type + // of the value functor is 'DT::Point' or 'DT::Vertex_handle' + typename boost::enable_if_c< + std::is_constructible< + std::function, + ValueFunctor + >::value>::type* = NULL) +{ + typedef typename Traits::FT FT; + typedef typename Dt::Point VF_arg_type; + typedef typename std::back_insert_iterator > > CoordInserter; + typedef Interpolation::internal::Extract_point_in_pair Coord_OutputFunctor; + + return sibson_gradient_fitting_internal(dt, out, fct, value_function, + natural_neighbor_coordinates_2_object(), + traits); +} + +template < class Dt, class OutputIterator, class OutputFunctor, class ValueFunctor, class Traits > +OutputIterator +sibson_gradient_fitting_nn_2(const Dt& dt, + OutputIterator out, + OutputFunctor fct, + ValueFunctor value_function, + const Traits& traits, + typename boost::enable_if_c< + std::is_constructible< + std::function, + ValueFunctor + >::value>::type* = NULL) +{ + typedef typename Traits::FT FT; + typedef typename Dt::Vertex_handle VF_arg_type; + typedef typename std::back_insert_iterator > > CoordInserter; + typedef CGAL::Identity > Coord_OutputFunctor; + + return sibson_gradient_fitting_internal(dt, out, fct, value_function, + natural_neighbor_coordinates_2_object(), + traits); +} + +#else // not CGAL_CXX11 + template < class Dt, class OutputIterator, class OutputFunctor, class ValueFunctor, class Traits > OutputIterator sibson_gradient_fitting_nn_2(const Dt& dt, @@ -224,15 +311,16 @@ sibson_gradient_fitting_nn_2(const Dt& dt, CGAL::Identity > >::type Coord_OutputFunctor; - return sibson_gradient_fitting_internal(dt, out, fct, value_function, - natural_neighbor_coordinates_2_object(), - traits); + return sibson_gradient_fitting_internal(dt, out, fct, value_function, + natural_neighbor_coordinates_2_object(), + traits); } +#endif // CGAL_CXX11 - -// Same as above but without OutputFunctor. Default to extracting the point, for backward compatibility. +// Same as above but without OutputFunctor. +// Defaults to extracting the point, for backward compatibility. template < class Dt, class OutputIterator, class ValueFunctor, class Traits > OutputIterator sibson_gradient_fitting_nn_2(const Dt& dt, @@ -246,6 +334,64 @@ sibson_gradient_fitting_nn_2(const Dt& dt, return sibson_gradient_fitting_nn_2(dt, out, OutputFunctor(), value_function, traits); } +// See above for the explanation. +#ifdef CGAL_CXX11 + +template < class Rt, class OutputIterator, class OutputFunctor, class ValueFunctor, class Traits > +OutputIterator +sibson_gradient_fitting_rn_2(const Rt& rt, + OutputIterator out, + OutputFunctor fct, + ValueFunctor value_function, + const Traits& traits, + // Some SFINAE to distinguish whether the argument type + // of the value functor is 'Rt::Point' (weighted point) or 'Rt::Vertex_handle' + typename boost::enable_if_c< + std::is_constructible< + std::function, + ValueFunctor + >::value>::type* = NULL) +{ + typedef typename Traits::FT FT; + typedef typename Rt::Point VF_arg_type; + typedef typename std::back_insert_iterator > > CoordInserter; + typedef Interpolation::internal::Extract_point_in_pair Coord_OutputFunctor; + + return sibson_gradient_fitting_internal(rt, out, fct, value_function, + regular_neighbor_coordinates_2_object(), + traits); +} + +template < class Rt, class OutputIterator, class OutputFunctor, class ValueFunctor, class Traits > +OutputIterator +sibson_gradient_fitting_rn_2(const Rt& rt, + OutputIterator out, + OutputFunctor fct, + ValueFunctor value_function, + const Traits& traits, + typename boost::enable_if_c< + std::is_constructible< + std::function, + ValueFunctor + >::value>::type* = NULL) +{ + typedef typename Traits::FT FT; + typedef typename Rt::Vertex_handle VF_arg_type; + typedef typename std::back_insert_iterator > > CoordInserter; + typedef CGAL::Identity > Coord_OutputFunctor; + + return sibson_gradient_fitting_internal(rt, out, fct, value_function, + regular_neighbor_coordinates_2_object(), + traits); +} + +#else // CGAL_CXX11 template < class Rt, class OutputIterator, class OutputFunctor, class ValueFunctor, class Traits > OutputIterator @@ -269,13 +415,14 @@ sibson_gradient_fitting_rn_2(const Rt& rt, CGAL::Identity > >::type Coord_OutputFunctor; - return sibson_gradient_fitting_internal(rt, out, fct, value_function, - regular_neighbor_coordinates_2_object(), - traits); + return sibson_gradient_fitting_internal(rt, out, fct, value_function, + regular_neighbor_coordinates_2_object(), + traits); } +#endif // Same as above but without OutputFunctor. Default to extracting the point, for backward compatibility. template < class Rt, class OutputIterator, class ValueFunctor, class Traits > diff --git a/Interpolation/test/Interpolation/include/CGAL/_test_interpolation_functions_2.cpp b/Interpolation/test/Interpolation/include/CGAL/_test_interpolation_functions_2.cpp index 88818490ccd..022efc4cbc7 100644 --- a/Interpolation/test/Interpolation/include/CGAL/_test_interpolation_functions_2.cpp +++ b/Interpolation/test/Interpolation/include/CGAL/_test_interpolation_functions_2.cpp @@ -31,11 +31,14 @@ #include #include #include +#include #include #include #include #include +#include + #include #include #include @@ -47,6 +50,8 @@ struct Extract_point typedef typename Traits::Point_2 Point_2; typedef typename Traits::Weighted_point_2 Weighted_point_2; + typedef typename Traits::Construct_point_2 Construct_point_2; + Extract_point(const Traits& traits = Traits()) : traits(traits) {} const Point_2& operator()(const Point_2& p) const { return p; } @@ -56,7 +61,8 @@ struct Extract_point } template - const Point_2& operator()(const VH& vh) const { + typename boost::result_of::type + operator()(const VH& vh) const { return traits.construct_point_2_object()(vh->point()); } @@ -64,6 +70,42 @@ private: Traits traits; }; +template +struct Value_function +{ + typedef V argument_type; + typedef std::pair result_type; + + Value_function(std::size_t i) : index(i) { } + + result_type operator()(const argument_type& a) const { + return result_type(a->info()[index].value, true); + } + +private: + std::size_t index; +}; + +template +struct Gradient_function + : public CGAL::cpp98::iterator +{ + + typedef V argument_type; + typedef std::pair result_type; + + Gradient_function(std::size_t i) : index(i) { } + + result_type operator()(const argument_type& a) const { + return std::make_pair(a->info()[index].gradient, + a->info()[index].gradient != CGAL::NULL_VECTOR); + } + +private: + std::size_t index; +}; + + template < class ForwardIterator > bool test_norm(ForwardIterator first, ForwardIterator beyond, typename std::iterator_traits::value_type::second_type norm) @@ -83,10 +125,10 @@ bool test_norm(ForwardIterator first, ForwardIterator beyond, } } -template < class Tr, class ForwardIterator > +template < class Tr, class ForwardIterator, class Point > bool test_barycenter(ForwardIterator first, ForwardIterator beyond, typename std::iterator_traits::value_type::second_type norm, - const typename std::iterator_traits::value_type::first_type& p, + const Point& p, const typename std::iterator_traits::value_type::second_type& tolerance) { typedef typename Tr::Geom_traits Gt; @@ -133,9 +175,13 @@ bool _test_sibson_c1_interpolation_sqrt(ForwardIterator first, ForwardIterator b const typename std::iterator_traits::value_type::second_type& exact_value, CGAL::Field_with_sqrt_tag) { - typename ValueFunctor::result_type res = CGAL::sibson_c1_interpolation(first, beyond, - norm, p, f, - grad_f, geom_traits); + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + + value_functor_result_type res = CGAL::sibson_c1_interpolation(first, beyond, + norm, p, f, + grad_f, geom_traits); + return res.second && (CGAL_NTS abs(res.first-exact_value) <= tolerance); } @@ -143,14 +189,18 @@ template < class ForwardIterator, class ValueFunctor, class GradFunctor, class G bool test_interpolation_with_value(ForwardIterator first, ForwardIterator beyond, const typename std::iterator_traits::value_type::second_type& norm, const Point& p, - const typename ValueFunctor::result_type::first_type exact_value, + const typename boost::result_of< + ValueFunctor(typename std::iterator_traits::value_type::first_type)> + ::type::first_type exact_value, ValueFunctor f, GradFunctor grad_f, const Gt& geom_traits, const int& i, const typename std::iterator_traits::value_type::second_type& tolerance) { - typedef typename ValueFunctor::result_type::first_type Value_type; + typedef typename std::iterator_traits::value_type::first_type arg_type; + typedef typename boost::result_of::type value_functor_result_type; + typedef typename value_functor_result_type::first_type Value_type; if(i == 0) { @@ -158,8 +208,8 @@ bool test_interpolation_with_value(ForwardIterator first, ForwardIterator beyond assert(CGAL_NTS abs(val - exact_value) <= tolerance); } - typename ValueFunctor::result_type res = CGAL::quadratic_interpolation(first, beyond, norm, p, f, - grad_f, geom_traits); + value_functor_result_type res = CGAL::quadratic_interpolation(first, beyond, norm, p, f, + grad_f, geom_traits); assert(res.second && (CGAL_NTS abs(res.first - exact_value) <= tolerance)); if(i<2) @@ -185,20 +235,17 @@ bool test_interpolation_with_value(ForwardIterator first, ForwardIterator beyond return true; } -template < class ForwardIterator, class ValueFunctor, class GradFunctor, class Gt, class Point> +template < class ForwardIterator, class ValueFunctor, class GradFunctor, class Gt, class Point, class Value_type> bool test_interpolation(ForwardIterator first, ForwardIterator beyond, const typename std::iterator_traits::value_type::second_type& norm, const Point& p, + const Value_type exact_value, ValueFunctor f, GradFunctor grad_f, const Gt& geom_traits, const int& i, const typename std::iterator_traits::value_type::second_type& tolerance) { - typedef typename ValueFunctor::result_type::first_type Value_type; - assert(f(p).second); - Value_type exact_value = f(p).first; - return test_interpolation_with_value(first, beyond, norm, p, exact_value, f, grad_f, geom_traits, i, tolerance); } @@ -222,7 +269,7 @@ void _test_interpolation_functions_2_Delaunay_without_OutputFunctor(const Dt&, c typedef typename Gt::FT Coord_type; typedef typename Gt::Vector_2 Vector; - typedef std::map Point_value_map ; + typedef std::map Point_value_map; typedef std::map Point_vector_map; typedef std::vector > Point_coordinate_vector; @@ -308,7 +355,8 @@ void _test_interpolation_functions_2_Delaunay_without_OutputFunctor(const Dt&, c for(int i=0; i<3; ++i) { - assert(test_interpolation(coords.begin(), coords.end(), norm, points[j], + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[j], values[i][points[j]], CGAL::Data_access< Point_value_map >(values[i]), CGAL::Data_access< Point_vector_map >(gradients[i]), Traits(), i, tolerance)); @@ -368,7 +416,8 @@ void _test_interpolation_functions_2_Delaunay_without_OutputFunctor(const Dt&, c for(int j=0; j<3; ++j) { - assert(test_interpolation(coords.begin(), coords.end(), norm, points[n/2], + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[n/2], values[j][points[n/2]], CGAL::Data_access(values[j]), CGAL::Data_access(gradients[j]), Traits(), j, tolerance)); @@ -391,16 +440,18 @@ void _test_interpolation_functions_2_Delaunay_with_OutputFunctor(const Dt&, cons typedef typename Dt::Geom_traits Gt; typedef CGAL::Interpolation_traits_2 Traits; + typedef typename Dt::Vertex_handle Vertex_handle; + typedef typename Gt::FT Coord_type; typedef typename Dt::Point Point; typedef typename Gt::Vector_2 Vector; - typedef std::map Point_value_map ; - typedef std::map Point_vector_map; + typedef std::vector > Coordinate_vector; + typedef typename Coordinate_vector::const_iterator CV_cit; + typedef CGAL::Identity > Output_functor; - typedef std::vector > Point_coordinate_vector; - typedef typename Point_coordinate_vector::const_iterator PCV_cit; - typedef CGAL::Interpolation::internal::Extract_point_in_pair Point_output_functor; + typedef std::map Point_value_map; + typedef std::map Point_vector_map; std::cout << "NN2: Testing random points." << std::endl; @@ -420,9 +471,6 @@ void _test_interpolation_functions_2_Delaunay_with_OutputFunctor(const Dt&, cons CGAL::Random random; - Point_value_map values[3]; - Point_vector_map gradients[3]; - Coord_type alpha = Coord_type(random.get_double(-max_value, max_value)), beta1 = Coord_type(random.get_double(-max_value, max_value)), beta2 = Coord_type(random.get_double(-max_value, max_value)), @@ -431,67 +479,110 @@ void _test_interpolation_functions_2_Delaunay_with_OutputFunctor(const Dt&, cons gamma3 = Coord_type(random.get_double(-max_value, max_value)); //INSERTION + DET. of GRADIENT for n DATA POINTS : - for(int j=0; j p_to_vh; + + for(int j=0; jinfo()[0].gradient = gradient0; + vh->info()[1].gradient = gradient1; + vh->info()[2].gradient = gradient2; + + + vh->info()[0].value = value0; + vh->info()[1].value = value1; + vh->info()[2].value = value2; + } + else + { + exact_values[0][points[j]] = value0; + exact_values[1][points[j]] = value1; + exact_values[2][points[j]] = value2; + } } //INTERPOLATION OF RANDOM POINTS: Coord_type norm; - Point_coordinate_vector pt_coords; - Point_output_functor pt_fct; + Coordinate_vector coords; + Output_functor out_fct; for(int j=n; j, Coord_type, bool> coordinate_result = - CGAL::natural_neighbor_coordinates_2(T, points[j], std::back_inserter(pt_coords), pt_fct); + CGAL::Triple, Coord_type, bool> coordinate_result = + CGAL::natural_neighbor_coordinates_2(T, points[j], std::back_inserter(coords), out_fct); assert(coordinate_result.third); norm = coordinate_result.second; - bool is_equal = test_norm(pt_coords.begin(), pt_coords.end(), norm); + bool is_equal = test_norm(coords.begin(), coords.end(), norm); assert(norm > 0); assert(is_equal); - is_equal = test_barycenter
(pt_coords.begin(), pt_coords.end(), norm, points[j], tolerance); + is_equal = test_barycenter
(coords.begin(), coords.end(), norm, points[j], tolerance); assert(is_equal); +#ifdef CGAL_CXX11 + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[j], exact_values[0][points[j]], + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[0].value, true); }, + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[0].gradient, true); }, + Traits(), 0, tolerance)); + + + // wrapping the lambda in a std function + CGAL::cpp11::function(const Vertex_handle)> value_function_1 = + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[1].value, true); }; + + std::function(const Vertex_handle)> gradient_function_1 = + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[1].gradient, true); }; + + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[j], exact_values[1][points[j]], + value_function_1, gradient_function_1, + Traits(), 1, tolerance)); + + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[j], exact_values[2][points[j]], + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[2].value, true); }, + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[2].gradient, true); }, + Traits(), 2, tolerance)); +#else for(int i=0; i<3; ++i) { - assert(test_interpolation(pt_coords.begin(), pt_coords.end(), norm, points[j], - CGAL::Data_access< Point_value_map >(values[i]), - CGAL::Data_access< Point_vector_map >(gradients[i]), + Value_function value_function(i); + Gradient_function gradient_function(i); + + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[j], exact_values[i][points[j]], + value_function, gradient_function, Traits(), i, tolerance)); } - pt_coords.clear(); +#endif + + coords.clear(); } //TESTING THE GRADIENT APPRXIMATION METHOD: @@ -499,18 +590,44 @@ void _test_interpolation_functions_2_Delaunay_with_OutputFunctor(const Dt&, cons std::cout << "Testing gradient estimation method on random points." << std::endl; typedef CGAL::Interpolation_gradient_fitting_traits_2 GradTraits; + Point_vector_map approx_gradients[2]; + +#ifdef CGAL_CXX11 + { + CGAL::sibson_gradient_fitting_nn_2(T, + std::inserter(approx_gradients[0], approx_gradients[0].begin()), // OutputIterator + CGAL::Interpolation::internal::Extract_point_in_pair(), // OutputFunctor + [](const Vertex_handle vh) + -> std::pair + { return std::make_pair(vh->info()[0].value, true); }, + GradTraits()); + + std::function(const Vertex_handle)> value_function_1 = + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[1].value, true); }; + + CGAL::sibson_gradient_fitting_nn_2(T, + std::inserter(approx_gradients[1], approx_gradients[1].begin()), + CGAL::Interpolation::internal::Extract_point_in_pair(), + value_function_1, + GradTraits()); + } +#else + Value_function value_function_0(0); + Value_function value_function_1(1); + CGAL::sibson_gradient_fitting_nn_2(T, std::inserter(approx_gradients[0], approx_gradients[0].begin()), // OutputIterator CGAL::Interpolation::internal::Extract_point_in_pair(), // OutputFunctor - CGAL::Data_access(values[0]), // ValueFunctor + value_function_0, GradTraits()); CGAL::sibson_gradient_fitting_nn_2(T, std::inserter(approx_gradients[1], approx_gradients[1].begin()), CGAL::Interpolation::internal::Extract_point_in_pair(), - CGAL::Data_access(values[1]), + value_function_1, GradTraits()); +#endif for(int j=0; j gradient_function_0(0); + Gradient_function gradient_function_1(1); + // if it is the exact computation kernel: test the equality: assert(tolerance > Coord_type(0) || - res.first == CGAL::Data_access(gradients[0])(points[j]).first); + res.first == (gradient_function_0(p_to_vh[points[j]])).first); res = CGAL::Data_access(approx_gradients[1])(points[j]); // if one exists->the other must also exist assert(res.second); assert(tolerance > Coord_type(0) || - res.first == CGAL::Data_access(gradients[1])(points[j]).first); + res.first == gradient_function_1(p_to_vh[points[j]]).first); } else { @@ -536,31 +656,66 @@ void _test_interpolation_functions_2_Delaunay_with_OutputFunctor(const Dt&, cons } //TESTING A POINT == A DATA POINT: - CGAL::Triple, Coord_type, bool> coordinate_result = - CGAL::natural_neighbor_coordinates_2(T, points[n/2], std::back_inserter(pt_coords), pt_fct); + CGAL::Triple, Coord_type, bool> coordinate_result = + CGAL::natural_neighbor_coordinates_2(T, points[n/2], std::back_inserter(coords), out_fct); assert(coordinate_result.third); norm = coordinate_result.second; assert(norm == Coord_type(1)); - PCV_cit ci = pt_coords.begin(); - assert(ci->first == points[n/2]); + CV_cit ci = coords.begin(); + assert(ci->first == p_to_vh[points[n/2]]); assert(ci->second == Coord_type(1)); ci++; - assert(ci == pt_coords.end()); + assert(ci == coords.end()); +#ifdef CGAL_CXX11 + Value_function value_function_0(0); + Value_function value_function_2(2); + + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[n/2], value_function_0(p_to_vh[points[n/2]]).first, + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[0].value, true); }, + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[0].gradient, true); }, + Traits(), 0, tolerance)); + + // wrapping the lambda in a std function + CGAL::cpp11::function(const Vertex_handle)> value_function_1 = + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[1].value, true); }; + + std::function(const Vertex_handle)> gradient_function_1 = + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[1].gradient, true); }; + + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[n/2], value_function_1(p_to_vh[points[n/2]]).first, + value_function_1, gradient_function_1, + Traits(), 1, tolerance)); + + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[n/2], value_function_2(p_to_vh[points[n/2]]).first, + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[2].value, true); }, + [](const Vertex_handle vh) -> std::pair { return std::make_pair(vh->info()[2].gradient, true); }, + Traits(), 2, tolerance)); +#else for(int j=0; j<3; ++j) { - assert(test_interpolation(pt_coords.begin(), pt_coords.end(), norm, points[n/2], - CGAL::Data_access(values[j]), - CGAL::Data_access(gradients[j]), + Value_function value_function(j); + Gradient_function gradient_function(j); + + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[n/2], value_function(p_to_vh[points[n/2]]).first, + value_function, gradient_function, Traits(), j, tolerance)); } - pt_coords.clear(); +#endif + + coords.clear(); } template void _test_interpolation_functions_2_regular_without_OutputFunctor(const Rt&, const typename Rt::Geom_traits::FT& tolerance) { + std::cout << "Testing backward compatibility..." << std::endl; + CGAL::Set_ieee_double_precision pfr; Rt T; @@ -577,12 +732,12 @@ void _test_interpolation_functions_2_regular_without_OutputFunctor(const Rt&, co typedef typename Gt::FT Coord_type; typedef typename Gt::Vector_2 Vector; - typedef std::map Point_value_map ; + typedef std::map Point_value_map; typedef std::map Point_vector_map; typedef std::vector > Point_coordinate_vector; - std::cout << "NN2: Testing random points." << std::endl; + std::cout << "RN2: Testing random points." << std::endl; // test random points in a square of length r: std::vector points; @@ -674,7 +829,8 @@ void _test_interpolation_functions_2_regular_without_OutputFunctor(const Rt&, co for(int i=0; i<3; ++i) { - assert(test_interpolation(coords.begin(), coords.end(), norm, points[j], + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[j], values[i][points[j]], CGAL::Data_access< Point_value_map >(values[i]), CGAL::Data_access< Point_vector_map >(gradients[i]), Traits(), i, tolerance)); @@ -735,7 +891,8 @@ void _test_interpolation_functions_2_regular_without_OutputFunctor(const Rt&, co for(int j=0; j<3; ++j) { - assert(test_interpolation(coords.begin(), coords.end(), norm, points[n/2], + assert(test_interpolation(coords.begin(), coords.end(), norm, + points[n/2], values[j][points[n/2]], CGAL::Data_access(values[j]), CGAL::Data_access(gradients[j]), Traits(), j, tolerance)); @@ -771,7 +928,7 @@ void _test_interpolation_functions_2_regular_with_OutputFunctor(const Rt&, const typedef typename Rt::Vertex_handle Vertex_handle; // These are the values at points which won't be inserted in the triangulation - typedef std::map Point_value_map ; + typedef std::map Point_value_map; typedef std::map Vertex_value_map; typedef std::map Vertex_vector_map; @@ -782,7 +939,7 @@ void _test_interpolation_functions_2_regular_with_OutputFunctor(const Rt&, const Identity_output_functor vh_fct; - std::cout << "NN2: Testing random points." << std::endl; + std::cout << "RN2: Testing random points." << std::endl; // test random points in a square of length r: std::vector points; @@ -979,8 +1136,8 @@ void _test_interpolation_functions_2_regular_with_OutputFunctor(const Rt&, const std::pair ev = CGAL::Data_access(values[j])(vh); assert(ev.second); - assert(test_interpolation_with_value(vh_coords.begin(), vh_coords.end(), norm, vh->point(), - ev.first /*exact value*/, + assert(test_interpolation_with_value(vh_coords.begin(), vh_coords.end(), norm, + vh->point(), ev.first /*exact value*/, CGAL::Data_access(values[j]), CGAL::Data_access(gradients[j]), Traits(), j, tolerance)); diff --git a/Interpolation/test/Interpolation/test_interpolation_functions_2.cpp b/Interpolation/test/Interpolation/test_interpolation_functions_2.cpp index ca18ef2faf2..c43b255d071 100644 --- a/Interpolation/test/Interpolation/test_interpolation_functions_2.cpp +++ b/Interpolation/test/Interpolation/test_interpolation_functions_2.cpp @@ -21,44 +21,59 @@ #include #include +#include +#include #include #include +#include #include -typedef CGAL::Exact_predicates_exact_constructions_kernel K; -typedef CGAL::Delaunay_triangulation_2 Dt; -typedef CGAL::Regular_triangulation_2 Rt; +typedef CGAL::Exact_predicates_exact_constructions_kernel EPECK; +typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK; -typedef CGAL::Exact_predicates_inexact_constructions_kernel K2; -typedef CGAL::Delaunay_triangulation_2 Dt2; -typedef CGAL::Regular_triangulation_2 Rt2; +template +struct Value_and_gradient +{ + Value_and_gradient() : value(), gradient(CGAL::NULL_VECTOR) {} + + V value; + G gradient; +}; + +template +void test_interpolation_functions() +{ + // For the Delaunay triangulation, values and gradients (three different data sets) + // are stored directly in the vertices + typedef typename Kernel::FT Coord_type; + typedef typename Kernel::Vector_2 Vector; + + typedef CGAL::Triangulation_vertex_base_with_info_2< + CGAL::cpp11::array< + Value_and_gradient, 3>, + Kernel> Vb; + typedef CGAL::Triangulation_data_structure_2 Tds; + typedef CGAL::Delaunay_triangulation_2 Delaunay_triangulation; + + typedef CGAL::Regular_triangulation_2 Regular_triangulation; + + std::cout << "Testing interpolation functions with 2D NN neighbors " << std::endl; + _test_interpolation_functions_2_Delaunay(Delaunay_triangulation(), Coord_type(1e-10)); + + std::cout << "Testing interpolation functions with 2D RN neighbors " << std::endl; + _test_interpolation_functions_2_regular(Regular_triangulation(), Coord_type(1e-10)); +} int main() { - std::cout << "Testing interpolation functions with 2D NN neighbors " - << std::endl; - std::cout << " using Exact_predicates_exact_constructions_kernel: " - << std::endl ; - _test_interpolation_functions_2_Delaunay(Dt(), K::FT(1e-10)); + std::cout << "--------------------------------------------" << std::endl; + std::cout << "Testing with EPECK" << std::endl; + test_interpolation_functions(); - std::cout << "Testing interpolation functions with 2D NN neighbors " - << std::endl; - std::cout << " using Exact_predicates_inexact_constructions_kernel: " - << std::endl ; - _test_interpolation_functions_2_Delaunay(Dt2(), K2::FT(1e-10)); - - std::cout << "Testing interpolation functions with 2D RN neighbors " - << std::endl; - std::cout << " using Exact_predicates_exact_constructions_kernel: " - << std::endl ; - _test_interpolation_functions_2_regular(Rt(), K::FT(1e-10)); - - std::cout << "Testing interpolation functions with 2D RN neighbors " - << std::endl; - std::cout << " using Exact_predicates_inexact_constructions_kernel: " - << std::endl ; - _test_interpolation_functions_2_regular(Rt2(), K2::FT(1e-10)); + std::cout << "--------------------------------------------" << std::endl; + std::cout << "Testing with EPICK" << std::endl; + test_interpolation_functions(); std::cout << "test_interpolation_functions_2 is finished" << std::endl; diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt index 92f4874bca2..3baa705dad3 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/PackageDescription.txt @@ -100,6 +100,7 @@ and provides a list of the parameters that are used in this package. - \link PMP_meshing_grp `CGAL::Polygon_mesh_processing::isotropic_remeshing()` \endlink - \link PMP_meshing_grp `CGAL::Polygon_mesh_processing::split_long_edges()` \endlink - `CGAL::Polygon_mesh_processing::random_perturbation()` +- `CGAL::Polygon_mesh_processing::extrude_mesh()` ## Hole Filling Functions ## - `CGAL::Polygon_mesh_processing::triangulate_hole()` diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h index 38c8fbb1058..1f7383346ed 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h @@ -419,22 +419,16 @@ corefine_and_compute_boolean_operations( if (output[Corefinement::UNION] != boost::none) if (&tm1 != *output[Corefinement::UNION]) copy_face_graph(tm1, - *(*output[Corefinement::UNION]), - Emptyset_iterator(), - Emptyset_iterator(), - Emptyset_iterator(), - vpm1, - *cpp11::get(vpm_out_tuple)); - + *(*output[Corefinement::UNION]), + parameters::vertex_point_map(vpm1), + parameters::vertex_point_map(*cpp11::get(vpm_out_tuple))); if (output[Corefinement::INTERSECTION] != boost::none) if (&tm1 != *output[Corefinement::INTERSECTION]) copy_face_graph(tm1, *(*output[Corefinement::INTERSECTION]), - Emptyset_iterator(), - Emptyset_iterator(), - Emptyset_iterator(), - vpm1, - *cpp11::get(vpm_out_tuple)); + parameters::vertex_point_map(vpm1), + parameters::vertex_point_map(*cpp11::get(vpm_out_tuple))); + if (output[Corefinement::TM1_MINUS_TM2] != boost::none) if (&tm1 == *output[Corefinement::TM1_MINUS_TM2]) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/extrude.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/extrude.h new file mode 100644 index 00000000000..aecf3c39b92 --- /dev/null +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/extrude.h @@ -0,0 +1,323 @@ +// Copyright (c) 2018 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 +// 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$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Sebastien Loriot, Maxime Gimeno + + +#ifndef CGAL_POLYGON_MESH_PROCESSING_EXTRUDE_H +#define CGAL_POLYGON_MESH_PROCESSING_EXTRUDE_H + +#include + + +#include +#include +#include +#include +#include +#include +#include + +namespace CGAL { +namespace Polygon_mesh_processing { +namespace extrude_impl{ + +template +void create_strip(const BorderHalfedgesRange& input_halfedges, + const BorderHalfedgesRange& output_halfedges, + PolygonMesh& mesh) +{ + CGAL_assertion(input_halfedges.size() == output_halfedges.size()); + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + for(std::size_t i = 0; i < input_halfedges.size(); ++i) + { + halfedge_descriptor h1 = input_halfedges[i], h2=output_halfedges[i], + nh1 = next(h1, mesh), ph2 = prev(h2, mesh); + halfedge_descriptor newh = halfedge(add_edge(mesh), mesh), + newh_opp = opposite(newh, mesh); + // set target vertices of the new halfedges + set_target(newh, target(h1, mesh), mesh); + set_target(newh_opp, target(ph2, mesh), mesh); + // update next/prev pointers + set_next(h1, newh_opp, mesh); + set_next(newh_opp, h2, mesh); + set_next(ph2, newh, mesh); + set_next(newh, nh1, mesh); + } + for(std::size_t i = 0; i < input_halfedges.size(); ++i) + { + halfedge_descriptor h = input_halfedges[i]; + face_descriptor nf = add_face(mesh); + + CGAL::cpp11::array hedges; + for (int k=0; k<4; ++k) + { + hedges[k]=h; + h = next(h, mesh); + } + + set_face(hedges[0], nf, mesh); + set_face(hedges[1], nf, mesh); + set_face(hedges[2], nf, mesh); + set_face(hedges[3], nf, mesh); + set_halfedge(nf, hedges[0], mesh); + Euler::split_face(hedges[0], hedges[2], mesh); + } +} + +template +struct Const_dist_translation{ + Const_dist_translation(PMAP map, const Vector& dir) + :map(map), dir(dir){} + + template + void operator()(const VertexDescriptor vd, const U&) const + { + typename boost::property_traits::value_type p = get(map, vd) + dir; + put(map, vd, p); + } + + PMAP map; + Vector dir; +}; + +struct Identity_functor +{ + template + void operator()(const T&, const U&) const {} +}; +}//end extrude_impl + +/** + * \ingroup PMP_meshing_grp + * \brief performs a generalized extrusion of `input` and puts it in `output`. + * + * This function extrudes the open surface mesh `input` and puts the result in `output`. The mesh generated is a closed + * surface mesh with a bottom and top part, both having the same graph combinatorics as `input` (except + * that the orientation of the faces of the bottom part is reversed). The bottom and the top parts are + * connected by a triangle strip between boundary cycles. The coordinates of the points associated to the + * vertices of the bottom and top part are first initialized to the same value as the corresponding + * vertices of `input`. Then for each vertex, a call to `bot` and `top` is done for the vertices of the + * bottom part and the top part, respectively. + * \attention `output` may be self intersecting. + * @tparam InputMesh a model of `FaceListGraph` + * @tparam OutputMesh a model of `FaceListGraph` and `MutableFaceGraph` + * @tparam NamedParameters1 a sequence of \ref pmp_namedparameters "Named Parameters" for `InputMesh` + * @tparam NamedParameters2 a sequence of \ref pmp_namedparameters "Named Parameters" for `OutputMesh` + * @tparam BottomFunctor a functor providing + * \code {.cpp} + * void operator()`(boost::graph_traits::vertex_descriptor input_v,boost::graph_traits::vertex_descriptor output_v) + * \endcode + * where `output_v` is the copy of `input_v` from `input` into the bottom part of `output`. + * + * @tparam TopFunctor a functor providing a similar `operator()` as `BottomFunctor`. + * @param input an open surface mesh to extrude. + * @param output a surface mesh that will contain the result of the extrusion. + * @param bot functor that will transform all points copied from + * `input` in order to shape the bottom part of the extrusion. + * @param top functor that will transform all points copied from + * `input` in order to shape the top part of the extrusion. + * @param np_in an optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below + * + * \cgalNamedParamsBegin + * \cgalParamBegin{vertex_point_map} + * the property map that contains the points associated to the vertices of `input`. + * If this parameter is omitted, an internal property map for `CGAL::vertex_point_t` + * should be available for the vertices of `input` \cgalParamEnd + * \cgalNamedParamsEnd + * + * * @param np_out an optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below + * + * \cgalNamedParamsBegin + * \cgalParamBegin{vertex_point_map} + * the property map that will contain the points associated to the vertices of `output`. + * If this parameter is omitted, an internal property map for `CGAL::vertex_point_t` + * should be available for the vertices of `output` \cgalParamEnd + * \cgalNamedParamsEnd + */ +template +void extrude_mesh(const InputMesh& input, + OutputMesh& output, + const BottomFunctor& bot, + const TopFunctor& top, + const NamedParameters1& np_in, + const NamedParameters2& np_out) +{ + typedef typename boost::graph_traits::vertex_descriptor input_vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor input_halfedge_descriptor; + + typedef typename boost::graph_traits::vertex_descriptor output_vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor output_halfedge_descriptor; + + CGAL_assertion(!CGAL::is_closed(input)); + typedef typename GetVertexPointMap < OutputMesh, NamedParameters2>::type VPMap; + typedef typename GetVertexPointMap < InputMesh, NamedParameters1>::const_type IVPMap; + + VPMap output_vpm = choose_param(get_param(np_out, internal_np::vertex_point), + get_property_map(vertex_point, output)); + IVPMap input_vpm = choose_param(get_param(np_in, internal_np::vertex_point), + get_const_property_map(vertex_point, input)); + + std::vector > bottom_v2v; + std::vector > bottom_h2h; + copy_face_graph(input, output, std::back_inserter(bottom_v2v), + std::back_inserter(bottom_h2h), Emptyset_iterator(), + input_vpm, output_vpm); + + // create the offset for the other side + for(std::size_t i = 0; i< bottom_v2v.size(); ++i) + { + bot(bottom_v2v[i].first, bottom_v2v[i].second); + } + CGAL::Polygon_mesh_processing::reverse_face_orientations(output); + + // collect border halfedges for the creation of the triangle strip + std::vector > top_v2v; + std::vector > top_h2h; + copy_face_graph(input, output, std::inserter(top_v2v, top_v2v.end()), + std::inserter(top_h2h, top_h2h.end()), Emptyset_iterator(), + input_vpm, output_vpm); + for(std::size_t i = 0; i< top_v2v.size(); ++i) + { + top(top_v2v[i].first, top_v2v[i].second); + } + std::vector border_hedges; + std::vector offset_border_hedges; + for(std::size_t i = 0; i< top_h2h.size(); ++i) + { + input_halfedge_descriptor h = top_h2h[i].first; + if( CGAL::is_border(h, input) ) + { + border_hedges.push_back(top_h2h[i].second); + offset_border_hedges.push_back(bottom_h2h[i].second); + CGAL_assertion(is_border(border_hedges.back(), output)); + CGAL_assertion(is_border(offset_border_hedges.back(), output)); + } + } + // now create a triangle strip + extrude_impl::create_strip(border_hedges, offset_border_hedges, output); +} + + +/** + * \ingroup PMP_meshing_grp + * fills `output` with a closed mesh bounding the volume swept by `input` when translating its + * vertices by `v`. The mesh is oriented so that the faces corresponding to `input` + * in `output` have the same orientation. + * \attention `output` may be self intersecting. + * @tparam InputMesh a model of the concept `FaceListGraph` + * @tparam OutputMesh a model of the concept `FaceListGraph` and `MutableFaceGraph` + * @tparam Vector_3 vector type from the same CGAL kernel as the point of the vertex point map used for `OutputMesh`. + * @tparam NamedParameters1 a sequence of \ref pmp_namedparameters "Named Parameters" for `InputMesh` + * @tparam NamedParameters2 a sequence of \ref pmp_namedparameters "Named Parameters" for `OutputMesh` + * @param input an open surface mesh to extrude. + * @param output a surface mesh that will contain the result of the extrusion. + * @param v the vector defining the direction of the extrusion + * @param np_in an optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below + * + * \cgalNamedParamsBegin + * \cgalParamBegin{vertex_point_map} + * the property map that contains the points associated to the vertices of `input`. + * If this parameter is omitted, an internal property map for `CGAL::vertex_point_t` + * should be available for the vertices of `input` \cgalParamEnd + * \cgalNamedParamsEnd + * + * * @param np_out an optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below + * + * \cgalNamedParamsBegin + * \cgalParamBegin{vertex_point_map} + * the property map that will contain the points associated to the vertices of `output`. + * If this parameter is omitted, an internal property map for `CGAL::vertex_point_t` + * should be available for the vertices of `output` \cgalParamEnd + * \cgalNamedParamsEnd + */ +template +void extrude_mesh(const InputMesh& input, + OutputMesh& output, + #ifdef DOXYGEN_RUNNING + Vector_3 v, + #else + typename GetGeomTraits::type::Vector_3 v, + #endif + const NamedParameters1& np_in, + const NamedParameters2& np_out) +{ + typedef typename GetVertexPointMap < OutputMesh, NamedParameters2>::type VPMap; + VPMap output_vpm = choose_param(get_param(np_out, internal_np::vertex_point), + get_property_map(vertex_point, output)); + + extrude_impl::Const_dist_translation< + typename GetVertexPointMap::type, + typename GetGeomTraits::type::Vector_3> bot(output_vpm, + v); + extrude_impl::Identity_functor top; + extrude_mesh(input, output, bot,top, np_in, np_out); +} +//convenience overload +template +void extrude_mesh(const InputMesh& input, + OutputMesh& output, + Vector dir) +{ + extrude_mesh(input, output, dir, + parameters::all_default(), + parameters::all_default()); +} + +template +void extrude_mesh(const InputMesh& input, + OutputMesh& output, + Vector dir, + const CGAL_PMP_NP_CLASS& np) +{ + extrude_mesh(input, output, dir, + np, + parameters::all_default()); +} + +template +void extrude_mesh(const InputMesh& input, + OutputMesh& output, + const BottomFunctor& bot, + const TopFunctor& top) +{ + extrude_mesh(input, output, bot, top, + parameters::all_default(), parameters::all_default()); +} + +}} //end CGAL::PMP +#endif //CGAL_POLYGON_MESH_PROCESSING_EXTRUDE_H diff --git a/Polygon_mesh_processing/include/CGAL/polygon_mesh_processing.h b/Polygon_mesh_processing/include/CGAL/polygon_mesh_processing.h index 9379a5f472d..7d587ad4b84 100644 --- a/Polygon_mesh_processing/include/CGAL/polygon_mesh_processing.h +++ b/Polygon_mesh_processing/include/CGAL/polygon_mesh_processing.h @@ -44,6 +44,11 @@ #include #include #include +#include +#include +#include +#include +#include // the named parameter header being not documented the doc is put here for now #ifdef DOXYGEN_RUNNING diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt index f7af9794708..6ffde721a7d 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt @@ -100,6 +100,7 @@ endif() create_single_source_cgal_program("surface_intersection_sm_poly.cpp" ) create_single_source_cgal_program("test_orient_cc.cpp") create_single_source_cgal_program("test_pmp_transform.cpp") + create_single_source_cgal_program("extrude_test.cpp") if( TBB_FOUND ) CGAL_target_use_TBB(test_pmp_distance) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/quad.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/quad.off new file mode 100644 index 00000000000..3e2d5bf595b --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/quad.off @@ -0,0 +1,9 @@ +OFF +4 2 0 +-0.5 -0.5 0 +0.5 -0.5 0 +0.5 0.5 0 +-0.5 0.5 0 + +3 0 1 2 +3 0 2 3 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/extrude_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/extrude_test.cpp new file mode 100644 index 00000000000..bee7e23c253 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/extrude_test.cpp @@ -0,0 +1,74 @@ +#include +#include +#include +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; +typedef CGAL::Surface_mesh SMesh; +typedef CGAL::Polyhedron_3 Polyhedron; + +template +struct Bot +{ + Bot(MAP map):map(map){} + template + void operator()(const T&,VD vd) const + { + put(map, vd, get(map, vd)+Kernel::Vector_3(-2.0,0.0,1.0)); + } + MAP map; + +}; + +template +struct Top +{ + Top(MAP map):map(map){} + + template + void operator()(const T&, VD vd) const + { + put(map, vd, get(map, vd)+Kernel::Vector_3(0.0,2.0,-1.0)); + } + + MAP map; +}; + +template +void test_mesh(const char* filename) +{ + Mesh in, out; + std::ifstream input(filename); + + if (!input || !(input >> in)) + { + std::cerr << "Error: cannot read Surface Mesh : " << filename << "\n"; + assert(!CGAL::is_empty(in)); + assert(false); + return ; + } + CGAL::Polygon_mesh_processing::extrude_mesh(in, out, Kernel::Vector_3(0.0, 0.0, -1.0)); + std::ofstream extruded_off("extruded.off"); + extruded_off << out; + extruded_off.close(); + out.clear(); + + typedef typename boost::property_map::type VPMap; + Bot bot(get(CGAL::vertex_point, out)); + Top top(get(CGAL::vertex_point, out)); + CGAL::Polygon_mesh_processing::extrude_mesh(in, out, bot, top); + std::ofstream gen_extruded_off("gen_extruded.off"); + gen_extruded_off << out; + gen_extruded_off.close(); + std::cerr << "All done." << std::endl; +} + +int main(int argc, char* argv[]) +{ + const char* filename = (argc > 1) ? argv[1] : "data/quad.off"; + test_mesh(filename); + test_mesh(filename); + return 0; +} diff --git a/Polyhedron/demo/Polyhedron/Plugins/Convex_hull/Kernel_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Convex_hull/Kernel_plugin.cpp index 5fbfe64e5d4..28383306d81 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Convex_hull/Kernel_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Convex_hull/Kernel_plugin.cpp @@ -181,10 +181,8 @@ void Polyhedron_demo_kernel_plugin::on_actionKernel_triggered() vpm[fd] = CGAL::ORIGIN + normal / distance_to_origin + translate; } CGAL::copy_face_graph(dual, *pKernel, - CGAL::Emptyset_iterator(), - CGAL::Emptyset_iterator(), - CGAL::Emptyset_iterator(), - boost::make_assoc_property_map(vpm)); + CGAL::parameters::vertex_point_map( + boost::make_assoc_property_map(vpm))); // pKernel->inside_out(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt index 6970f0255c5..a626bc567d9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt @@ -163,3 +163,10 @@ polyhedron_demo_plugin(degenerated_faces_sm_plugin Degenerated_faces_plugin) target_link_libraries(degenerated_faces_sm_plugin PUBLIC scene_surface_mesh_item scene_surface_mesh_selection_item) target_compile_definitions(degenerated_faces_sm_plugin PUBLIC "-DUSE_SURFACE_MESH" ) + +polyhedron_demo_plugin(extrude_poly_plugin Extrude_plugin) +target_link_libraries(extrude_poly_plugin PUBLIC scene_polyhedron_item scene_polyhedron_selection_item) + +polyhedron_demo_plugin(extrude_sm_plugin Extrude_plugin) +target_link_libraries(extrude_sm_plugin PUBLIC scene_surface_mesh_item scene_surface_mesh_selection_item) +target_compile_definitions(extrude_sm_plugin PUBLIC "-DUSE_SURFACE_MESH" ) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Extrude_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Extrude_plugin.cpp new file mode 100644 index 00000000000..6f7bedf349f --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Extrude_plugin.cpp @@ -0,0 +1,478 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include "Messages_interface.h" +#ifdef USE_SURFACE_MESH +#include "Kernel_type.h" +#include "Scene_surface_mesh_item.h" +#else +#include "Scene_polyhedron_item.h" +#include "Polyhedron_type.h" +#endif +#include "Scene_polyhedron_selection_item.h" +#include "Scene.h" +#ifdef USE_SURFACE_MESH +typedef Scene_surface_mesh_item Scene_face_graph_item; +#else +typedef Scene_polyhedron_item Scene_face_graph_item; +#endif + +typedef Scene_face_graph_item::Face_graph Face_graph; +typedef CGAL::qglviewer::Vec Vec; +using namespace CGAL::Three; +//use frame to get dist and dir. +//fix frame in translation and use mousewheel to choose dist +//finding frame's position : first try at the center of the item's bbox +//maybe find intersection between surface and diag bbox. +//orientation : PCA : normal. +typedef Kernel::Plane_3 Plane; +typedef Kernel::Triangle_3 Triangle; +typedef Kernel::Point_3 Point; +typedef Kernel::Vector_3 Vector; +class Scene_arrow_item : public Scene_item +{ + Q_OBJECT +public : + Scene_arrow_item(Vec center_, double r, double length_) + :Scene_item(2, 1), center_(center_), length_(length_), R(r), + frame(new Scene_item::ManipulatedFrame()) + { + const CGAL::qglviewer::Vec offset = static_cast(CGAL::QGLViewer::QGLViewerPool().first())->offset(); + frame->setPosition( center_+offset); + nb_pos = 0; + tick = length_/10.0f; + ctrl_pressing = false; + } + // Indicates if rendering mode is supported + bool supportsRenderingMode(RenderingMode m) const Q_DECL_OVERRIDE { + return (m == Gouraud); + } + //Displays the item + void draw(Viewer_interface* viewer) const Q_DECL_OVERRIDE + { + if(!are_buffers_filled) + { + initializeBuffers(viewer); + } + vaos[0]->bind(); + program = getShaderProgram(PROGRAM_WITH_LIGHT); + GLdouble d_mat[16]; + QMatrix4x4 mvp_mat; + GLdouble matrix[16]; + QMatrix4x4 f_matrix; + frame->getMatrix(matrix); + for (int i=0; i<16; ++i) + f_matrix.data()[i] = (float)matrix[i]; + viewer->camera()->getModelViewProjectionMatrix(d_mat); + for (int i=0; i<16; ++i) + mvp_mat.data()[i] = GLfloat(d_mat[i]); + mvp_mat = mvp_mat*f_matrix; + QMatrix4x4 mv_mat; + viewer->camera()->getModelViewMatrix(d_mat); + for (int i=0; i<16; ++i) + mv_mat.data()[i] = GLfloat(d_mat[i]); + mv_mat = mv_mat*f_matrix; + attribBuffers(viewer, PROGRAM_WITH_LIGHT); + program->bind(); + program->setUniformValue("mvp_matrix", mvp_mat); + program->setUniformValue("mv_matrix", mv_mat); + program->setUniformValue("is_clipbox_on", false); + program->setAttributeValue("radius",0.01*diagonalBbox()); + program->setAttributeValue("colors", QColor(Qt::red)); + program->setAttributeValue("colors", this->color()); + viewer->glDrawArrays(GL_TRIANGLES, 0, static_cast(nb_pos/3)); + vaos[0]->release(); + program->release(); + } + void invalidateOpenGLBuffers() Q_DECL_OVERRIDE + { + are_buffers_filled = false; + } + Scene_item* clone() const Q_DECL_OVERRIDE {return 0;} + QString toolTip() const Q_DECL_OVERRIDE {return QString();} + Vec center()const { return center_; } + Scene_item::ManipulatedFrame* manipulatedFrame() Q_DECL_OVERRIDE { return frame; } + bool manipulatable() const Q_DECL_OVERRIDE { return true; } + bool eventFilter(QObject *, QEvent *event) Q_DECL_OVERRIDE + { + if(event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) + { + ctrl_pressing = static_cast(event)->modifiers().testFlag(Qt::ControlModifier); + } + if(event->type() == QEvent::Wheel && ctrl_pressing) + { + QWheelEvent *mouseEvent = static_cast(event); + int steps = mouseEvent->delta() / 120; + if (steps > 0) + length_+=tick; + else + length_-=tick; + invalidateOpenGLBuffers(); + redraw(); + return true; + } + return false; + } + double length()const { return length_; } +private: + //make an arrow showing the length and direction of the transformation for the extrusion. + void initializeBuffers(Viewer_interface *viewer)const + { + std::vector vertices; + std::vector normals; + int prec = 60; + //Head + const float Rf = static_cast(R); + for(int d = 0; d<360; d+= 360/prec) + { + float D = (float) (d * CGAL_PI / 180.); + float a = (float) std::atan(Rf / 0.33); + QVector4D pR(0., 1.*length_, 0, 1.); + QVector4D nR(Rf*2.*sin(D), sin(a), Rf*2.*cos(D), 1.); + + //point A1 + vertices.push_back(pR.x()); + vertices.push_back(pR.y()); + vertices.push_back(pR.z()); + normals.push_back(nR.x()); + normals.push_back(nR.y()); + normals.push_back(nR.z()); + + //point B1 + pR = QVector4D(Rf*2.*sin(D), 0.66f*length_, Rf*2.* cos(D), 1.f); + nR = QVector4D(sin(D), sin(a), cos(D), 1.); + vertices.push_back(pR.x()); + vertices.push_back(pR.y()); + vertices.push_back(pR.z()); + normals.push_back(nR.x()); + normals.push_back(nR.y()); + normals.push_back(nR.z()); + //point C1 + D = (d+360/prec)*CGAL_PI/180.0; + pR = QVector4D(Rf*2.* sin(D), 0.66f*length_, Rf *2.* cos(D), 1.f); + nR = QVector4D(sin(D), sin(a), cos(D), 1.0); + + vertices.push_back(pR.x()); + vertices.push_back(pR.y()); + vertices.push_back(pR.z()); + normals.push_back(nR.x()); + normals.push_back(nR.y()); + normals.push_back(nR.z()); + } + + //cylinder + //body of the cylinder + for(int d = 0; d<360; d+= 360/prec) + { + //point A1 + double D = d*CGAL_PI/180.0; + QVector4D pR(Rf*sin(D), 0.66f*length_, Rf*cos(D), 1.f); + QVector4D nR(sin(D), 0.f, cos(D), 1.f); + + vertices.push_back(pR.x()); + vertices.push_back(pR.y()); + vertices.push_back(pR.z()); + normals.push_back(nR.x()); + normals.push_back(nR.y()); + normals.push_back(nR.z()); + //point B1 + pR = QVector4D(Rf * sin(D),0,Rf*cos(D), 1.0); + nR = QVector4D(sin(D), 0, cos(D), 1.0); + + vertices.push_back(pR.x()); + vertices.push_back(pR.y()); + vertices.push_back(pR.z()); + normals.push_back(nR.x()); + normals.push_back(nR.y()); + normals.push_back(nR.z()); + //point C1 + D = (d+360/prec)*CGAL_PI/180.0; + pR = QVector4D(Rf * sin(D),0,Rf*cos(D), 1.0); + nR = QVector4D(sin(D), 0, cos(D), 1.0); + vertices.push_back(pR.x()); + vertices.push_back(pR.y()); + vertices.push_back(pR.z()); + normals.push_back(nR.x()); + normals.push_back(nR.y()); + normals.push_back(nR.z()); + //point A2 + D = (d+360/prec)*CGAL_PI/180.0; + + pR = QVector4D(Rf * sin(D),0,Rf*cos(D), 1.0); + nR = QVector4D(sin(D), 0, cos(D), 1.0); + + vertices.push_back(pR.x()); + vertices.push_back(pR.y()); + vertices.push_back(pR.z()); + normals.push_back(nR.x()); + normals.push_back(nR.y()); + normals.push_back(nR.z()); + //point B2 + pR = QVector4D(Rf * sin(D), 0.66f*length_, Rf*cos(D), 1.f); + nR = QVector4D(sin(D), 0, cos(D), 1.0); + + vertices.push_back(pR.x()); + vertices.push_back(pR.y()); + vertices.push_back(pR.z()); + normals.push_back(nR.x()); + normals.push_back(nR.y()); + normals.push_back(nR.z()); + //point C2 + D = d*CGAL_PI/180.0; + pR = QVector4D(Rf * sin(D), 0.66f*length_, Rf*cos(D), 1.f); + nR = QVector4D(sin(D), 0.f, cos(D), 1.f); + + vertices.push_back(pR.x()); + vertices.push_back(pR.y()); + vertices.push_back(pR.z()); + normals.push_back(nR.x()); + normals.push_back(nR.y()); + normals.push_back(nR.z()); + } + + //fill buffers + //vao containing the data for the facets + program = getShaderProgram(PROGRAM_WITH_LIGHT, viewer); + program->bind(); + vaos[0]->bind(); + buffers[0].bind(); + buffers[0].allocate(vertices.data(), + static_cast(vertices.size()*sizeof(float))); + program->enableAttributeArray("vertex"); + program->setAttributeBuffer("vertex",GL_FLOAT,0,3); + buffers[0].release(); + buffers[1].bind(); + buffers[1].allocate(normals.data(), + static_cast(normals.size()*sizeof(float))); + program->enableAttributeArray("normals"); + program->setAttributeBuffer("normals",GL_FLOAT,0,3); + buffers[1].release(); + vaos[0]->release(); + program->release(); + //once the buffers are filled, we can empty the vectors to optimize memory consumption + nb_pos = vertices.size(); + _bbox = Bbox(0,0,0,0,0,0); + for(std::size_t i = 0; i< vertices.size(); i+=3) + { + _bbox += Point(vertices[i], + vertices[i+1], + vertices[i+2]).bbox(); + } + + are_buffers_filled = true; + } + + mutable std::size_t nb_pos; + Vec center_; + double length_; + double tick; + double R; + bool ctrl_pressing; + mutable QOpenGLShaderProgram *program; + Scene_item::ManipulatedFrame* frame; +}; //end of class Scene_arrow_item + + +template +CGAL::Bbox_3 triangles(const TriangleMesh& mesh, + OutputIterator out) +{ + CGAL::Bbox_3 bb; + typename boost::property_map::const_type vpm = + get(CGAL::vertex_point, mesh); + BOOST_FOREACH(typename boost::graph_traits::face_descriptor fd, faces(mesh)){ + typename boost::graph_traits::halfedge_descriptor hd = halfedge(fd,mesh); + Triangle t(get(vpm,source(hd,mesh)), + get(vpm,target(hd,mesh)), + get(vpm,target(next(hd,mesh),mesh))); + *out++ = t; + bb = bb + t.bbox(); + } + return bb; +} + +Vector estimate_normals(const std::vector& tris) +{ + Vector moy(0,0,0); + + BOOST_FOREACH(const Triangle& tri, tris) + { + Vector norm = CGAL::Polygon_mesh_processing::internal::triangle_normal( + tri[0], tri[1], tri[2], Kernel()); + norm /= CGAL::sqrt(norm.squared_length()); + moy += norm; + } + return moy; +} + + +class ExtrudePlugin : + public QObject, + public Polyhedron_demo_plugin_interface +{ + Q_OBJECT + Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface) + Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0") +public: + + bool applicable(QAction* action) const Q_DECL_OVERRIDE + { + if(action == actionCreateItem) + { + return !oliver_queen && + (qobject_cast(scene->item(scene->mainSelectionIndex())) + || qobject_cast(scene->item(scene->mainSelectionIndex()))); + } + else if(oliver_queen) + return true; + return false; + } + + QList actions() const Q_DECL_OVERRIDE + { + return _actions; + } + + void init(QMainWindow* mainWindow, Scene_interface* sc, Messages_interface* mi) Q_DECL_OVERRIDE + { + this->messageInterface = mi; + this->scene = sc; + this->mw = mainWindow; + oliver_queen = NULL; + target = NULL; + actionCreateItem = new QAction(QString("Extrude Item"), mw); + actionCreateItem->setProperty("submenuName", "Polygon Mesh Processing"); + connect(actionCreateItem, SIGNAL(triggered()), + this, SLOT(createItem())); + _actions << actionCreateItem; + actionExtrude = new QAction(QString("Perform Extrusion"), mw); + actionExtrude->setProperty("submenuName", "Polygon Mesh Processing"); + connect(actionExtrude, SIGNAL(triggered()), + this, SLOT(do_extrude())); + _actions << actionExtrude; + } +private Q_SLOTS: + void createItem() + { + Scene_item * item = scene->item(scene->mainSelectionIndex()); + Scene_polyhedron_selection_item* sel_item = qobject_cast(scene->item(scene->mainSelectionIndex())); + Scene_face_graph_item* fg_item = qobject_cast(item); + Face_graph* pMesh = NULL; + if(sel_item) + { + pMesh = new Face_graph(); + if(!sel_item->export_selected_facets_as_polyhedron(pMesh)) + { + messageInterface->error("Face selection is not valid. Aborting."); + + return; + } + fg_item = new Scene_facegraph_item(pMesh); + fg_item->setName(QString("%1 selection").arg(sel_item->polyhedron_item()->name())); + scene->addItem(fg_item); + sel_item->polyhedron_item()->setWireframeMode(); + sel_item->polyhedron_item()->redraw(); + } + if(fg_item) + pMesh = fg_item->face_graph(); + else + return; + if(CGAL::is_closed(*pMesh)) + { + messageInterface->error("The face graph must be open. Aborting."); + return; + } + std::vector triangles; + ::triangles(*pMesh,std::back_inserter(triangles)); + Plane plane; + CGAL::linear_least_squares_fitting_3(triangles.begin(),triangles.end(),plane,CGAL::Dimension_tag<2>()); + + // compute centroid + Point c = CGAL::centroid(triangles.begin(),triangles.end()); + + oliver_queen = new Scene_arrow_item(Vec(c.x(),c.y(),c.z()), fg_item->diagonalBbox() / 50.0f, + fg_item->diagonalBbox()/3.0f); + Vec dir(plane.orthogonal_vector().x(), + plane.orthogonal_vector().y(), + plane.orthogonal_vector().z()); + if(CGAL::scalar_product(Vector(dir.x, dir.y, dir.z), estimate_normals(triangles)) > 0) + dir = -dir; + + CGAL::qglviewer::Quaternion orientation(CGAL::qglviewer::Vec(0,1,0), dir); + oliver_queen->manipulatedFrame()->setOrientation(orientation); + constraint.setRotationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::FREE); + constraint.setTranslationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::FORBIDDEN); + oliver_queen->manipulatedFrame()->setConstraint(&constraint); + oliver_queen->setColor(QColor(Qt::green)); + oliver_queen->setName("Extrude item"); + CGAL::QGLViewer* viewer = *CGAL::QGLViewer::QGLViewerPool().begin(); + viewer->installEventFilter(oliver_queen); + mw->installEventFilter(oliver_queen); + scene->addItem(oliver_queen); + target = fg_item; + + connect(oliver_queen, &Scene_arrow_item::aboutToBeDestroyed, + [this](){ + oliver_queen = NULL; + }); + + //!@todo : add a way to track scene's bbox recomputation and reset frame's position when triggered. + } + void do_extrude() + { + if(!target) + return; + Face_graph pMesh = *target->face_graph(); + target->face_graph()->clear(); + double length = oliver_queen->length(); + double matrix[16]; + oliver_queen->manipulatedFrame()->getMatrix(matrix); + QMatrix4x4 rotate_matrix; + QMatrix4x4 transform_matrix; + for(int i=0; i<16; ++i) + transform_matrix.data()[i] = (float)matrix[i]; + rotate_matrix = transform_matrix; + rotate_matrix.setColumn(3, QVector4D(0,0,0,1)); + QVector3D dir = rotate_matrix * QVector3D(0,1,0); + dir.normalize(); + dir = length * dir; + + CGAL::Polygon_mesh_processing::extrude_mesh(pMesh, *target->face_graph(), + Kernel::Vector_3(dir.x(), dir.y(), dir.z())); + scene->erase(scene->item_id(oliver_queen)); + oliver_queen = NULL; + target->invalidateOpenGLBuffers(); + target->itemChanged(); + target = NULL; + } + +private: + + QList _actions; + Messages_interface* messageInterface; + Scene_interface* scene; + QMainWindow* mw; + QAction *actionCreateItem; + QAction *actionExtrude; + Scene_arrow_item* oliver_queen; + Scene_face_graph_item* target; + CGAL::qglviewer::LocalConstraint constraint; +}; +#include "Extrude_plugin.moc" diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index 858654605cf..f0172b836fa 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -638,6 +638,10 @@ void Viewer::attribBuffers(int program_name) const { program->setUniformValue("clipbox1", clipbox1); program->setUniformValue("clipbox2", clipbox2); } + if(program_name == PROGRAM_WITH_LIGHT) + { + program->setUniformValue("alpha", 1.0f); //overriden in item draw() if necessary + } switch(program_name) { case PROGRAM_WITH_LIGHT: diff --git a/Polyhedron/demo/Polyhedron/cgal_test_with_cmake b/Polyhedron/demo/Polyhedron/cgal_test_with_cmake index 6bc5f895d86..740946b6ccc 100755 --- a/Polyhedron/demo/Polyhedron/cgal_test_with_cmake +++ b/Polyhedron/demo/Polyhedron/cgal_test_with_cmake @@ -140,6 +140,8 @@ distance_plugin \ distance_sm_plugin \ edit_polyhedron_plugin \ edit_sm_plugin \ +extrude_poly_plugin \ +extrude_sm_plugin \ fairing_plugin \ features_detection_plugin \ gocad_plugin \ diff --git a/Scripts/developer_scripts/add_toc_to_github_wiki_page.py b/Scripts/developer_scripts/add_toc_to_github_wiki_page.py index 8f96b785ec8..ce61f49db7e 100644 --- a/Scripts/developer_scripts/add_toc_to_github_wiki_page.py +++ b/Scripts/developer_scripts/add_toc_to_github_wiki_page.py @@ -2,6 +2,18 @@ from sys import argv from sys import exit import codecs import re +import argparse + +parser = argparse.ArgumentParser() +parser.add_argument("filename", + help="the Mardown file to process") +parser.add_argument("--codebase", + help="for a Markdown file of Codebase instead of Github", + action="store_true") +parser.add_argument("--h1", + help="support level one sections (h1)", + action="store_true") +args = parser.parse_args() # a probably incomplete version to generate an anchor from a section name def get_anchor(s): @@ -13,7 +25,10 @@ def get_anchor(s): s = s.replace(":","") s = s.replace(",","") s = s.replace(";","") - s = s.replace("/","") + if args.codebase: + s = s.replace("/","-") + else: + s = s.replace("/","") s = s.replace("<","") s = s.replace(">","") s = s.replace("+","") @@ -23,8 +38,11 @@ def get_anchor(s): s = s.lstrip(" ") s = s.rstrip("\n") s = s.rstrip(" ") - s = s.replace(" ","-") - s = s.lower() + s = re.sub(r'\s+','-',s) + if not args.codebase: + s = s.lower() + if args.codebase: + s = s.replace("'","-and-39-") return "#"+s # indices the nesting level (first level allowed is ##) @@ -45,11 +63,14 @@ def get_name(s): #generate the entry for one section def get_toc_entry(s): name = get_name(s) - level = get_level(s)-2 + if args.h1: + level = get_level(s)-1 + else: + level = get_level(s)-2 anchor = get_anchor(s) if level<0: - return "ERROR: h1 section are not allowed" + return "ERROR: h1 sections are not allowed" res="* ["+name+"]("+anchor+")" for i in range(0,level): @@ -57,11 +78,7 @@ def get_toc_entry(s): return res #now the main -if len(argv) < 2: - print("Nothing done, no input file provided") - exit() - -input = argv[1] +input = args.filename f = codecs.open(input, 'r', encoding='utf-8') diff --git a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/discrete_authalic.cpp b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/discrete_authalic.cpp index ed4eb5ef07f..a93852c0043 100644 --- a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/discrete_authalic.cpp +++ b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/discrete_authalic.cpp @@ -27,12 +27,12 @@ typedef boost::graph_traits::face_descriptor face_descriptor; namespace SMP = CGAL::Surface_mesh_parameterization; -int main(int argc, char * argv[]) +int main(int argc, char** argv) { std::ifstream in((argc>1) ? argv[1] : "data/three_peaks.off"); if(!in) { std::cerr << "Problem loading the input data" << std::endl; - return 1; + return EXIT_FAILURE; } SurfaceMesh sm; @@ -52,11 +52,11 @@ int main(int argc, char * argv[]) if(err != SMP::OK) { std::cerr << "Error: " << SMP::get_error_message(err) << std::endl; - return 1; + return EXIT_FAILURE; } std::ofstream out("result.off"); SMP::IO::output_uvmap_to_off(sm, bhd, uv_map, out); - return 0; + return EXIT_SUCCESS; } diff --git a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/lscm.cpp b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/lscm.cpp index 1b0675c8a8d..fc95fc9a3a0 100644 --- a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/lscm.cpp +++ b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/lscm.cpp @@ -37,12 +37,12 @@ typedef boost::graph_traits::face_descriptor face_descriptor; namespace SMP = CGAL::Surface_mesh_parameterization; -int main(int argc, char * argv[]) +int main(int argc, char** argv) { std::ifstream in_mesh((argc>1) ? argv[1] : "data/lion.off"); if(!in_mesh){ std::cerr << "Error: problem loading the input data" << std::endl; - return 1; + return EXIT_FAILURE; } SurfaceMesh sm; @@ -97,6 +97,6 @@ int main(int argc, char * argv[]) std::ofstream out("result.off"); SMP::IO::output_uvmap_to_off(mesh, bhd, uv_pm, out); - return 0; + return EXIT_SUCCESS; } diff --git a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/orbifold.cpp b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/orbifold.cpp index 84296d8ab87..67c095bcaf9 100644 --- a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/orbifold.cpp +++ b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/orbifold.cpp @@ -41,7 +41,7 @@ typedef SurfaceMesh::Property_map UV_pmap; namespace SMP = CGAL::Surface_mesh_parameterization; -int main(int argc, char * argv[]) +int main(int argc, char** argv) { CGAL::Timer task_timer; task_timer.start(); @@ -50,7 +50,7 @@ int main(int argc, char * argv[]) std::ifstream in_mesh(mesh_filename); if(!in_mesh) { std::cerr << "Error: problem loading the input data" << std::endl; - return 1; + return EXIT_FAILURE; } SurfaceMesh sm; // underlying mesh of the seam mesh @@ -120,4 +120,5 @@ int main(int argc, char * argv[]) parameterizer.parameterize(mesh, bhd, cmap, uvmap, vimap); std::cout << "Finished in " << task_timer.time() << " seconds" << std::endl; + return EXIT_SUCCESS; } diff --git a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/seam_Polyhedron_3.cpp b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/seam_Polyhedron_3.cpp index 21308c43e7f..b101786e0a6 100644 --- a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/seam_Polyhedron_3.cpp +++ b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/seam_Polyhedron_3.cpp @@ -37,12 +37,12 @@ typedef boost::graph_traits::face_descriptor face_descriptor; namespace SMP = CGAL::Surface_mesh_parameterization; -int main(int argc, char * argv[]) +int main(int argc, char** argv) { std::ifstream in_mesh((argc>1)?argv[1]:"data/lion.off"); if(!in_mesh) { std::cerr << "Error: problem loading the input data" << std::endl; - return 1; + return EXIT_FAILURE; } PolyMesh sm; @@ -77,6 +77,6 @@ int main(int argc, char * argv[]) std::ofstream out("result.off"); SMP::IO::output_uvmap_to_off(mesh, bhd, uv_pm, out); - return 0; + return EXIT_SUCCESS; } diff --git a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/simple_parameterization.cpp b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/simple_parameterization.cpp index 890503c46a2..a5aeba4f2f3 100644 --- a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/simple_parameterization.cpp +++ b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/simple_parameterization.cpp @@ -21,12 +21,12 @@ typedef boost::graph_traits::face_descriptor face_descriptor; namespace SMP = CGAL::Surface_mesh_parameterization; -int main(int argc, char * argv[]) +int main(int argc, char** argv) { std::ifstream in((argc>1) ? argv[1] : "data/nefertiti.off"); if(!in) { std::cerr << "Problem loading the input data" << std::endl; - return 1; + return EXIT_FAILURE; } SurfaceMesh sm; @@ -44,5 +44,5 @@ int main(int argc, char * argv[]) std::ofstream out("result.off"); SMP::IO::output_uvmap_to_off(sm, bhd, uv_map, out); - return 0; + return EXIT_SUCCESS; } diff --git a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/square_border_parameterizer.cpp b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/square_border_parameterizer.cpp index 8cc315c599e..9e64c7db2fd 100644 --- a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/square_border_parameterizer.cpp +++ b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/square_border_parameterizer.cpp @@ -97,7 +97,7 @@ bool read_vertices(const PolyMesh& mesh, return true; } -int main(int argc, char * argv[]) +int main(int argc, char** argv) { std::ifstream in((argc>1) ? argv[1] : "data/nefertiti.off"); if(!in){ @@ -118,7 +118,7 @@ int main(int argc, char * argv[]) Vd_array vda; if(!read_vertices(sm, filename, vda)) { std::cerr << "Error: problem loading the square corners" << std::endl; - return 1; + return EXIT_FAILURE; } typedef SMP::Square_border_uniform_parameterizer_3 Border_parameterizer; @@ -138,5 +138,5 @@ int main(int argc, char * argv[]) std::ofstream out("result.off"); SMP::IO::output_uvmap_to_off(sm, bhd, uv_map, out); - return 0; + return EXIT_SUCCESS; } 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 07658f43a35..ffb4c2a3e64 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 @@ -1327,8 +1327,11 @@ public: NT energy_this = compute_current_energy(mesh, faces, ctmap, lp, lpmap, ltmap, uvmap); NT energy_last; + +#ifdef CGAL_PARAMETERIZATION_ARAP_VERBOSE std::cout << "Initial energy: " << energy_this << std::endl; std::cout << m_iterations << " max iterations" << std::endl; +#endif // main loop for(unsigned int ite=1; ite<=m_iterations; ++ite) @@ -1342,7 +1345,9 @@ public: energy_last = energy_this; energy_this = compute_current_energy(mesh, faces, ctmap, lp, lpmap, ltmap, uvmap); +#ifdef CGAL_PARAMETERIZATION_ARAP_VERBOSE std::cout << "Energy at iteration " << ite << " : " << energy_this << std::endl; +#endif CGAL_warning(energy_this >= 0); if(status != OK) @@ -1353,9 +1358,11 @@ public: { // also no need compute energy if this iteration is the last iteration double energy_diff = std::abs((energy_last - energy_this) / energy_this); if(energy_diff < m_tolerance) { +#ifdef CGAL_PARAMETERIZATION_ARAP_VERBOSE std::cout << "Minimization process ended after: " << ite + 1 << " iterations. " << "Energy diff: " << energy_diff << std::endl; +#endif break; } } diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/MVC_post_processor_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/MVC_post_processor_3.h index 6e8015c9b55..3cf75893e1b 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/MVC_post_processor_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/MVC_post_processor_3.h @@ -744,7 +744,6 @@ public: // Run the MVC parameterize_convex_hull_with_MVC(mesh, vertices, faces, ct, uvmap, vimap, vpmap); - std::cout << "End of post processing" << std::endl; return OK; } 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 b3189bbb868..fdb68bc3d09 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 @@ -110,10 +110,12 @@ Error_code read_cones(const TriangleMesh& tm, std::ifstream& in, VertexIndexMap while(in >> cone_index) cones.push_back(cone_index); +#ifdef CGAL_PARAMETERIZATION_ORBIFOLD_CONE_VERBOSE std::cout << "Input cones: "; for(std::size_t i=0; i 4) { std::cerr << "Error: Not enough or too many input cones" << std::endl; diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/angles.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/angles.h index cea7ebb6866..800f58fbfd7 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/angles.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/angles.h @@ -34,8 +34,8 @@ namespace Surface_mesh_parameterization { namespace internal { -// -> -> -// Return cotangent of (P,Q,R) corner (i.e. cotan of QP, QR angle). +// -> -> +// Returns the cotangent of the corner (P,Q,R) (i.e. the cotan of the angle (QP, QR) ). template typename K::FT cotangent(const typename K::Point_3& P, const typename K::Point_3& Q, @@ -46,18 +46,17 @@ typename K::FT cotangent(const typename K::Point_3& P, Vector_3 u = P - Q; Vector_3 v = R - Q; - // (u . v) / ((u x v).len) - NT dot = (u*v); - Vector_3 cross_vector = CGAL::cross_product(u,v); + NT dot = (u * v); + Vector_3 cross_vector = CGAL::cross_product(u, v); NT cross_norm = CGAL::sqrt(cross_vector * cross_vector); - if(cross_norm != 0.0) + if(cross_norm != NT(0)) return (dot / cross_norm); else - return 0.0; // undefined + return 0; // undefined } -// -> -> -// Return tangent of (P,Q,R) corner (i.e. tangent of QP, QR angle). +// -> -> +// Returns the tangent of the corner (P,Q,R) (i.e. the tangent of angle (QP, QR) ). template typename K::FT tangent(const typename K::Point_3& P, const typename K::Point_3& Q, @@ -68,17 +67,16 @@ typename K::FT tangent(const typename K::Point_3& P, Vector_3 u = P - Q; Vector_3 v = R - Q; - // (u . v) / ((u x v).len) NT dot = (u * v); Vector_3 cross_vector = CGAL::cross_product(u, v); NT cross_norm = CGAL::sqrt(cross_vector * cross_vector); - if(dot != 0.0) + if(dot != NT(0)) return (cross_norm / dot); else - return 0.0; // undefined + return 0; // undefined } -// Fix sine to be within [-1;1]. +// Fixes the sine to be within [-1;1]. template typename K::FT fix_sine(typename K::FT sine) { @@ -90,8 +88,8 @@ typename K::FT fix_sine(typename K::FT sine) return sine; } -// -> -> -// Return angle (in radians) of of (P,Q,R) corner (i.e. QP, QR angle). +// -> -> +// Returns the angle (in radians) of the corner (P,Q,R) (i.e. the angle (QP, QR) ). template typename K::FT compute_angle_rad(const typename K::Point_3& P, const typename K::Point_3& Q, @@ -103,10 +101,9 @@ typename K::FT compute_angle_rad(const typename K::Point_3& P, Vector_3 u = P - Q; Vector_3 v = R - Q; - // check NT product = CGAL::sqrt(u * u) * CGAL::sqrt(v * v); - if(product == 0) - return 0.0; + if(product == NT(0)) + return 0; // cosine NT dot = (u * v); @@ -116,7 +113,7 @@ typename K::FT compute_angle_rad(const typename K::Point_3& P, Vector_3 w = CGAL::cross_product(u, v); NT abs_sine = CGAL::sqrt(w * w) / product; - if(cosine >= 0) + if(cosine >= NT(0)) return std::asin(fix_sine(abs_sine)); else return CGAL_PI - std::asin(fix_sine(abs_sine)); diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/orbifold_shortest_path.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/orbifold_shortest_path.h index 5479683a81c..3a21e30b78d 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/orbifold_shortest_path.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/orbifold_shortest_path.h @@ -130,7 +130,7 @@ void compute_shortest_paths_between_two_cones(const TriangleMesh& mesh, EdgeOutputIterator oi) { if(source == target) { - std::cout << "Warning: the source and target are identical in 'shortest_path' " << std::endl; + std::cerr << "Warning: the source and target are identical in 'shortest_path' " << std::endl; return; } @@ -150,7 +150,7 @@ void compute_shortest_paths_between_two_cones(const TriangleMesh& mesh, try { boost::dijkstra_shortest_paths(mesh, source, boost::predecessor_map(pred_pmap).visitor(vis)); } catch (const std::exception& e) { - std::cout << e.what() << std::endl; + std::cerr << e.what() << std::endl; } // Draw the path from target to source and collect the edges along the way diff --git a/Surface_mesh_parameterization/test/Surface_mesh_parameterization/extensive_parameterization_test.cpp b/Surface_mesh_parameterization/test/Surface_mesh_parameterization/extensive_parameterization_test.cpp index 9ff1649fe82..aaaf0a45e5e 100644 --- a/Surface_mesh_parameterization/test/Surface_mesh_parameterization/extensive_parameterization_test.cpp +++ b/Surface_mesh_parameterization/test/Surface_mesh_parameterization/extensive_parameterization_test.cpp @@ -92,7 +92,7 @@ int main(int, char**) in >> pm; if(!in || num_vertices(pm) == 0) { std::cerr << "Problem loading the input data" << std::endl; - return 1; + return EXIT_FAILURE; } PM_halfedge_descriptor hd = CGAL::Polygon_mesh_processing::longest_border(pm).first; @@ -108,7 +108,7 @@ int main(int, char**) if(status != SMP::OK) { std::cout << "Encountered a problem: " << status << std::endl; - return 1; + return EXIT_FAILURE; } else { std::cout << "Parameterized with MVC (POLY)!" << std::endl; @@ -129,7 +129,7 @@ int main(int, char**) in >> pm; if(!in || num_vertices(pm) == 0) { std::cerr << "Problem loading the input data" << std::endl; - return 1; + return EXIT_FAILURE; } PM_halfedge_descriptor hd = CGAL::Polygon_mesh_processing::longest_border(pm).first; @@ -162,7 +162,7 @@ int main(int, char**) if(status != SMP::OK) { std::cout << "Encountered a problem: " << status << std::endl; - return 1; + return EXIT_FAILURE; } else { std::cout << "Parameterized with ARAP (POLY)!" << std::endl; @@ -183,7 +183,7 @@ int main(int, char**) in >> sm; if(!in || num_vertices(sm) == 0) { std::cerr << "Problem loading the input data" << std::endl; - return 1; + return EXIT_FAILURE; } SM_halfedge_descriptor hd = CGAL::Polygon_mesh_processing::longest_border(sm).first; @@ -214,7 +214,7 @@ int main(int, char**) if(status != SMP::OK) { std::cout << "Encountered a problem: " << status << std::endl; - return 1; + return EXIT_FAILURE; } else { std::cout << "Parameterized with Barycentric (SM)!" << std::endl; @@ -235,7 +235,7 @@ int main(int, char**) in >> sm; if(!in || num_vertices(sm) == 0) { std::cerr << "Problem loading the input data" << std::endl; - return 1; + return EXIT_FAILURE; } // halfedge on the longest border @@ -269,7 +269,7 @@ int main(int, char**) SMP::Error_code status = parameterizer.parameterize(sm, hd, uv_pm, vipm, vpm); if(status != SMP::OK) { std::cout << "Encountered a problem: " << status << std::endl; - return 1; + return EXIT_FAILURE; } else { std::cout << "Parameterized with ARAP (SM)!" << std::endl; @@ -286,7 +286,7 @@ int main(int, char**) in >> pm; if(!in || num_vertices(pm) == 0) { std::cerr << "Problem loading the input data" << std::endl; - return 1; + return EXIT_FAILURE; } const char* selection = "data/fandisk.dcm.selection.txt"; @@ -330,7 +330,7 @@ int main(int, char**) if(status != SMP::OK) { std::cout << "Encountered a problem: " << status << std::endl; - return 1; + return EXIT_FAILURE; } else { std::cout << "Parameterized with DCM (SEAM POLY)!" << std::endl; @@ -351,7 +351,7 @@ int main(int, char**) in >> sm; if(!in || num_vertices(sm) == 0) { std::cerr << "Problem loading the input data" << std::endl; - return 1; + return EXIT_FAILURE; } const char* selection = "data/bear.dac.selection.txt"; @@ -395,7 +395,7 @@ int main(int, char**) SMP::Error_code status = parameterizer.parameterize(mesh, hd, uv_pm, vipm, vpm); if(status != SMP::OK) { std::cout << "Encountered a problem: " << status << std::endl; - return 1; + return EXIT_FAILURE; } else { std::cout << "Parameterized with DAC (SEAM SM)!" << std::endl; @@ -413,7 +413,7 @@ int main(int, char**) in >> sm; if(!in || num_vertices(sm) == 0) { std::cerr << "Problem loading the input data" << std::endl; - return 1; + return EXIT_FAILURE; } const char* cone_filename = "data/fandisk.orbifold.selection.txt"; @@ -471,7 +471,7 @@ int main(int, char**) SMP::Error_code status = parameterizer.parameterize(mesh, hd, cmap, uvmap, vimap); if(status != SMP::OK) { std::cout << "Encountered a problem: " << status << std::endl; - return 1; + return EXIT_FAILURE; } else { std::cout << "Parameterized with Orbifold (SEAM SM)!" << std::endl; @@ -481,5 +481,5 @@ int main(int, char**) std::cout << "Done!" << std::endl; - return 0; + return EXIT_SUCCESS; } diff --git a/Surface_mesh_skeletonization/include/CGAL/Mean_curvature_flow_skeletonization.h b/Surface_mesh_skeletonization/include/CGAL/Mean_curvature_flow_skeletonization.h index bd23a70f0e8..967cb23d44c 100644 --- a/Surface_mesh_skeletonization/include/CGAL/Mean_curvature_flow_skeletonization.h +++ b/Surface_mesh_skeletonization/include/CGAL/Mean_curvature_flow_skeletonization.h @@ -847,7 +847,8 @@ private: { typedef std::pair Vertex_pair; std::vector v2v; - copy_face_graph(tmesh, m_tmesh, std::back_inserter(v2v)); + copy_face_graph(tmesh, m_tmesh, + CGAL::parameters::vertex_to_vertex_output_iterator(std::back_inserter(v2v))); // copy input vertices to keep correspondence BOOST_FOREACH(const Vertex_pair& vp, v2v)