Merge branch 'master' into Periodic_3_mesh_3-Feature-MBogdanov

This commit is contained in:
Mael 2018-07-04 16:55:30 +02:00 committed by GitHub
commit 74e569db86
41 changed files with 1800 additions and 316 deletions

View File

@ -114,6 +114,67 @@ as result of a partition algorithm; if it is not provided, this information is
simply inaccessible. simply inaccessible.
\cgalNPEnd \cgalNPEnd
\cgalNPBegin{vertex_to_vertex_output_iterator} \anchor BGL_vertex_to_vertex_output_iterator
is a model of `OutputIterator` accepting `std::pair<vertex_descriptor, vertex_descriptor>`
A typical use case is mapping the vertices from a source mesh to its copy's after a `copy_face_graph()`
operation.\n
<b>Type:</b>a class model of `OutputIterator` accepting
`std::pair<`boost::graph_traits<PolygonMesh>::%vertex_descriptor, `boost::graph_traits<PolygonMesh>::%vertex_descriptor>`.\n
<b>Default:</b> Emptyset_iterator
\cgalNPEnd
\cgalNPBegin{halfedge_to_halfedge_output_iterator} \anchor BGL_halfedge_to_halfedge_output_iterator
is a model of `OutputIterator` accepting `std::pair<halfedge_descriptor, halfedge_descriptor>`
A typical use case is mapping the halfedges from a source mesh to its copy's after a `copy_face_graph()`
operation.\n
<b>Type:</b>a class model of `OutputIterator` accepting
`std::pair<`boost::graph_traits<PolygonMesh>::%halfedge_descriptor, `boost::graph_traits<PolygonMesh>::%halfedge_descriptor>`.\n
<b>Default:</b> Emptyset_iterator
\cgalNPEnd
\cgalNPBegin{face_to_face_output_iterator} \anchor BGL_face_to_face_output_iterator
is a model of `OutputIterator` accepting `std::pair<face_descriptor, face_descriptor>`
A typical use case is mapping the faces from a source mesh to its copy's after a `copy_face_graph()`
operation.\n
<b>Type:</b>a class model of `OutputIterator` accepting
`std::pair<`boost::graph_traits<PolygonMesh>::%face_descriptor, `boost::graph_traits<PolygonMesh>::%face_descriptor>`.\n
<b>Default:</b> 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
<b>Type:</b>a class model of `ReadWritePropertyMap` with
`boost::graph_traits<PolygonMesh1>::%vertex_descriptor` as key type and
`boost::graph_traits<PolygonMesh2>::%vertex_descriptor` as value type.\n
<b>Default:</b> 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
<b>Type:</b>a class model of `ReadWritePropertyMap` with
`boost::graph_traits<PolygonMesh1>::%halfedge_descriptor` as key type and
`boost::graph_traits<PolygonMesh2>::%halfedge_descriptor` as value type.\n
<b>Default:</b> 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
<b>Type:</b>a class model of `ReadWritePropertyMap` with
`boost::graph_traits<PolygonMesh1>::%face_descriptor` as key type and
`boost::graph_traits<PolygonMesh2>::%face_descriptor` as value type.\n
<b>Default:</b> None.
\cgalNPEnd
\cgalNPTableEnd \cgalNPTableEnd
*/ */

View File

@ -52,7 +52,8 @@ int main(int argc, char* argv[])
boost::unordered_map<source_vertex_descriptor, tm_vertex_descriptor> v2v; boost::unordered_map<source_vertex_descriptor, tm_vertex_descriptor> v2v;
boost::unordered_map<source_halfedge_descriptor, tm_halfedge_descriptor> h2h; boost::unordered_map<source_halfedge_descriptor, tm_halfedge_descriptor> 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"); std::ofstream out("reverse.off");
out << S; out << S;
} }

View File

@ -17,6 +17,7 @@
#include <iterator> #include <iterator>
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Polyhedron_3<Kernel> Source; typedef CGAL::Polyhedron_3<Kernel> Source;
@ -57,9 +58,9 @@ int main(int argc, char* argv[])
boost::unordered_map<sm_halfedge_descriptor, tm_halfedge_descriptor> h2h; boost::unordered_map<sm_halfedge_descriptor, tm_halfedge_descriptor> h2h;
boost::unordered_map<sm_face_descriptor, tm_face_descriptor> f2f; boost::unordered_map<sm_face_descriptor, tm_face_descriptor> f2f;
CGAL::copy_face_graph(S, T2, std::inserter(v2v, v2v.end()), CGAL::copy_face_graph(S, T2, CGAL::parameters::vertex_to_vertex_output_iterator(std::inserter(v2v, v2v.end()))
std::inserter(h2h, h2h.end()), .halfedge_to_halfedge_output_iterator(std::inserter(h2h, h2h.end()))
std::inserter(f2f, f2f.end())); .face_to_face_output_iterator(std::inserter(f2f, f2f.end())));
OpenMesh::IO::write_mesh(T2, "om.off"); OpenMesh::IO::write_mesh(T2, "om.off");
} }
#endif #endif
@ -67,16 +68,22 @@ int main(int argc, char* argv[])
{ {
typedef boost::graph_traits<Target1>::vertex_descriptor source_vertex_descriptor; typedef boost::graph_traits<Target1>::vertex_descriptor source_vertex_descriptor;
typedef boost::graph_traits<Target1>::halfedge_descriptor source_halfedge_descriptor; typedef boost::graph_traits<Target1>::halfedge_descriptor source_halfedge_descriptor;
typedef boost::graph_traits<Target1>::face_descriptor source_face_descriptor;
typedef boost::graph_traits<Source>::vertex_descriptor tm_vertex_descriptor; typedef boost::graph_traits<Source>::vertex_descriptor tm_vertex_descriptor;
typedef boost::graph_traits<Source>::halfedge_descriptor tm_halfedge_descriptor; typedef boost::graph_traits<Source>::halfedge_descriptor tm_halfedge_descriptor;
typedef boost::graph_traits<Source>::face_descriptor tm_face_descriptor;
boost::unordered_map<source_vertex_descriptor, tm_vertex_descriptor> v2v; boost::unordered_map<source_vertex_descriptor, tm_vertex_descriptor> v2v;
boost::unordered_map<source_halfedge_descriptor, tm_halfedge_descriptor> h2h; boost::unordered_map<source_halfedge_descriptor, tm_halfedge_descriptor> h2h;
boost::unordered_map<source_face_descriptor, tm_face_descriptor> f2f;
CGAL::copy_face_graph(T1, S, std::inserter(v2v, v2v.end()), std::inserter(h2h, h2h.end())); CGAL::copy_face_graph(T1, S, std::inserter(v2v, v2v.end()), std::inserter(h2h, h2h.end()));
std::ofstream out("reverse.off"); std::ofstream out("reverse.off");
out << S; 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; return 0;
} }

View File

@ -29,8 +29,12 @@
#include <CGAL/boost/graph/Euler_operations.h> #include <CGAL/boost/graph/Euler_operations.h>
#include <CGAL/boost/graph/iterator.h> #include <CGAL/boost/graph/iterator.h>
#include <CGAL/boost/graph/helpers.h> #include <CGAL/boost/graph/helpers.h>
#include <CGAL/boost/graph/named_function_params.h>
#include <CGAL/boost/graph/named_params_helper.h>
#include <CGAL/property_map.h> #include <CGAL/property_map.h>
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/function_output_iterator.hpp>
namespace CGAL { namespace CGAL {
@ -208,7 +212,39 @@ void copy_face_graph(const SourceMesh& sm, TargetMesh& tm,
sm_vpm, tm_vpm); sm_vpm, tm_vpm);
} }
} // end of namespace internal } // end of namespace internal
namespace impl
{
template<typename PMAP>
struct Output_iterator_functor
{
typedef typename boost::property_traits<PMAP>::key_type input_t;
typedef typename boost::property_traits<PMAP>::value_type output_t;
PMAP map;
Output_iterator_functor(PMAP map)
:map(map)
{
}
void operator()(const typename std::pair<input_t, output_t>& pair)
{
put(map, pair.first, pair.second);
}
};
template<typename PMAP>
boost::function_output_iterator<Output_iterator_functor<PMAP> > make_functor(PMAP map)
{
return boost::make_function_output_iterator(Output_iterator_functor<PMAP>(map));
}
inline Emptyset_iterator make_functor(const boost::param_not_found&)
{
return Emptyset_iterator();
}
}//end of impl
/*! /*!
\ingroup PkgBGLHelperFct \ingroup PkgBGLHelperFct
@ -223,50 +259,115 @@ void copy_face_graph(const SourceMesh& sm, TargetMesh& tm,
and `boost::graph_traits<SourceMesh>::%face_descriptor` must be and `boost::graph_traits<SourceMesh>::%face_descriptor` must be
models of `Hashable`. models of `Hashable`.
\tparam TargetMesh a model of `FaceListGraph` \tparam TargetMesh a model of `FaceListGraph`
\tparam V2V a model of `OutputIterator` accepting `std::pair<sm_vertex_descriptor, tm_vertex_descriptor>` \tparam NamedParameters1 a sequence of \ref pmp_namedparameters "Named Parameters"
\tparam H2H a model of `OutputIterator` accepting `std::pair<sm_halfedge_descriptor, tm_halfedge_descriptor>` \tparam NamedParameters2 a sequence of \ref pmp_namedparameters "Named Parameters"
\tparam F2F a model of `OutputIterator` accepting `std::pair<sm_face_descriptor, tm_face_descriptor>`
\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.
The types `sm_vertex_descriptor` and `sm_face_descriptor` must be models of the concept `Hashable`. The types `sm_vertex_descriptor` and `sm_face_descriptor` must be models of the concept `Hashable`.
\param sm the source mesh \param sm the source mesh
\param tm the target 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 np1 optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below
\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` \cgalNamedParamsBegin
\param sm_vpm vertex point map for `sm` \cgalParamBegin{vertex_point_map}
\param tm_vpm vertex point map for `tm` 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 The points from `sm` to `tm` are converted using
`CGAL::Cartesian_converter<SourceKernel, TargetKernel>`. `CGAL::Cartesian_converter<SourceKernel, TargetKernel>`.
`SourceKernel` and `TargetKernel` are deduced using `CGAL::Kernel_traits` `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. Other properties are not copied.
*/ */
#if defined(DOXYGEN_RUNNING) // Use template default arguments
template <typename SourceMesh, typename TargetMesh, template <typename SourceMesh, typename TargetMesh,
typename V2V = Emptyset_iterator, #ifndef DOXYGEN_RUNNING
typename H2H = Emptyset_iterator, typename T1, typename Tag1, typename Base1,
typename F2F = Emptyset_iterator, typename T2, typename Tag2, typename Base2
typename Src_vpm = typename boost::property_map<SourceMesh, vertex_point_t>::const_type, #else
typename Tgt_vpm = typename boost::property_map<TargetMesh, vertex_point_t>::type> typename NamedParameters1, typename NamedParameters2
#endif
>
void copy_face_graph(const SourceMesh& sm, TargetMesh& tm, void copy_face_graph(const SourceMesh& sm, TargetMesh& tm,
V2V v2v = V2V(), H2H h2h = H2H(), F2F f2f = F2F(), #ifndef DOXYGEN_RUNNING
Src_vpm sm_vpm = get(vertex_point, sm), const CGAL::cgal_bgl_named_params<T1,Tag1,Base1>& np1,
Tgt_vpm tm_vpm = get(vertex_point, tm) ) const CGAL::cgal_bgl_named_params<T2,Tag2,Base2>& np2
#else // use the overloads #else
const NamedParameters1& np1,
const NamedParameters2& np2
#endif
)
{
using boost::choose_param;
internal::copy_face_graph(sm, tm,
CGAL::graph_has_property<SourceMesh,boost::halfedge_index_t>(),
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 <typename SourceMesh, typename TargetMesh>
void copy_face_graph(const SourceMesh& sm, TargetMesh& tm)
{
copy_face_graph(sm, tm, parameters::all_default(), parameters::all_default());
}
template <typename SourceMesh, typename TargetMesh,
typename T, typename Tag, typename Base >
void copy_face_graph(const SourceMesh& sm, TargetMesh& tm,
const CGAL::cgal_bgl_named_params<T,Tag,Base>& np)
{
copy_face_graph(sm, tm, np, parameters::all_default());
}
#if !defined(DOXYGEN_RUNNING)
template <typename SourceMesh, typename TargetMesh, template <typename SourceMesh, typename TargetMesh,
typename V2V, typename H2H, typename F2F, typename V2V, typename H2H, typename F2F,
typename Src_vpm, typename Tgt_vpm> typename Src_vpm, typename Tgt_vpm>
void copy_face_graph(const SourceMesh& sm, TargetMesh& tm, void copy_face_graph(const SourceMesh& sm, TargetMesh& tm,
V2V v2v, H2H h2h, F2F f2f, V2V v2v, H2H h2h, F2F f2f,
Src_vpm sm_vpm, Tgt_vpm tm_vpm ) Src_vpm sm_vpm, Tgt_vpm tm_vpm )
#endif
{ {
internal::copy_face_graph(sm, tm, internal::copy_face_graph(sm, tm,
CGAL::graph_has_property<SourceMesh,boost::halfedge_index_t>(), CGAL::graph_has_property<SourceMesh,boost::halfedge_index_t>(),
@ -274,11 +375,6 @@ void copy_face_graph(const SourceMesh& sm, TargetMesh& tm,
sm_vpm, tm_vpm); sm_vpm, tm_vpm);
} }
#if !defined(DOXYGEN_RUNNING)
template <typename SourceMesh, typename TargetMesh>
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 <typename SourceMesh, typename TargetMesh, typename V2V> template <typename SourceMesh, typename TargetMesh, typename V2V>
void copy_face_graph(const SourceMesh& sm, TargetMesh& tm, V2V v2v) void copy_face_graph(const SourceMesh& sm, TargetMesh& tm, V2V v2v)

View File

@ -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(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(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' // 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) CGAL_add_named_parameter(vertex_feature_degree_t, vertex_feature_degree, vertex_feature_degree_map)

View File

@ -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::METIS_options).v == 800000001);
assert(get_param(np, CGAL::internal_np::vertex_partition_id).v == 800000002); 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::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' // Named parameters that we use in the package 'Mesh_3'
assert(get_param(np, CGAL::internal_np::vertex_feature_degree).v == 9); 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<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<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<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' // Named parameters that we use in the package 'Mesh_3'
check_same_type<9>(get_param(np, CGAL::internal_np::vertex_feature_degree)); check_same_type<9>(get_param(np, CGAL::internal_np::vertex_feature_degree));
@ -178,6 +193,12 @@ int main()
.METIS_options(A<800000001>(800000001)) .METIS_options(A<800000001>(800000001))
.vertex_partition_id_map(A<800000002>(800000002)) .vertex_partition_id_map(A<800000002>(800000002))
.face_partition_id_map(A<800000003>(800000003)) .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)) .vertex_feature_degree_map(A<9>(9))
.geom_traits(A<10>(10)) .geom_traits(A<10>(10))
.vertex_incident_patches_map(A<11>(11)) .vertex_incident_patches_map(A<11>(11))

View File

@ -66,6 +66,7 @@ Release date: September 2018
to reflect the real needs of the code (some types and operators were used to reflect the real needs of the code (some types and operators were used
in the code but did not appear in the concepts). in the code but did not appear in the concepts).
### Point Set Processing ### Point Set Processing
- Added a callback mechanism to the following functions: - 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::pca_estimate_normals()`, `CGAL::remove_outliers()` and
`CGAL::wlop_simplify_and_regularize_point_set()`. `CGAL::wlop_simplify_and_regularize_point_set()`.
### Polygon Mesh Processing ### Polygon Mesh Processing
- Added a named parameter in stitching functions that allows to choose whether the operation should - 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()` - 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). (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 ### 3D Mesh Generation
- **Breaking change:** The template parameters of the class template - **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 - 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. 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 - **Breaking change**: `CGAL::lloyd_optimize_mesh_3` now depends on
the _Eigen_ library. the _Eigen_ library.
@ -164,6 +167,17 @@ Release date: September 2018
- Improved the function `CGAL::Euler::collapse_edge` such that the target - Improved the function `CGAL::Euler::collapse_edge` such that the target
vertex of the collapsed edge is now always kept after the collapse. 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 ### CGAL and Solvers
- **Breaking change**: `CGAL::Diagonalize_traits` is now deprecated - **Breaking change**: `CGAL::Diagonalize_traits` is now deprecated

View File

@ -86,8 +86,7 @@ function \ref PkgInterpolationNaturalNeighborCoordinates2.
\tparam OutputFunctor must be a functor with argument type `std::pair<Dt::Vertex_handle, Traits::Vector_d>`. \tparam OutputFunctor must be a functor with argument type `std::pair<Dt::Vertex_handle, Traits::Vector_d>`.
Note that the result type of the functor is not specified and is chosen by users to fit their needs. 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: \tparam ValueFunctor must be a functor where:
- `ValueFunctor::argument_type` must be either `std::pair<Dt::Vertex_handle, Dt::Geom_traits::FT>` - `ValueFunctor::argument_type` must be either `Dt::Vertex_handle` or `Dt::Point`.
or `std::pair<Dt::Point, Dt::Geom_traits::FT>`.
- `ValueFunctor::result_type` is a pair of the function value type and a Boolean. - `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 The function value type must provide a multiplication and addition operation with the type
`Traits::FT` as well as a constructor with argument `0`. `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<Rt::Vertex_handle, Traits::Vector_d>`. \tparam OutputFunctor must be a functor with argument type `std::pair<Rt::Vertex_handle, Traits::Vector_d>`.
Note that the result type of the functor is not specified and is chosen by users to fit their needs. 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: \tparam ValueFunctor must be a functor where:
- `ValueFunctor::argument_type` must be either `std::pair<Rt::Vertex_handle, Rt::Geom_traits::FT>` - `ValueFunctor::argument_type` must be either `Rt::Vertex_handle` or `Rt::Weighted_point`.
or `std::pair<Rt::Weighted_point, Rt::Geom_traits::FT>`.
- `ValueFunctor::result_type` is a pair of the function value type and a Boolean. - `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 The function value type must provide a multiplication and addition operation with the type
`Traits::FT` as well as a constructor with argument `0`. `Traits::FT` as well as a constructor with argument `0`.

View File

@ -94,6 +94,7 @@ int main()
Delaunay_triangulation T; Delaunay_triangulation T;
// Note that a supported alternative to creating the functors below is to use lambdas
Value_function<Vertex_handle, Coord_type> value_function; Value_function<Vertex_handle, Coord_type> value_function;
Gradient_function<Vertex_handle, Vector> gradient_function; Gradient_function<Vertex_handle, Vector> gradient_function;

View File

@ -73,6 +73,7 @@ int main()
{ {
Regular_triangulation rt; Regular_triangulation rt;
// Note that a supported alternative to creating the functors below is to use lambdas
Value_function<Vertex_handle, Coord_type> value_function; Value_function<Vertex_handle, Coord_type> value_function;
Gradient_function<Vertex_handle, Vector> gradient_function; Gradient_function<Vertex_handle, Vector> gradient_function;

View File

@ -74,6 +74,7 @@ int main()
{ {
Delaunay_triangulation dt; Delaunay_triangulation dt;
// Note that a supported alternative to creating the functors below is to use lambdas
Value_function<Vertex_handle, Coord_type> value_function; Value_function<Vertex_handle, Coord_type> value_function;
Gradient_function<Vertex_handle, Vector> gradient_function; Gradient_function<Vertex_handle, Vector> gradient_function;

View File

@ -27,6 +27,8 @@
#include <CGAL/double.h> #include <CGAL/double.h>
#include <CGAL/use.h> #include <CGAL/use.h>
#include <boost/utility/result_of.hpp>
#include <iterator> #include <iterator>
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -58,17 +60,21 @@ struct Data_access
//the interpolation functions: //the interpolation functions:
template < class ForwardIterator, class ValueFunctor > template < class ForwardIterator, class ValueFunctor >
typename ValueFunctor::result_type::first_type typename boost::result_of<
ValueFunctor(typename std::iterator_traits<ForwardIterator>::value_type::first_type)>
::type::first_type
linear_interpolation(ForwardIterator first, ForwardIterator beyond, linear_interpolation(ForwardIterator first, ForwardIterator beyond,
const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm, const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm,
ValueFunctor value_function) ValueFunctor value_function)
{ {
CGAL_precondition(norm > 0); CGAL_precondition(norm > 0);
typedef typename ValueFunctor::result_type::first_type Value_type; typedef typename std::iterator_traits<ForwardIterator>::value_type::first_type arg_type;
typedef typename boost::result_of<ValueFunctor(arg_type)>::type result_type;
typedef typename result_type::first_type Value_type;
Value_type result(0); Value_type result(0);
typename ValueFunctor::result_type val; result_type val;
for(; first!=beyond; ++first) for(; first!=beyond; ++first)
{ {
val = value_function(first->first); val = value_function(first->first);
@ -78,9 +84,12 @@ linear_interpolation(ForwardIterator first, ForwardIterator beyond,
return result; return result;
} }
template < class ForwardIterator, class ValueFunctor, class GradFunctor, class Traits, class 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<ForwardIterator>::value_type::first_type)>
::type::first_type,
bool>
quadratic_interpolation(ForwardIterator first, ForwardIterator beyond, quadratic_interpolation(ForwardIterator first, ForwardIterator beyond,
const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm, const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm,
const Point& p, const Point& p,
@ -89,15 +98,20 @@ quadratic_interpolation(ForwardIterator first, ForwardIterator beyond,
const Traits& traits) const Traits& traits)
{ {
CGAL_precondition(norm > 0); 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<ForwardIterator>::value_type::first_type arg_type;
typedef typename boost::result_of<ValueFunctor(arg_type)>::type value_functor_result_type;
typedef typename boost::result_of<GradFunctor(arg_type)>::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<Traits> cp(traits); Interpolation::internal::Extract_bare_point<Traits> cp(traits);
const Bare_point& bp = cp(p); const Bare_point& bp = cp(p);
Value_type result(0); Value_type result(0);
typename ValueFunctor::result_type f; value_functor_result_type f;
typename GradFunctor::result_type grad; gradient_functor_result_type grad;
for(; first!=beyond; ++first) 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 > 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<ForwardIterator>::value_type::first_type)>
::type::first_type,
bool>
sibson_c1_interpolation(ForwardIterator first, ForwardIterator beyond, sibson_c1_interpolation(ForwardIterator first, ForwardIterator beyond,
const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm, const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm,
const Point& p, const Point& p,
@ -129,17 +147,21 @@ sibson_c1_interpolation(ForwardIterator first, ForwardIterator beyond,
{ {
CGAL_precondition(norm >0); CGAL_precondition(norm >0);
typedef typename ValueFunctor::result_type::first_type Value_type; typedef typename std::iterator_traits<ForwardIterator>::value_type::first_type arg_type;
typedef typename Traits::FT Coord_type; typedef typename boost::result_of<ValueFunctor(arg_type)>::type value_functor_result_type;
typedef typename Traits::Point_d Bare_point; typedef typename boost::result_of<GradFunctor(arg_type)>::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<Traits> cp(traits); Interpolation::internal::Extract_bare_point<Traits> cp(traits);
const Bare_point& bp = cp(p); const Bare_point& bp = cp(p);
Coord_type term1(0), term2(term1), term3(term1), term4(term1); Coord_type term1(0), term2(term1), term3(term1), term4(term1);
Value_type linear_int(0), gradient_int(0); Value_type linear_int(0), gradient_int(0);
typename ValueFunctor::result_type f; value_functor_result_type f;
typename GradFunctor::result_type grad; gradient_functor_result_type grad;
for(; first!=beyond; ++first) 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())); // 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 > 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<ForwardIterator>::value_type::first_type)>
::type::first_type,
bool>
sibson_c1_interpolation_square(ForwardIterator first, ForwardIterator beyond, sibson_c1_interpolation_square(ForwardIterator first, ForwardIterator beyond,
const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm, const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm,
const Point& p, const Point& p,
@ -203,17 +229,21 @@ sibson_c1_interpolation_square(ForwardIterator first, ForwardIterator beyond,
{ {
CGAL_precondition(norm > 0); CGAL_precondition(norm > 0);
typedef typename ValueFunctor::result_type::first_type Value_type; typedef typename std::iterator_traits<ForwardIterator>::value_type::first_type arg_type;
typedef typename Traits::FT Coord_type; typedef typename boost::result_of<ValueFunctor(arg_type)>::type value_functor_result_type;
typedef typename Traits::Point_d Bare_point; typedef typename boost::result_of<GradFunctor(arg_type)>::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<Traits> cp(traits); Interpolation::internal::Extract_bare_point<Traits> cp(traits);
const Bare_point& bp = cp(p); const Bare_point& bp = cp(p);
Coord_type term1(0), term2(term1), term3(term1), term4(term1); Coord_type term1(0), term2(term1), term3(term1), term4(term1);
Value_type linear_int(0), gradient_int(0); Value_type linear_int(0), gradient_int(0);
typename ValueFunctor::result_type f; value_functor_result_type f;
typename GradFunctor::result_type grad; gradient_functor_result_type grad;
for(; first!=beyond; ++first) for(; first!=beyond; ++first)
{ {
@ -257,7 +287,11 @@ sibson_c1_interpolation_square(ForwardIterator first, ForwardIterator beyond,
template < class RandomAccessIterator, class ValueFunctor, class GradFunctor, template < class RandomAccessIterator, class ValueFunctor, class GradFunctor,
class Traits, class Point_> class Traits, class Point_>
std::pair< typename ValueFunctor::result_type::first_type, bool> std::pair<
typename boost::result_of<
ValueFunctor(typename std::iterator_traits<RandomAccessIterator>::value_type::first_type)>
::type::first_type,
bool>
farin_c1_interpolation(RandomAccessIterator first, farin_c1_interpolation(RandomAccessIterator first,
RandomAccessIterator beyond, RandomAccessIterator beyond,
const typename std::iterator_traits<RandomAccessIterator>::value_type::second_type& norm, const typename std::iterator_traits<RandomAccessIterator>::value_type::second_type& norm,
@ -268,14 +302,16 @@ farin_c1_interpolation(RandomAccessIterator first,
{ {
CGAL_precondition(norm >0); CGAL_precondition(norm >0);
// the function value is available for all points typedef typename std::iterator_traits<RandomAccessIterator>::value_type::first_type arg_type;
// if a gradient value is not availble: function returns false typedef typename boost::result_of<ValueFunctor(arg_type)>::type value_functor_result_type;
typedef typename ValueFunctor::result_type::first_type Value_type; typedef typename boost::result_of<GradFunctor(arg_type)>::type gradient_functor_result_type;
typedef typename Traits::FT Coord_type; typedef typename value_functor_result_type::first_type Value_type;
typedef typename Traits::FT Coord_type;
Interpolation::internal::Extract_bare_point<Traits> cp(traits); Interpolation::internal::Extract_bare_point<Traits> cp(traits);
typename ValueFunctor::result_type f; value_functor_result_type f;
typename GradFunctor::result_type grad; gradient_functor_result_type grad;
int n = static_cast<int>(beyond - first); int n = static_cast<int>(beyond - first);
if(n == 1) if(n == 1)

View File

@ -29,14 +29,22 @@
#include <CGAL/regular_neighbor_coordinates_2.h> #include <CGAL/regular_neighbor_coordinates_2.h>
#include <CGAL/Origin.h> #include <CGAL/Origin.h>
#include <CGAL/function.h>
#include <boost/any.hpp>
#include <boost/mpl/if.hpp> #include <boost/mpl/if.hpp>
#include <boost/type_traits/is_same.hpp> #include <boost/utility/enable_if.hpp>
#include <boost/utility/result_of.hpp>
#include <iterator> #include <iterator>
#include <utility> #include <utility>
#include <vector> #include <vector>
#ifdef CGAL_CXX11
#include <type_traits>
#include <functional>
#endif
namespace CGAL { namespace CGAL {
template < class ForwardIterator, class ValueFunctor, class Traits, class Point > template < class ForwardIterator, class ValueFunctor, class Traits, class Point >
@ -45,12 +53,17 @@ sibson_gradient_fitting(ForwardIterator first,
ForwardIterator beyond, ForwardIterator beyond,
const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm, const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm,
const Point& p, const Point& p,
const typename ValueFunctor::result_type::first_type fn, const typename boost::result_of<
ValueFunctor(typename std::iterator_traits<ForwardIterator>::value_type::first_type)>
::type::first_type fn,
ValueFunctor value_function, ValueFunctor value_function,
const Traits& traits) const Traits& traits)
{ {
CGAL_precondition( first != beyond && norm != 0); CGAL_precondition( first != beyond && norm != 0);
typedef typename std::iterator_traits<ForwardIterator>::value_type::first_type arg_type;
typedef typename boost::result_of<ValueFunctor(arg_type)>::type value_functor_result_type;
typedef typename Traits::Aff_transformation_d Aff_transformation; typedef typename Traits::Aff_transformation_d Aff_transformation;
typedef typename Traits::FT Coord_type; typedef typename Traits::FT Coord_type;
typedef typename Traits::Point_d Bare_point; 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); typename Traits::Vector_d d = traits.construct_vector_d_object()(bp, bare_f);
// compute the vector pn: // 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 CGAL_assertion(f.second); // function value of first->first is valid
pn = pn + traits.construct_scaled_vector_d_object()(d, scale * (f.first - fn)); 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, ValueFunctor value_function,
const Traits& traits) const Traits& traits)
{ {
typename ValueFunctor::result_type fn = value_function(p); typedef typename std::iterator_traits<ForwardIterator>::value_type::first_type arg_type;
typedef typename boost::result_of<ValueFunctor(arg_type)>::type value_functor_result_type;
value_functor_result_type fn = value_function(p);
CGAL_assertion(fn.second); CGAL_assertion(fn.second);
return sibson_gradient_fitting(first, beyond, norm, p, fn.first, value_function, traits); 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. // types of arguments and pass a final (bare) point + value to the function above.
template < class ForwardIterator, class ValueFunctor, class Traits, class VH > template < class ForwardIterator, class ValueFunctor, class Traits, class VH >
typename Traits::Vector_d typename Traits::Vector_d
sibson_gradient_fitting_internal(ForwardIterator first, sibson_gradient_fitting_internal_with_dummy(ForwardIterator first,
ForwardIterator beyond, ForwardIterator beyond,
const typename std::iterator_traits< const typename std::iterator_traits<
ForwardIterator>::value_type::second_type& norm, ForwardIterator>::value_type::second_type& norm,
VH vh, VH vh,
ValueFunctor value_function, ValueFunctor value_function,
const Traits& traits, const Traits& traits,
const typename Traits::Point_d& /*dummy*/) const typename Traits::Point_d& /*dummy*/)
{ {
typedef typename std::iterator_traits<ForwardIterator>::value_type::first_type arg_type;
typedef typename boost::result_of<ValueFunctor(arg_type)>::type value_functor_result_type;
const typename Traits::Point_d& bare_p = traits.construct_point_d_object()(vh->point()); 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); CGAL_assertion(fn.second);
return sibson_gradient_fitting(first, beyond, norm, bare_p, fn.first, value_function, traits); 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 > template < class ForwardIterator, class ValueFunctor, class Traits, class VH >
typename Traits::Vector_d typename Traits::Vector_d
sibson_gradient_fitting_internal(ForwardIterator first, sibson_gradient_fitting_internal_with_dummy(ForwardIterator first,
ForwardIterator beyond, ForwardIterator beyond,
const typename std::iterator_traits< const typename std::iterator_traits<
ForwardIterator>::value_type::second_type& norm, ForwardIterator>::value_type::second_type& norm,
VH vh, VH vh,
ValueFunctor value_function, ValueFunctor value_function,
const Traits& traits, const Traits& traits,
const typename Traits::Weighted_point_d& /*dummy*/) const typename Traits::Weighted_point_d& /*dummy*/)
{ {
typename ValueFunctor::result_type fn = value_function(vh->point()); typedef typename std::iterator_traits<ForwardIterator>::value_type::first_type arg_type;
typedef typename boost::result_of<ValueFunctor(arg_type)>::type value_functor_result_type;
value_functor_result_type fn = value_function(vh->point());
CGAL_assertion(fn.second); CGAL_assertion(fn.second);
return sibson_gradient_fitting(first, beyond, norm, vh->point(), fn.first, value_function, traits); 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 > template < class ForwardIterator, class ValueFunctor, class Traits, class VH >
typename Traits::Vector_d typename Traits::Vector_d
sibson_gradient_fitting_internal(ForwardIterator first, sibson_gradient_fitting_internal_with_dummy(ForwardIterator first,
ForwardIterator beyond, ForwardIterator beyond,
const typename std::iterator_traits< const typename std::iterator_traits<
ForwardIterator>::value_type::second_type& norm, ForwardIterator>::value_type::second_type& norm,
VH vh, VH vh,
ValueFunctor value_function, ValueFunctor value_function,
const Traits& traits, const Traits& traits,
VH /*dummy*/) VH /*dummy*/)
{ {
typedef typename std::iterator_traits<ForwardIterator>::value_type::first_type arg_type;
typedef typename boost::result_of<ValueFunctor(arg_type)>::type value_functor_result_type;
const typename Traits::Point_d& bare_p = traits.construct_point_d_object()(vh->point()); 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); CGAL_assertion(fn.second);
return sibson_gradient_fitting(first, beyond, norm, bare_p, fn.first, value_function, traits); 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 > class ValueFunctor, class CoordFunctor, class Traits >
OutputIterator OutputIterator
sibson_gradient_fitting_internal(const Tr& tr, 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; typedef typename Tr::Vertex_handle Vertex_handle;
Coord_type norm; Coord_type norm;
std::vector<std::pair<typename ValueFunctor::argument_type, Coord_type> > coords; std::vector<std::pair<ValueFunctorArgType, Coord_type> > coords;
typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(); typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin();
for(; vit != tr.finite_vertices_end(); ++vit) 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; norm = compute_coordinates(tr, vit, std::back_inserter(coords), Coord_OutputFunctor()).second;
*out++ = fct(std::make_pair(vit, *out++ = fct(std::make_pair(vit,
sibson_gradient_fitting_internal(coords.begin(), sibson_gradient_fitting_internal_with_dummy(coords.begin(),
coords.end(), coords.end(),
norm, norm,
Vertex_handle(vit), Vertex_handle(vit),
value_function, value_function,
traits, traits,
typename ValueFunctor::argument_type()))); ValueFunctorArgType())));
coords.clear(); coords.clear();
} }
@ -196,12 +222,73 @@ sibson_gradient_fitting_internal(const Tr& tr,
return out; return out;
} }
// The following functions allow to fit the gradients for all points in // The following functions allow to fit the gradients for all points in
// a triangulation except the convex hull points. // a triangulation except the convex hull points.
// -> _nn2: natural_neighbor_coordinates_2 // -> _nn2: natural_neighbor_coordinates_2
// -> _rn2: regular_neighbor_coordinates_2 // -> _rn2: regular_neighbor_coordinates_2
// -> _sn2_3: surface_neighbor_coordinates_2_3 // -> _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<boost::any(typename Dt::Point)>,
ValueFunctor
>::value>::type* = NULL)
{
typedef typename Traits::FT FT;
typedef typename Dt::Point VF_arg_type;
typedef typename std::back_insert_iterator<std::vector<
std::pair<VF_arg_type, FT> > > CoordInserter;
typedef Interpolation::internal::Extract_point_in_pair<Dt, FT> Coord_OutputFunctor;
return sibson_gradient_fitting_internal<VF_arg_type>(dt, out, fct, value_function,
natural_neighbor_coordinates_2_object<Dt,
CoordInserter,
Coord_OutputFunctor>(),
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<boost::any(typename Dt::Vertex_handle)>,
ValueFunctor
>::value>::type* = NULL)
{
typedef typename Traits::FT FT;
typedef typename Dt::Vertex_handle VF_arg_type;
typedef typename std::back_insert_iterator<std::vector<
std::pair<VF_arg_type, FT> > > CoordInserter;
typedef CGAL::Identity<std::pair<VF_arg_type, FT> > Coord_OutputFunctor;
return sibson_gradient_fitting_internal<VF_arg_type>(dt, out, fct, value_function,
natural_neighbor_coordinates_2_object<Dt,
CoordInserter,
Coord_OutputFunctor>(),
traits);
}
#else // not CGAL_CXX11
template < class Dt, class OutputIterator, class OutputFunctor, class ValueFunctor, class Traits > template < class Dt, class OutputIterator, class OutputFunctor, class ValueFunctor, class Traits >
OutputIterator OutputIterator
sibson_gradient_fitting_nn_2(const Dt& dt, sibson_gradient_fitting_nn_2(const Dt& dt,
@ -224,15 +311,16 @@ sibson_gradient_fitting_nn_2(const Dt& dt,
CGAL::Identity<std::pair<VF_arg_type, FT> > CGAL::Identity<std::pair<VF_arg_type, FT> >
>::type Coord_OutputFunctor; >::type Coord_OutputFunctor;
return sibson_gradient_fitting_internal(dt, out, fct, value_function, return sibson_gradient_fitting_internal<VF_arg_type>(dt, out, fct, value_function,
natural_neighbor_coordinates_2_object<Dt, natural_neighbor_coordinates_2_object<Dt,
CoordInserter, CoordInserter,
Coord_OutputFunctor>(), Coord_OutputFunctor>(),
traits); traits);
} }
#endif // CGAL_CXX11
// Same as above but without OutputFunctor.
// Same as above but without OutputFunctor. Default to extracting the point, for backward compatibility. // Defaults to extracting the point, for backward compatibility.
template < class Dt, class OutputIterator, class ValueFunctor, class Traits > template < class Dt, class OutputIterator, class ValueFunctor, class Traits >
OutputIterator OutputIterator
sibson_gradient_fitting_nn_2(const Dt& dt, 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); 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<boost::any(typename Rt::Point)>,
ValueFunctor
>::value>::type* = NULL)
{
typedef typename Traits::FT FT;
typedef typename Rt::Point VF_arg_type;
typedef typename std::back_insert_iterator<std::vector<
std::pair<VF_arg_type, FT> > > CoordInserter;
typedef Interpolation::internal::Extract_point_in_pair<Rt, FT> Coord_OutputFunctor;
return sibson_gradient_fitting_internal<VF_arg_type>(rt, out, fct, value_function,
regular_neighbor_coordinates_2_object<Rt,
CoordInserter,
Coord_OutputFunctor>(),
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<boost::any(typename Rt::Vertex_handle)>,
ValueFunctor
>::value>::type* = NULL)
{
typedef typename Traits::FT FT;
typedef typename Rt::Vertex_handle VF_arg_type;
typedef typename std::back_insert_iterator<std::vector<
std::pair<VF_arg_type, FT> > > CoordInserter;
typedef CGAL::Identity<std::pair<VF_arg_type, FT> > Coord_OutputFunctor;
return sibson_gradient_fitting_internal<VF_arg_type>(rt, out, fct, value_function,
regular_neighbor_coordinates_2_object<Rt,
CoordInserter,
Coord_OutputFunctor>(),
traits);
}
#else // CGAL_CXX11
template < class Rt, class OutputIterator, class OutputFunctor, class ValueFunctor, class Traits > template < class Rt, class OutputIterator, class OutputFunctor, class ValueFunctor, class Traits >
OutputIterator OutputIterator
@ -269,13 +415,14 @@ sibson_gradient_fitting_rn_2(const Rt& rt,
CGAL::Identity<std::pair<VF_arg_type, FT> > CGAL::Identity<std::pair<VF_arg_type, FT> >
>::type Coord_OutputFunctor; >::type Coord_OutputFunctor;
return sibson_gradient_fitting_internal(rt, out, fct, value_function, return sibson_gradient_fitting_internal<VF_arg_type>(rt, out, fct, value_function,
regular_neighbor_coordinates_2_object<Rt, regular_neighbor_coordinates_2_object<Rt,
CoordInserter, CoordInserter,
Coord_OutputFunctor>(), Coord_OutputFunctor>(),
traits); traits);
} }
#endif
// Same as above but without OutputFunctor. Default to extracting the point, for backward compatibility. // Same as above but without OutputFunctor. Default to extracting the point, for backward compatibility.
template < class Rt, class OutputIterator, class ValueFunctor, class Traits > template < class Rt, class OutputIterator, class ValueFunctor, class Traits >

View File

@ -31,11 +31,14 @@
#include <CGAL/algorithm.h> #include <CGAL/algorithm.h>
#include <CGAL/double.h> #include <CGAL/double.h>
#include <CGAL/function_objects.h> #include <CGAL/function_objects.h>
#include <CGAL/function.h>
#include <CGAL/Origin.h> #include <CGAL/Origin.h>
#include <CGAL/point_generators_2.h> #include <CGAL/point_generators_2.h>
#include <CGAL/Random.h> #include <CGAL/Random.h>
#include <CGAL/squared_distance_2.h> #include <CGAL/squared_distance_2.h>
#include <boost/utility/result_of.hpp>
#include <iostream> #include <iostream>
#include <cassert> #include <cassert>
#include <utility> #include <utility>
@ -47,6 +50,8 @@ struct Extract_point
typedef typename Traits::Point_2 Point_2; typedef typename Traits::Point_2 Point_2;
typedef typename Traits::Weighted_point_2 Weighted_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) {} Extract_point(const Traits& traits = Traits()) : traits(traits) {}
const Point_2& operator()(const Point_2& p) const { return p; } const Point_2& operator()(const Point_2& p) const { return p; }
@ -56,7 +61,8 @@ struct Extract_point
} }
template <typename VH> template <typename VH>
const Point_2& operator()(const VH& vh) const { typename boost::result_of<const Construct_point_2(const Point_2&)>::type
operator()(const VH& vh) const {
return traits.construct_point_2_object()(vh->point()); return traits.construct_point_2_object()(vh->point());
} }
@ -64,6 +70,42 @@ private:
Traits traits; Traits traits;
}; };
template <typename V, typename T>
struct Value_function
{
typedef V argument_type;
typedef std::pair<T, bool> 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 <typename V, typename G>
struct Gradient_function
: public CGAL::cpp98::iterator<std::output_iterator_tag, void, void, void, void>
{
typedef V argument_type;
typedef std::pair<G, bool> 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 > template < class ForwardIterator >
bool test_norm(ForwardIterator first, ForwardIterator beyond, bool test_norm(ForwardIterator first, ForwardIterator beyond,
typename std::iterator_traits<ForwardIterator>::value_type::second_type norm) typename std::iterator_traits<ForwardIterator>::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, bool test_barycenter(ForwardIterator first, ForwardIterator beyond,
typename std::iterator_traits<ForwardIterator>::value_type::second_type norm, typename std::iterator_traits<ForwardIterator>::value_type::second_type norm,
const typename std::iterator_traits<ForwardIterator>::value_type::first_type& p, const Point& p,
const typename std::iterator_traits<ForwardIterator>::value_type::second_type& tolerance) const typename std::iterator_traits<ForwardIterator>::value_type::second_type& tolerance)
{ {
typedef typename Tr::Geom_traits Gt; 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<ForwardIterator>::value_type::second_type& exact_value, const typename std::iterator_traits<ForwardIterator>::value_type::second_type& exact_value,
CGAL::Field_with_sqrt_tag) CGAL::Field_with_sqrt_tag)
{ {
typename ValueFunctor::result_type res = CGAL::sibson_c1_interpolation(first, beyond, typedef typename std::iterator_traits<ForwardIterator>::value_type::first_type arg_type;
norm, p, f, typedef typename boost::result_of<ValueFunctor(arg_type)>::type value_functor_result_type;
grad_f, geom_traits);
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); 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, bool test_interpolation_with_value(ForwardIterator first, ForwardIterator beyond,
const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm, const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm,
const Point& p, const Point& p,
const typename ValueFunctor::result_type::first_type exact_value, const typename boost::result_of<
ValueFunctor(typename std::iterator_traits<ForwardIterator>::value_type::first_type)>
::type::first_type exact_value,
ValueFunctor f, ValueFunctor f,
GradFunctor grad_f, GradFunctor grad_f,
const Gt& geom_traits, const Gt& geom_traits,
const int& i, const int& i,
const typename std::iterator_traits<ForwardIterator>::value_type::second_type& tolerance) const typename std::iterator_traits<ForwardIterator>::value_type::second_type& tolerance)
{ {
typedef typename ValueFunctor::result_type::first_type Value_type; typedef typename std::iterator_traits<ForwardIterator>::value_type::first_type arg_type;
typedef typename boost::result_of<ValueFunctor(arg_type)>::type value_functor_result_type;
typedef typename value_functor_result_type::first_type Value_type;
if(i == 0) if(i == 0)
{ {
@ -158,8 +208,8 @@ bool test_interpolation_with_value(ForwardIterator first, ForwardIterator beyond
assert(CGAL_NTS abs(val - exact_value) <= tolerance); assert(CGAL_NTS abs(val - exact_value) <= tolerance);
} }
typename ValueFunctor::result_type res = CGAL::quadratic_interpolation(first, beyond, norm, p, f, value_functor_result_type res = CGAL::quadratic_interpolation(first, beyond, norm, p, f,
grad_f, geom_traits); grad_f, geom_traits);
assert(res.second && (CGAL_NTS abs(res.first - exact_value) <= tolerance)); assert(res.second && (CGAL_NTS abs(res.first - exact_value) <= tolerance));
if(i<2) if(i<2)
@ -185,20 +235,17 @@ bool test_interpolation_with_value(ForwardIterator first, ForwardIterator beyond
return true; 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, bool test_interpolation(ForwardIterator first, ForwardIterator beyond,
const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm, const typename std::iterator_traits<ForwardIterator>::value_type::second_type& norm,
const Point& p, const Point& p,
const Value_type exact_value,
ValueFunctor f, ValueFunctor f,
GradFunctor grad_f, GradFunctor grad_f,
const Gt& geom_traits, const Gt& geom_traits,
const int& i, const int& i,
const typename std::iterator_traits<ForwardIterator>::value_type::second_type& tolerance) const typename std::iterator_traits<ForwardIterator>::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); 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::FT Coord_type;
typedef typename Gt::Vector_2 Vector; typedef typename Gt::Vector_2 Vector;
typedef std::map<Point, Coord_type, typename Gt::Less_xy_2> Point_value_map ; typedef std::map<Point, Coord_type, typename Gt::Less_xy_2> Point_value_map;
typedef std::map<Point, Vector, typename Gt::Less_xy_2> Point_vector_map; typedef std::map<Point, Vector, typename Gt::Less_xy_2> Point_vector_map;
typedef std::vector<std::pair<Point, Coord_type> > Point_coordinate_vector; typedef std::vector<std::pair<Point, Coord_type> > 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) 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_value_map >(values[i]),
CGAL::Data_access< Point_vector_map >(gradients[i]), CGAL::Data_access< Point_vector_map >(gradients[i]),
Traits(), i, tolerance)); 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) 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<Point_value_map>(values[j]), CGAL::Data_access<Point_value_map>(values[j]),
CGAL::Data_access<Point_vector_map>(gradients[j]), CGAL::Data_access<Point_vector_map>(gradients[j]),
Traits(), j, tolerance)); 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 typename Dt::Geom_traits Gt;
typedef CGAL::Interpolation_traits_2<Gt> Traits; typedef CGAL::Interpolation_traits_2<Gt> Traits;
typedef typename Dt::Vertex_handle Vertex_handle;
typedef typename Gt::FT Coord_type; typedef typename Gt::FT Coord_type;
typedef typename Dt::Point Point; typedef typename Dt::Point Point;
typedef typename Gt::Vector_2 Vector; typedef typename Gt::Vector_2 Vector;
typedef std::map<Point, Coord_type, typename Gt::Less_xy_2> Point_value_map ; typedef std::vector<std::pair<Vertex_handle, Coord_type> > Coordinate_vector;
typedef std::map<Point, Vector, typename Gt::Less_xy_2> Point_vector_map; typedef typename Coordinate_vector::const_iterator CV_cit;
typedef CGAL::Identity<std::pair<Vertex_handle, Coord_type> > Output_functor;
typedef std::vector<std::pair<Point, Coord_type> > Point_coordinate_vector; typedef std::map<Point, Coord_type> Point_value_map;
typedef typename Point_coordinate_vector::const_iterator PCV_cit; typedef std::map<Point, Vector> Point_vector_map;
typedef CGAL::Interpolation::internal::Extract_point_in_pair<Dt, Coord_type> Point_output_functor;
std::cout << "NN2: Testing random points." << std::endl; 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; 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)), Coord_type alpha = Coord_type(random.get_double(-max_value, max_value)),
beta1 = 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)), 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)); gamma3 = Coord_type(random.get_double(-max_value, max_value));
//INSERTION + DET. of GRADIENT for n DATA POINTS : //INSERTION + DET. of GRADIENT for n DATA POINTS :
for(int j=0; j<n; ++j)
{
T.insert(points[j]);
gradients[0].insert(std::make_pair(points[j], Vector(beta1, beta2)));
gradients[1].insert(std::make_pair(points[j],
Vector(beta1 + Coord_type(2)*gamma1*points[j].x(),
beta2 + Coord_type(2)*gamma1*points[j].y())));
gradients[2].insert(std::make_pair(points[j],
Vector(beta1 + Coord_type(2)*gamma1*points[j].x() + gamma3*points[j].y(),
beta2 + Coord_type(2)*gamma2*points[j].y() + gamma3*points[j].x())));
}
//DETERMINE VALUES FOR n DATA POINTS AND m RANDOM TEST POINTS: //DETERMINE VALUES FOR n DATA POINTS AND m RANDOM TEST POINTS:
for(int j=0; j<n+m; j++) Point_value_map exact_values[3];
std::map<Point, Vertex_handle> p_to_vh;
for(int j=0; j<n+m; ++j)
{ {
// linear function Vector gradient0(beta1, beta2);
values[0].insert(std::make_pair(points[j], alpha + beta1*points[j].x() + beta2*points[j].y())); Vector gradient1(beta1 + Coord_type(2)*gamma1*points[j].x(),
beta2 + Coord_type(2)*gamma1*points[j].y());
Vector gradient2(beta1 + Coord_type(2)*gamma1*points[j].x() + gamma3*points[j].y(),
beta2 + Coord_type(2)*gamma2*points[j].y() + gamma3*points[j].x());
// spherical function: Coord_type value0 = alpha + beta1*points[j].x() + beta2*points[j].y();
values[1].insert(std::make_pair(points[j], alpha + beta1*points[j].x() + Coord_type value1 = alpha + beta1*points[j].x()
beta2*points[j].y() + + beta2*points[j].y()
gamma1*points[j].x()*points[j].x()+ + gamma1*points[j].x()*points[j].x()
gamma1*points[j].y()*points[j].y())); + gamma1*points[j].y()*points[j].y();
Coord_type value2 = alpha + beta1*points[j].x()
+ beta2*points[j].y()
+ gamma1*points[j].x()*points[j].x()
+ gamma2*points[j].y()*points[j].y()
+ gamma3*points[j].x()*points[j].y();
// quadratic function if(j<n) // only insert n points
values[2].insert(std::make_pair(points[j], alpha + beta1*points[j].x() + {
beta2*points[j].y() + Vertex_handle vh = T.insert(points[j]);
gamma1*points[j].x()*points[j].x() + p_to_vh[points[j]] = vh;
gamma2*points[j].y()*points[j].y() +
gamma3*points[j].x()*points[j].y())); vh->info()[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: //INTERPOLATION OF RANDOM POINTS:
Coord_type norm; Coord_type norm;
Point_coordinate_vector pt_coords; Coordinate_vector coords;
Point_output_functor pt_fct; Output_functor out_fct;
for(int j=n; j<n+m; ++j) for(int j=n; j<n+m; ++j)
{ {
CGAL::Triple<std::back_insert_iterator<Point_coordinate_vector>, Coord_type, bool> coordinate_result = CGAL::Triple<std::back_insert_iterator<Coordinate_vector>, Coord_type, bool> coordinate_result =
CGAL::natural_neighbor_coordinates_2(T, points[j], std::back_inserter(pt_coords), pt_fct); CGAL::natural_neighbor_coordinates_2(T, points[j], std::back_inserter(coords), out_fct);
assert(coordinate_result.third); assert(coordinate_result.third);
norm = coordinate_result.second; 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(norm > 0);
assert(is_equal); assert(is_equal);
is_equal = test_barycenter<Dt>(pt_coords.begin(), pt_coords.end(), norm, points[j], tolerance); is_equal = test_barycenter<Dt>(coords.begin(), coords.end(), norm, points[j], tolerance);
assert(is_equal); 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<Coord_type, bool> { return std::make_pair(vh->info()[0].value, true); },
[](const Vertex_handle vh) -> std::pair<Vector, bool> { return std::make_pair(vh->info()[0].gradient, true); },
Traits(), 0, tolerance));
// wrapping the lambda in a std function
CGAL::cpp11::function<std::pair<Coord_type, bool>(const Vertex_handle)> value_function_1 =
[](const Vertex_handle vh) -> std::pair<Coord_type, bool> { return std::make_pair(vh->info()[1].value, true); };
std::function<std::pair<Vector, bool>(const Vertex_handle)> gradient_function_1 =
[](const Vertex_handle vh) -> std::pair<Vector, bool> { 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<Coord_type, bool> { return std::make_pair(vh->info()[2].value, true); },
[](const Vertex_handle vh) -> std::pair<Vector, bool> { return std::make_pair(vh->info()[2].gradient, true); },
Traits(), 2, tolerance));
#else
for(int i=0; i<3; ++i) for(int i=0; i<3; ++i)
{ {
assert(test_interpolation(pt_coords.begin(), pt_coords.end(), norm, points[j], Value_function<Vertex_handle, Coord_type> value_function(i);
CGAL::Data_access< Point_value_map >(values[i]), Gradient_function<Vertex_handle, Vector> gradient_function(i);
CGAL::Data_access< Point_vector_map >(gradients[i]),
assert(test_interpolation(coords.begin(), coords.end(), norm,
points[j], exact_values[i][points[j]],
value_function, gradient_function,
Traits(), i, tolerance)); Traits(), i, tolerance));
} }
pt_coords.clear(); #endif
coords.clear();
} }
//TESTING THE GRADIENT APPRXIMATION METHOD: //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; std::cout << "Testing gradient estimation method on random points." << std::endl;
typedef CGAL::Interpolation_gradient_fitting_traits_2<Gt> GradTraits; typedef CGAL::Interpolation_gradient_fitting_traits_2<Gt> GradTraits;
Point_vector_map approx_gradients[2]; 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<Dt, Vector>(), // OutputFunctor
[](const Vertex_handle vh)
-> std::pair<Coord_type, bool>
{ return std::make_pair(vh->info()[0].value, true); },
GradTraits());
std::function<std::pair<Coord_type, bool>(const Vertex_handle)> value_function_1 =
[](const Vertex_handle vh) -> std::pair<Coord_type, bool> { 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<Dt, Vector>(),
value_function_1,
GradTraits());
}
#else
Value_function<Vertex_handle, Coord_type> value_function_0(0);
Value_function<Vertex_handle, Coord_type> value_function_1(1);
CGAL::sibson_gradient_fitting_nn_2(T, CGAL::sibson_gradient_fitting_nn_2(T,
std::inserter(approx_gradients[0], approx_gradients[0].begin()), // OutputIterator std::inserter(approx_gradients[0], approx_gradients[0].begin()), // OutputIterator
CGAL::Interpolation::internal::Extract_point_in_pair<Dt, Vector>(), // OutputFunctor CGAL::Interpolation::internal::Extract_point_in_pair<Dt, Vector>(), // OutputFunctor
CGAL::Data_access<Point_value_map>(values[0]), // ValueFunctor value_function_0,
GradTraits()); GradTraits());
CGAL::sibson_gradient_fitting_nn_2(T, CGAL::sibson_gradient_fitting_nn_2(T,
std::inserter(approx_gradients[1], approx_gradients[1].begin()), std::inserter(approx_gradients[1], approx_gradients[1].begin()),
CGAL::Interpolation::internal::Extract_point_in_pair<Dt, Vector>(), CGAL::Interpolation::internal::Extract_point_in_pair<Dt, Vector>(),
CGAL::Data_access<Point_value_map>(values[1]), value_function_1,
GradTraits()); GradTraits());
#endif
for(int j=0; j<n; ++j) for(int j=0; j<n; ++j)
{ {
@ -518,16 +635,19 @@ void _test_interpolation_functions_2_Delaunay_with_OutputFunctor(const Dt&, cons
if(res.second) if(res.second)
{ {
Gradient_function<Vertex_handle, Vector> gradient_function_0(0);
Gradient_function<Vertex_handle, Vector> gradient_function_1(1);
// if it is the exact computation kernel: test the equality: // if it is the exact computation kernel: test the equality:
assert(tolerance > Coord_type(0) || assert(tolerance > Coord_type(0) ||
res.first == CGAL::Data_access<Point_vector_map>(gradients[0])(points[j]).first); res.first == (gradient_function_0(p_to_vh[points[j]])).first);
res = CGAL::Data_access<Point_vector_map>(approx_gradients[1])(points[j]); res = CGAL::Data_access<Point_vector_map>(approx_gradients[1])(points[j]);
// if one exists->the other must also exist // if one exists->the other must also exist
assert(res.second); assert(res.second);
assert(tolerance > Coord_type(0) || assert(tolerance > Coord_type(0) ||
res.first == CGAL::Data_access<Point_vector_map>(gradients[1])(points[j]).first); res.first == gradient_function_1(p_to_vh[points[j]]).first);
} }
else else
{ {
@ -536,31 +656,66 @@ void _test_interpolation_functions_2_Delaunay_with_OutputFunctor(const Dt&, cons
} }
//TESTING A POINT == A DATA POINT: //TESTING A POINT == A DATA POINT:
CGAL::Triple<std::back_insert_iterator<Point_coordinate_vector>, Coord_type, bool> coordinate_result = CGAL::Triple<std::back_insert_iterator<Coordinate_vector>, Coord_type, bool> coordinate_result =
CGAL::natural_neighbor_coordinates_2(T, points[n/2], std::back_inserter(pt_coords), pt_fct); CGAL::natural_neighbor_coordinates_2(T, points[n/2], std::back_inserter(coords), out_fct);
assert(coordinate_result.third); assert(coordinate_result.third);
norm = coordinate_result.second; norm = coordinate_result.second;
assert(norm == Coord_type(1)); assert(norm == Coord_type(1));
PCV_cit ci = pt_coords.begin(); CV_cit ci = coords.begin();
assert(ci->first == points[n/2]); assert(ci->first == p_to_vh[points[n/2]]);
assert(ci->second == Coord_type(1)); assert(ci->second == Coord_type(1));
ci++; ci++;
assert(ci == pt_coords.end()); assert(ci == coords.end());
#ifdef CGAL_CXX11
Value_function<Vertex_handle, Coord_type> value_function_0(0);
Value_function<Vertex_handle, Coord_type> 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<Coord_type, bool> { return std::make_pair(vh->info()[0].value, true); },
[](const Vertex_handle vh) -> std::pair<Vector, bool> { return std::make_pair(vh->info()[0].gradient, true); },
Traits(), 0, tolerance));
// wrapping the lambda in a std function
CGAL::cpp11::function<std::pair<Coord_type, bool>(const Vertex_handle)> value_function_1 =
[](const Vertex_handle vh) -> std::pair<Coord_type, bool> { return std::make_pair(vh->info()[1].value, true); };
std::function<std::pair<Vector, bool>(const Vertex_handle)> gradient_function_1 =
[](const Vertex_handle vh) -> std::pair<Vector, bool> { 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<Coord_type, bool> { return std::make_pair(vh->info()[2].value, true); },
[](const Vertex_handle vh) -> std::pair<Vector, bool> { return std::make_pair(vh->info()[2].gradient, true); },
Traits(), 2, tolerance));
#else
for(int j=0; j<3; ++j) for(int j=0; j<3; ++j)
{ {
assert(test_interpolation(pt_coords.begin(), pt_coords.end(), norm, points[n/2], Value_function<Vertex_handle, Coord_type> value_function(j);
CGAL::Data_access<Point_value_map>(values[j]), Gradient_function<Vertex_handle, Vector> gradient_function(j);
CGAL::Data_access<Point_vector_map>(gradients[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)); Traits(), j, tolerance));
} }
pt_coords.clear(); #endif
coords.clear();
} }
template <class Rt> template <class Rt>
void _test_interpolation_functions_2_regular_without_OutputFunctor(const Rt&, const typename Rt::Geom_traits::FT& tolerance) 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; CGAL::Set_ieee_double_precision pfr;
Rt T; 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::FT Coord_type;
typedef typename Gt::Vector_2 Vector; typedef typename Gt::Vector_2 Vector;
typedef std::map<Weighted_point, Coord_type> Point_value_map ; typedef std::map<Weighted_point, Coord_type> Point_value_map;
typedef std::map<Weighted_point, Vector> Point_vector_map; typedef std::map<Weighted_point, Vector> Point_vector_map;
typedef std::vector<std::pair<Weighted_point, Coord_type> > Point_coordinate_vector; typedef std::vector<std::pair<Weighted_point, Coord_type> > 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: // test random points in a square of length r:
std::vector<Weighted_point> points; std::vector<Weighted_point> points;
@ -674,7 +829,8 @@ void _test_interpolation_functions_2_regular_without_OutputFunctor(const Rt&, co
for(int i=0; i<3; ++i) 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_value_map >(values[i]),
CGAL::Data_access< Point_vector_map >(gradients[i]), CGAL::Data_access< Point_vector_map >(gradients[i]),
Traits(), i, tolerance)); 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) 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<Point_value_map>(values[j]), CGAL::Data_access<Point_value_map>(values[j]),
CGAL::Data_access<Point_vector_map>(gradients[j]), CGAL::Data_access<Point_vector_map>(gradients[j]),
Traits(), j, tolerance)); 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; typedef typename Rt::Vertex_handle Vertex_handle;
// These are the values at points which won't be inserted in the triangulation // These are the values at points which won't be inserted in the triangulation
typedef std::map<Weighted_point, Coord_type> Point_value_map ; typedef std::map<Weighted_point, Coord_type> Point_value_map;
typedef std::map<Vertex_handle, Coord_type> Vertex_value_map; typedef std::map<Vertex_handle, Coord_type> Vertex_value_map;
typedef std::map<Vertex_handle, Vector> Vertex_vector_map; typedef std::map<Vertex_handle, Vector> Vertex_vector_map;
@ -782,7 +939,7 @@ void _test_interpolation_functions_2_regular_with_OutputFunctor(const Rt&, const
Identity_output_functor vh_fct; 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: // test random points in a square of length r:
std::vector<Weighted_point> points; std::vector<Weighted_point> points;
@ -979,8 +1136,8 @@ void _test_interpolation_functions_2_regular_with_OutputFunctor(const Rt&, const
std::pair<FT, bool> ev = CGAL::Data_access<Vertex_value_map>(values[j])(vh); std::pair<FT, bool> ev = CGAL::Data_access<Vertex_value_map>(values[j])(vh);
assert(ev.second); assert(ev.second);
assert(test_interpolation_with_value(vh_coords.begin(), vh_coords.end(), norm, vh->point(), assert(test_interpolation_with_value(vh_coords.begin(), vh_coords.end(), norm,
ev.first /*exact value*/, vh->point(), ev.first /*exact value*/,
CGAL::Data_access<Vertex_value_map>(values[j]), CGAL::Data_access<Vertex_value_map>(values[j]),
CGAL::Data_access<Vertex_vector_map>(gradients[j]), CGAL::Data_access<Vertex_vector_map>(gradients[j]),
Traits(), j, tolerance)); Traits(), j, tolerance));

View File

@ -21,44 +21,59 @@
#include <CGAL/Exact_predicates_exact_constructions_kernel.h> #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/array.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Delaunay_triangulation_2.h> #include <CGAL/Delaunay_triangulation_2.h>
#include <CGAL/Regular_triangulation_2.h> #include <CGAL/Regular_triangulation_2.h>
#include <CGAL/Origin.h>
#include <iostream> #include <iostream>
typedef CGAL::Exact_predicates_exact_constructions_kernel K; typedef CGAL::Exact_predicates_exact_constructions_kernel EPECK;
typedef CGAL::Delaunay_triangulation_2<K> Dt; typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK;
typedef CGAL::Regular_triangulation_2<K> Rt;
typedef CGAL::Exact_predicates_inexact_constructions_kernel K2; template <typename V, typename G>
typedef CGAL::Delaunay_triangulation_2<K2> Dt2; struct Value_and_gradient
typedef CGAL::Regular_triangulation_2<K2> Rt2; {
Value_and_gradient() : value(), gradient(CGAL::NULL_VECTOR) {}
V value;
G gradient;
};
template<typename Kernel>
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<Coord_type, Vector>, 3>,
Kernel> Vb;
typedef CGAL::Triangulation_data_structure_2<Vb> Tds;
typedef CGAL::Delaunay_triangulation_2<Kernel, Tds> Delaunay_triangulation;
typedef CGAL::Regular_triangulation_2<Kernel> 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() int main()
{ {
std::cout << "Testing interpolation functions with 2D NN neighbors " std::cout << "--------------------------------------------" << std::endl;
<< std::endl; std::cout << "Testing with EPECK" << std::endl;
std::cout << " using Exact_predicates_exact_constructions_kernel: " test_interpolation_functions<EPECK>();
<< std::endl ;
_test_interpolation_functions_2_Delaunay(Dt(), K::FT(1e-10));
std::cout << "Testing interpolation functions with 2D NN neighbors " std::cout << "--------------------------------------------" << std::endl;
<< std::endl; std::cout << "Testing with EPICK" << std::endl;
std::cout << " using Exact_predicates_inexact_constructions_kernel: " test_interpolation_functions<EPICK>();
<< 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 << "test_interpolation_functions_2 is finished" << std::endl; std::cout << "test_interpolation_functions_2 is finished" << std::endl;

View File

@ -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::isotropic_remeshing()` \endlink
- \link PMP_meshing_grp `CGAL::Polygon_mesh_processing::split_long_edges()` \endlink - \link PMP_meshing_grp `CGAL::Polygon_mesh_processing::split_long_edges()` \endlink
- `CGAL::Polygon_mesh_processing::random_perturbation()` - `CGAL::Polygon_mesh_processing::random_perturbation()`
- `CGAL::Polygon_mesh_processing::extrude_mesh()`
## Hole Filling Functions ## ## Hole Filling Functions ##
- `CGAL::Polygon_mesh_processing::triangulate_hole()` - `CGAL::Polygon_mesh_processing::triangulate_hole()`

View File

@ -419,22 +419,16 @@ corefine_and_compute_boolean_operations(
if (output[Corefinement::UNION] != boost::none) if (output[Corefinement::UNION] != boost::none)
if (&tm1 != *output[Corefinement::UNION]) if (&tm1 != *output[Corefinement::UNION])
copy_face_graph(tm1, copy_face_graph(tm1,
*(*output[Corefinement::UNION]), *(*output[Corefinement::UNION]),
Emptyset_iterator(), parameters::vertex_point_map(vpm1),
Emptyset_iterator(), parameters::vertex_point_map(*cpp11::get<Corefinement::UNION>(vpm_out_tuple)));
Emptyset_iterator(),
vpm1,
*cpp11::get<Corefinement::UNION>(vpm_out_tuple));
if (output[Corefinement::INTERSECTION] != boost::none) if (output[Corefinement::INTERSECTION] != boost::none)
if (&tm1 != *output[Corefinement::INTERSECTION]) if (&tm1 != *output[Corefinement::INTERSECTION])
copy_face_graph(tm1, copy_face_graph(tm1,
*(*output[Corefinement::INTERSECTION]), *(*output[Corefinement::INTERSECTION]),
Emptyset_iterator(), parameters::vertex_point_map(vpm1),
Emptyset_iterator(), parameters::vertex_point_map(*cpp11::get<Corefinement::INTERSECTION>(vpm_out_tuple)));
Emptyset_iterator(),
vpm1,
*cpp11::get<Corefinement::INTERSECTION>(vpm_out_tuple));
if (output[Corefinement::TM1_MINUS_TM2] != boost::none) if (output[Corefinement::TM1_MINUS_TM2] != boost::none)
if (&tm1 == *output[Corefinement::TM1_MINUS_TM2]) if (&tm1 == *output[Corefinement::TM1_MINUS_TM2])

View File

@ -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 <CGAL/license/Polygon_mesh_processing/meshing_hole_filling.h>
#include <CGAL/Polygon_mesh_processing/orientation.h>
#include <CGAL/boost/graph/named_params_helper.h>
#include <CGAL/boost/graph/named_function_params.h>
#include <CGAL/boost/graph/copy_face_graph.h>
#include <CGAL/Kernel_traits.h>
#include <CGAL/boost/graph/Euler_operations.h>
#include <vector>
namespace CGAL {
namespace Polygon_mesh_processing {
namespace extrude_impl{
template<typename BorderHalfedgesRange, class PolygonMesh>
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<PolygonMesh>::halfedge_descriptor halfedge_descriptor;
typedef typename boost::graph_traits<PolygonMesh>::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<halfedge_descriptor, 4> 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<typename PMAP, typename Vector>
struct Const_dist_translation{
Const_dist_translation(PMAP map, const Vector& dir)
:map(map), dir(dir){}
template<typename VertexDescriptor, typename U>
void operator()(const VertexDescriptor vd, const U&) const
{
typename boost::property_traits<PMAP>::value_type p = get(map, vd) + dir;
put(map, vd, p);
}
PMAP map;
Vector dir;
};
struct Identity_functor
{
template<typename T, typename U>
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<InputMesh>::vertex_descriptor input_v,boost::graph_traits<OutputMesh>::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 <class InputMesh,
class OutputMesh,
class BottomFunctor,
class TopFunctor,
class NamedParameters1,
class NamedParameters2
>
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<InputMesh>::vertex_descriptor input_vertex_descriptor;
typedef typename boost::graph_traits<InputMesh>::halfedge_descriptor input_halfedge_descriptor;
typedef typename boost::graph_traits<OutputMesh>::vertex_descriptor output_vertex_descriptor;
typedef typename boost::graph_traits<OutputMesh>::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<std::pair<input_vertex_descriptor, output_vertex_descriptor> > bottom_v2v;
std::vector<std::pair<input_halfedge_descriptor, output_halfedge_descriptor> > 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<std::pair<input_vertex_descriptor, output_vertex_descriptor> > top_v2v;
std::vector<std::pair<input_halfedge_descriptor, output_halfedge_descriptor> > 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<output_halfedge_descriptor> border_hedges;
std::vector<output_halfedge_descriptor> 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 <class InputMesh,
class OutputMesh,
class NamedParameters1,
class NamedParameters2>
void extrude_mesh(const InputMesh& input,
OutputMesh& output,
#ifdef DOXYGEN_RUNNING
Vector_3 v,
#else
typename GetGeomTraits<OutputMesh, NamedParameters2>::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<OutputMesh, NamedParameters2>::type,
typename GetGeomTraits<OutputMesh, NamedParameters2>::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 <class InputMesh,
class OutputMesh,
typename Vector>
void extrude_mesh(const InputMesh& input,
OutputMesh& output,
Vector dir)
{
extrude_mesh(input, output, dir,
parameters::all_default(),
parameters::all_default());
}
template <class InputMesh,
class OutputMesh,
typename Vector,
typename CGAL_PMP_NP_TEMPLATE_PARAMETERS>
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 <class InputMesh,
class OutputMesh,
class BottomFunctor,
class TopFunctor>
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

View File

@ -44,6 +44,11 @@
#include <CGAL/Polygon_mesh_processing/remesh.h> #include <CGAL/Polygon_mesh_processing/remesh.h>
#include <CGAL/Polygon_mesh_processing/corefinement.h> #include <CGAL/Polygon_mesh_processing/corefinement.h>
#include <CGAL/Polygon_mesh_processing/detect_features.h> #include <CGAL/Polygon_mesh_processing/detect_features.h>
#include <CGAL/Polygon_mesh_processing/extrude.h>
#include <CGAL/Polygon_mesh_processing/random_perturbation.h>
#include <CGAL/Polygon_mesh_processing/distance.h>
#include <CGAL/Polygon_mesh_processing/intersection.h>
#include <CGAL/Polygon_mesh_processing/transform.h>
// the named parameter header being not documented the doc is put here for now // the named parameter header being not documented the doc is put here for now
#ifdef DOXYGEN_RUNNING #ifdef DOXYGEN_RUNNING

View File

@ -100,6 +100,7 @@ endif()
create_single_source_cgal_program("surface_intersection_sm_poly.cpp" ) 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_orient_cc.cpp")
create_single_source_cgal_program("test_pmp_transform.cpp") create_single_source_cgal_program("test_pmp_transform.cpp")
create_single_source_cgal_program("extrude_test.cpp")
if( TBB_FOUND ) if( TBB_FOUND )
CGAL_target_use_TBB(test_pmp_distance) CGAL_target_use_TBB(test_pmp_distance)

View File

@ -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

View File

@ -0,0 +1,74 @@
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Polygon_mesh_processing/extrude.h>
#include <iostream>
#include <fstream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Surface_mesh<Kernel::Point_3> SMesh;
typedef CGAL::Polyhedron_3<Kernel> Polyhedron;
template<typename MAP>
struct Bot
{
Bot(MAP map):map(map){}
template<typename VD, typename T>
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<typename MAP>
struct Top
{
Top(MAP map):map(map){}
template<typename VD, typename T>
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 <class Mesh>
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<Mesh, CGAL::vertex_point_t>::type VPMap;
Bot<VPMap> bot(get(CGAL::vertex_point, out));
Top<VPMap> 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<SMesh>(filename);
test_mesh<Polyhedron>(filename);
return 0;
}

View File

@ -181,10 +181,8 @@ void Polyhedron_demo_kernel_plugin::on_actionKernel_triggered()
vpm[fd] = CGAL::ORIGIN + normal / distance_to_origin + translate; vpm[fd] = CGAL::ORIGIN + normal / distance_to_origin + translate;
} }
CGAL::copy_face_graph(dual, *pKernel, CGAL::copy_face_graph(dual, *pKernel,
CGAL::Emptyset_iterator(), CGAL::parameters::vertex_point_map(
CGAL::Emptyset_iterator(), boost::make_assoc_property_map(vpm)));
CGAL::Emptyset_iterator(),
boost::make_assoc_property_map(vpm));
// pKernel->inside_out(); // pKernel->inside_out();

View File

@ -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_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" ) 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" )

View File

@ -0,0 +1,478 @@
#include <CGAL/Three/Polyhedron_demo_plugin_interface.h>
#include <QApplication>
#include <QObject>
#include <QAction>
#include <QMainWindow>
#include <QInputDialog>
#include <QMessageBox>
#include <CGAL/Three/Scene_item.h>
#include <CGAL/Three/Viewer_interface.h>
#include <CGAL/linear_least_squares_fitting_3.h>
#include <CGAL/Polygon_mesh_processing/extrude.h>
#include <CGAL/Polygon_mesh_processing/compute_normal.h>
#include <CGAL/Qt/manipulatedFrame.h>
#include <CGAL/Qt/constraint.h>
#include <CGAL/number_type_config.h>
#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<Viewer_interface*>(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<GLsizei>(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<QKeyEvent*>(event)->modifiers().testFlag(Qt::ControlModifier);
}
if(event->type() == QEvent::Wheel && ctrl_pressing)
{
QWheelEvent *mouseEvent = static_cast<QWheelEvent*>(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<float> vertices;
std::vector<float> normals;
int prec = 60;
//Head
const float Rf = static_cast<float>(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<GLsizei>(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<GLsizei>(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 <typename TriangleMesh, typename OutputIterator>
CGAL::Bbox_3 triangles(const TriangleMesh& mesh,
OutputIterator out)
{
CGAL::Bbox_3 bb;
typename boost::property_map<TriangleMesh,CGAL::vertex_point_t>::const_type vpm =
get(CGAL::vertex_point, mesh);
BOOST_FOREACH(typename boost::graph_traits<TriangleMesh>::face_descriptor fd, faces(mesh)){
typename boost::graph_traits<TriangleMesh>::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<Triangle>& 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_face_graph_item*>(scene->item(scene->mainSelectionIndex()))
|| qobject_cast<Scene_polyhedron_selection_item*>(scene->item(scene->mainSelectionIndex())));
}
else if(oliver_queen)
return true;
return false;
}
QList<QAction*> 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_polyhedron_selection_item*>(scene->item(scene->mainSelectionIndex()));
Scene_face_graph_item* fg_item = qobject_cast<Scene_face_graph_item*>(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<Triangle> 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<QAction*> _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"

View File

@ -638,6 +638,10 @@ void Viewer::attribBuffers(int program_name) const {
program->setUniformValue("clipbox1", clipbox1); program->setUniformValue("clipbox1", clipbox1);
program->setUniformValue("clipbox2", clipbox2); program->setUniformValue("clipbox2", clipbox2);
} }
if(program_name == PROGRAM_WITH_LIGHT)
{
program->setUniformValue("alpha", 1.0f); //overriden in item draw() if necessary
}
switch(program_name) switch(program_name)
{ {
case PROGRAM_WITH_LIGHT: case PROGRAM_WITH_LIGHT:

View File

@ -140,6 +140,8 @@ distance_plugin \
distance_sm_plugin \ distance_sm_plugin \
edit_polyhedron_plugin \ edit_polyhedron_plugin \
edit_sm_plugin \ edit_sm_plugin \
extrude_poly_plugin \
extrude_sm_plugin \
fairing_plugin \ fairing_plugin \
features_detection_plugin \ features_detection_plugin \
gocad_plugin \ gocad_plugin \

View File

@ -2,6 +2,18 @@ from sys import argv
from sys import exit from sys import exit
import codecs import codecs
import re 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 # a probably incomplete version to generate an anchor from a section name
def get_anchor(s): def get_anchor(s):
@ -13,7 +25,10 @@ def get_anchor(s):
s = s.replace(":","") s = s.replace(":","")
s = s.replace(",","") 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(">","") s = s.replace(">","")
s = s.replace("+","") s = s.replace("+","")
@ -23,8 +38,11 @@ def get_anchor(s):
s = s.lstrip(" ") s = s.lstrip(" ")
s = s.rstrip("\n") s = s.rstrip("\n")
s = s.rstrip(" ") s = s.rstrip(" ")
s = s.replace(" ","-") s = re.sub(r'\s+','-',s)
s = s.lower() if not args.codebase:
s = s.lower()
if args.codebase:
s = s.replace("'","-and-39-")
return "#"+s return "#"+s
# indices the nesting level (first level allowed is ##) # indices the nesting level (first level allowed is ##)
@ -45,11 +63,14 @@ def get_name(s):
#generate the entry for one section #generate the entry for one section
def get_toc_entry(s): def get_toc_entry(s):
name = get_name(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) anchor = get_anchor(s)
if level<0: if level<0:
return "ERROR: h1 section are not allowed" return "ERROR: h1 sections are not allowed"
res="* ["+name+"]("+anchor+")" res="* ["+name+"]("+anchor+")"
for i in range(0,level): for i in range(0,level):
@ -57,11 +78,7 @@ def get_toc_entry(s):
return res return res
#now the main #now the main
if len(argv) < 2: input = args.filename
print("Nothing done, no input file provided")
exit()
input = argv[1]
f = codecs.open(input, 'r', encoding='utf-8') f = codecs.open(input, 'r', encoding='utf-8')

View File

@ -27,12 +27,12 @@ typedef boost::graph_traits<SurfaceMesh>::face_descriptor face_descriptor;
namespace SMP = CGAL::Surface_mesh_parameterization; 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"); std::ifstream in((argc>1) ? argv[1] : "data/three_peaks.off");
if(!in) { if(!in) {
std::cerr << "Problem loading the input data" << std::endl; std::cerr << "Problem loading the input data" << std::endl;
return 1; return EXIT_FAILURE;
} }
SurfaceMesh sm; SurfaceMesh sm;
@ -52,11 +52,11 @@ int main(int argc, char * argv[])
if(err != SMP::OK) { if(err != SMP::OK) {
std::cerr << "Error: " << SMP::get_error_message(err) << std::endl; std::cerr << "Error: " << SMP::get_error_message(err) << std::endl;
return 1; return EXIT_FAILURE;
} }
std::ofstream out("result.off"); std::ofstream out("result.off");
SMP::IO::output_uvmap_to_off(sm, bhd, uv_map, out); SMP::IO::output_uvmap_to_off(sm, bhd, uv_map, out);
return 0; return EXIT_SUCCESS;
} }

View File

@ -37,12 +37,12 @@ typedef boost::graph_traits<Mesh>::face_descriptor face_descriptor;
namespace SMP = CGAL::Surface_mesh_parameterization; 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"); std::ifstream in_mesh((argc>1) ? argv[1] : "data/lion.off");
if(!in_mesh){ if(!in_mesh){
std::cerr << "Error: problem loading the input data" << std::endl; std::cerr << "Error: problem loading the input data" << std::endl;
return 1; return EXIT_FAILURE;
} }
SurfaceMesh sm; SurfaceMesh sm;
@ -97,6 +97,6 @@ int main(int argc, char * argv[])
std::ofstream out("result.off"); std::ofstream out("result.off");
SMP::IO::output_uvmap_to_off(mesh, bhd, uv_pm, out); SMP::IO::output_uvmap_to_off(mesh, bhd, uv_pm, out);
return 0; return EXIT_SUCCESS;
} }

View File

@ -41,7 +41,7 @@ typedef SurfaceMesh::Property_map<SM_halfedge_descriptor, Point_2> UV_pmap;
namespace SMP = CGAL::Surface_mesh_parameterization; namespace SMP = CGAL::Surface_mesh_parameterization;
int main(int argc, char * argv[]) int main(int argc, char** argv)
{ {
CGAL::Timer task_timer; CGAL::Timer task_timer;
task_timer.start(); task_timer.start();
@ -50,7 +50,7 @@ int main(int argc, char * argv[])
std::ifstream in_mesh(mesh_filename); std::ifstream in_mesh(mesh_filename);
if(!in_mesh) { if(!in_mesh) {
std::cerr << "Error: problem loading the input data" << std::endl; std::cerr << "Error: problem loading the input data" << std::endl;
return 1; return EXIT_FAILURE;
} }
SurfaceMesh sm; // underlying mesh of the seam mesh 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); parameterizer.parameterize(mesh, bhd, cmap, uvmap, vimap);
std::cout << "Finished in " << task_timer.time() << " seconds" << std::endl; std::cout << "Finished in " << task_timer.time() << " seconds" << std::endl;
return EXIT_SUCCESS;
} }

View File

@ -37,12 +37,12 @@ typedef boost::graph_traits<Mesh>::face_descriptor face_descriptor;
namespace SMP = CGAL::Surface_mesh_parameterization; 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"); std::ifstream in_mesh((argc>1)?argv[1]:"data/lion.off");
if(!in_mesh) { if(!in_mesh) {
std::cerr << "Error: problem loading the input data" << std::endl; std::cerr << "Error: problem loading the input data" << std::endl;
return 1; return EXIT_FAILURE;
} }
PolyMesh sm; PolyMesh sm;
@ -77,6 +77,6 @@ int main(int argc, char * argv[])
std::ofstream out("result.off"); std::ofstream out("result.off");
SMP::IO::output_uvmap_to_off(mesh, bhd, uv_pm, out); SMP::IO::output_uvmap_to_off(mesh, bhd, uv_pm, out);
return 0; return EXIT_SUCCESS;
} }

View File

@ -21,12 +21,12 @@ typedef boost::graph_traits<SurfaceMesh>::face_descriptor face_descriptor;
namespace SMP = CGAL::Surface_mesh_parameterization; 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"); std::ifstream in((argc>1) ? argv[1] : "data/nefertiti.off");
if(!in) { if(!in) {
std::cerr << "Problem loading the input data" << std::endl; std::cerr << "Problem loading the input data" << std::endl;
return 1; return EXIT_FAILURE;
} }
SurfaceMesh sm; SurfaceMesh sm;
@ -44,5 +44,5 @@ int main(int argc, char * argv[])
std::ofstream out("result.off"); std::ofstream out("result.off");
SMP::IO::output_uvmap_to_off(sm, bhd, uv_map, out); SMP::IO::output_uvmap_to_off(sm, bhd, uv_map, out);
return 0; return EXIT_SUCCESS;
} }

View File

@ -97,7 +97,7 @@ bool read_vertices(const PolyMesh& mesh,
return true; return true;
} }
int main(int argc, char * argv[]) int main(int argc, char** argv)
{ {
std::ifstream in((argc>1) ? argv[1] : "data/nefertiti.off"); std::ifstream in((argc>1) ? argv[1] : "data/nefertiti.off");
if(!in){ if(!in){
@ -118,7 +118,7 @@ int main(int argc, char * argv[])
Vd_array vda; Vd_array vda;
if(!read_vertices(sm, filename, vda)) { if(!read_vertices(sm, filename, vda)) {
std::cerr << "Error: problem loading the square corners" << std::endl; std::cerr << "Error: problem loading the square corners" << std::endl;
return 1; return EXIT_FAILURE;
} }
typedef SMP::Square_border_uniform_parameterizer_3<PolyMesh> Border_parameterizer; typedef SMP::Square_border_uniform_parameterizer_3<PolyMesh> Border_parameterizer;
@ -138,5 +138,5 @@ int main(int argc, char * argv[])
std::ofstream out("result.off"); std::ofstream out("result.off");
SMP::IO::output_uvmap_to_off(sm, bhd, uv_map, out); SMP::IO::output_uvmap_to_off(sm, bhd, uv_map, out);
return 0; return EXIT_SUCCESS;
} }

View File

@ -1327,8 +1327,11 @@ public:
NT energy_this = compute_current_energy(mesh, faces, ctmap, lp, lpmap, NT energy_this = compute_current_energy(mesh, faces, ctmap, lp, lpmap,
ltmap, uvmap); ltmap, uvmap);
NT energy_last; NT energy_last;
#ifdef CGAL_PARAMETERIZATION_ARAP_VERBOSE
std::cout << "Initial energy: " << energy_this << std::endl; std::cout << "Initial energy: " << energy_this << std::endl;
std::cout << m_iterations << " max iterations" << std::endl; std::cout << m_iterations << " max iterations" << std::endl;
#endif
// main loop // main loop
for(unsigned int ite=1; ite<=m_iterations; ++ite) for(unsigned int ite=1; ite<=m_iterations; ++ite)
@ -1342,7 +1345,9 @@ public:
energy_last = energy_this; energy_last = energy_this;
energy_this = compute_current_energy(mesh, faces, ctmap, lp, lpmap, energy_this = compute_current_energy(mesh, faces, ctmap, lp, lpmap,
ltmap, uvmap); ltmap, uvmap);
#ifdef CGAL_PARAMETERIZATION_ARAP_VERBOSE
std::cout << "Energy at iteration " << ite << " : " << energy_this << std::endl; std::cout << "Energy at iteration " << ite << " : " << energy_this << std::endl;
#endif
CGAL_warning(energy_this >= 0); CGAL_warning(energy_this >= 0);
if(status != OK) if(status != OK)
@ -1353,9 +1358,11 @@ public:
{ // also no need compute energy if this iteration is the last iteration { // also no need compute energy if this iteration is the last iteration
double energy_diff = std::abs((energy_last - energy_this) / energy_this); double energy_diff = std::abs((energy_last - energy_this) / energy_this);
if(energy_diff < m_tolerance) { if(energy_diff < m_tolerance) {
#ifdef CGAL_PARAMETERIZATION_ARAP_VERBOSE
std::cout << "Minimization process ended after: " std::cout << "Minimization process ended after: "
<< ite + 1 << " iterations. " << ite + 1 << " iterations. "
<< "Energy diff: " << energy_diff << std::endl; << "Energy diff: " << energy_diff << std::endl;
#endif
break; break;
} }
} }

View File

@ -744,7 +744,6 @@ public:
// Run the MVC // Run the MVC
parameterize_convex_hull_with_MVC(mesh, vertices, faces, ct, uvmap, vimap, vpmap); parameterize_convex_hull_with_MVC(mesh, vertices, faces, ct, uvmap, vimap, vpmap);
std::cout << "End of post processing" << std::endl;
return OK; return OK;
} }

View File

@ -110,10 +110,12 @@ Error_code read_cones(const TriangleMesh& tm, std::ifstream& in, VertexIndexMap
while(in >> cone_index) while(in >> cone_index)
cones.push_back(cone_index); cones.push_back(cone_index);
#ifdef CGAL_PARAMETERIZATION_ORBIFOLD_CONE_VERBOSE
std::cout << "Input cones: "; std::cout << "Input cones: ";
for(std::size_t i=0; i<cones.size(); ++i) for(std::size_t i=0; i<cones.size(); ++i)
std::cout << cones[i] << " "; std::cout << cones[i] << " ";
std::cout << std::endl; std::cout << std::endl;
#endif
if(cones.size() < 3 || cones.size() > 4) { if(cones.size() < 3 || cones.size() > 4) {
std::cerr << "Error: Not enough or too many input cones" << std::endl; std::cerr << "Error: Not enough or too many input cones" << std::endl;

View File

@ -34,8 +34,8 @@ namespace Surface_mesh_parameterization {
namespace internal { 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> template<typename K>
typename K::FT cotangent(const typename K::Point_3& P, typename K::FT cotangent(const typename K::Point_3& P,
const typename K::Point_3& Q, 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 u = P - Q;
Vector_3 v = R - Q; Vector_3 v = R - Q;
// (u . v) / ((u x v).len) NT dot = (u * v);
NT dot = (u*v); Vector_3 cross_vector = CGAL::cross_product(u, v);
Vector_3 cross_vector = CGAL::cross_product(u,v);
NT cross_norm = CGAL::sqrt(cross_vector * cross_vector); NT cross_norm = CGAL::sqrt(cross_vector * cross_vector);
if(cross_norm != 0.0) if(cross_norm != NT(0))
return (dot / cross_norm); return (dot / cross_norm);
else 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> template<typename K>
typename K::FT tangent(const typename K::Point_3& P, typename K::FT tangent(const typename K::Point_3& P,
const typename K::Point_3& Q, 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 u = P - Q;
Vector_3 v = R - Q; Vector_3 v = R - Q;
// (u . v) / ((u x v).len)
NT dot = (u * v); NT dot = (u * v);
Vector_3 cross_vector = CGAL::cross_product(u, v); Vector_3 cross_vector = CGAL::cross_product(u, v);
NT cross_norm = CGAL::sqrt(cross_vector * cross_vector); NT cross_norm = CGAL::sqrt(cross_vector * cross_vector);
if(dot != 0.0) if(dot != NT(0))
return (cross_norm / dot); return (cross_norm / dot);
else 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> template<typename K>
typename K::FT fix_sine(typename K::FT sine) 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 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> template<typename K>
typename K::FT compute_angle_rad(const typename K::Point_3& P, typename K::FT compute_angle_rad(const typename K::Point_3& P,
const typename K::Point_3& Q, 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 u = P - Q;
Vector_3 v = R - Q; Vector_3 v = R - Q;
// check
NT product = CGAL::sqrt(u * u) * CGAL::sqrt(v * v); NT product = CGAL::sqrt(u * u) * CGAL::sqrt(v * v);
if(product == 0) if(product == NT(0))
return 0.0; return 0;
// cosine // cosine
NT dot = (u * v); 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); Vector_3 w = CGAL::cross_product(u, v);
NT abs_sine = CGAL::sqrt(w * w) / product; NT abs_sine = CGAL::sqrt(w * w) / product;
if(cosine >= 0) if(cosine >= NT(0))
return std::asin(fix_sine<K>(abs_sine)); return std::asin(fix_sine<K>(abs_sine));
else else
return CGAL_PI - std::asin(fix_sine<K>(abs_sine)); return CGAL_PI - std::asin(fix_sine<K>(abs_sine));

View File

@ -130,7 +130,7 @@ void compute_shortest_paths_between_two_cones(const TriangleMesh& mesh,
EdgeOutputIterator oi) EdgeOutputIterator oi)
{ {
if(source == target) { 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; return;
} }
@ -150,7 +150,7 @@ void compute_shortest_paths_between_two_cones(const TriangleMesh& mesh,
try { try {
boost::dijkstra_shortest_paths(mesh, source, boost::predecessor_map(pred_pmap).visitor(vis)); boost::dijkstra_shortest_paths(mesh, source, boost::predecessor_map(pred_pmap).visitor(vis));
} catch (const std::exception& e) { } 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 // Draw the path from target to source and collect the edges along the way

View File

@ -92,7 +92,7 @@ int main(int, char**)
in >> pm; in >> pm;
if(!in || num_vertices(pm) == 0) { if(!in || num_vertices(pm) == 0) {
std::cerr << "Problem loading the input data" << std::endl; 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; PM_halfedge_descriptor hd = CGAL::Polygon_mesh_processing::longest_border(pm).first;
@ -108,7 +108,7 @@ int main(int, char**)
if(status != SMP::OK) { if(status != SMP::OK) {
std::cout << "Encountered a problem: " << status << std::endl; std::cout << "Encountered a problem: " << status << std::endl;
return 1; return EXIT_FAILURE;
} }
else { else {
std::cout << "Parameterized with MVC (POLY)!" << std::endl; std::cout << "Parameterized with MVC (POLY)!" << std::endl;
@ -129,7 +129,7 @@ int main(int, char**)
in >> pm; in >> pm;
if(!in || num_vertices(pm) == 0) { if(!in || num_vertices(pm) == 0) {
std::cerr << "Problem loading the input data" << std::endl; 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; PM_halfedge_descriptor hd = CGAL::Polygon_mesh_processing::longest_border(pm).first;
@ -162,7 +162,7 @@ int main(int, char**)
if(status != SMP::OK) { if(status != SMP::OK) {
std::cout << "Encountered a problem: " << status << std::endl; std::cout << "Encountered a problem: " << status << std::endl;
return 1; return EXIT_FAILURE;
} }
else { else {
std::cout << "Parameterized with ARAP (POLY)!" << std::endl; std::cout << "Parameterized with ARAP (POLY)!" << std::endl;
@ -183,7 +183,7 @@ int main(int, char**)
in >> sm; in >> sm;
if(!in || num_vertices(sm) == 0) { if(!in || num_vertices(sm) == 0) {
std::cerr << "Problem loading the input data" << std::endl; 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; SM_halfedge_descriptor hd = CGAL::Polygon_mesh_processing::longest_border(sm).first;
@ -214,7 +214,7 @@ int main(int, char**)
if(status != SMP::OK) { if(status != SMP::OK) {
std::cout << "Encountered a problem: " << status << std::endl; std::cout << "Encountered a problem: " << status << std::endl;
return 1; return EXIT_FAILURE;
} }
else { else {
std::cout << "Parameterized with Barycentric (SM)!" << std::endl; std::cout << "Parameterized with Barycentric (SM)!" << std::endl;
@ -235,7 +235,7 @@ int main(int, char**)
in >> sm; in >> sm;
if(!in || num_vertices(sm) == 0) { if(!in || num_vertices(sm) == 0) {
std::cerr << "Problem loading the input data" << std::endl; std::cerr << "Problem loading the input data" << std::endl;
return 1; return EXIT_FAILURE;
} }
// halfedge on the longest border // 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); SMP::Error_code status = parameterizer.parameterize(sm, hd, uv_pm, vipm, vpm);
if(status != SMP::OK) { if(status != SMP::OK) {
std::cout << "Encountered a problem: " << status << std::endl; std::cout << "Encountered a problem: " << status << std::endl;
return 1; return EXIT_FAILURE;
} }
else { else {
std::cout << "Parameterized with ARAP (SM)!" << std::endl; std::cout << "Parameterized with ARAP (SM)!" << std::endl;
@ -286,7 +286,7 @@ int main(int, char**)
in >> pm; in >> pm;
if(!in || num_vertices(pm) == 0) { if(!in || num_vertices(pm) == 0) {
std::cerr << "Problem loading the input data" << std::endl; std::cerr << "Problem loading the input data" << std::endl;
return 1; return EXIT_FAILURE;
} }
const char* selection = "data/fandisk.dcm.selection.txt"; const char* selection = "data/fandisk.dcm.selection.txt";
@ -330,7 +330,7 @@ int main(int, char**)
if(status != SMP::OK) { if(status != SMP::OK) {
std::cout << "Encountered a problem: " << status << std::endl; std::cout << "Encountered a problem: " << status << std::endl;
return 1; return EXIT_FAILURE;
} }
else { else {
std::cout << "Parameterized with DCM (SEAM POLY)!" << std::endl; std::cout << "Parameterized with DCM (SEAM POLY)!" << std::endl;
@ -351,7 +351,7 @@ int main(int, char**)
in >> sm; in >> sm;
if(!in || num_vertices(sm) == 0) { if(!in || num_vertices(sm) == 0) {
std::cerr << "Problem loading the input data" << std::endl; std::cerr << "Problem loading the input data" << std::endl;
return 1; return EXIT_FAILURE;
} }
const char* selection = "data/bear.dac.selection.txt"; 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); SMP::Error_code status = parameterizer.parameterize(mesh, hd, uv_pm, vipm, vpm);
if(status != SMP::OK) { if(status != SMP::OK) {
std::cout << "Encountered a problem: " << status << std::endl; std::cout << "Encountered a problem: " << status << std::endl;
return 1; return EXIT_FAILURE;
} }
else { else {
std::cout << "Parameterized with DAC (SEAM SM)!" << std::endl; std::cout << "Parameterized with DAC (SEAM SM)!" << std::endl;
@ -413,7 +413,7 @@ int main(int, char**)
in >> sm; in >> sm;
if(!in || num_vertices(sm) == 0) { if(!in || num_vertices(sm) == 0) {
std::cerr << "Problem loading the input data" << std::endl; std::cerr << "Problem loading the input data" << std::endl;
return 1; return EXIT_FAILURE;
} }
const char* cone_filename = "data/fandisk.orbifold.selection.txt"; 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); SMP::Error_code status = parameterizer.parameterize(mesh, hd, cmap, uvmap, vimap);
if(status != SMP::OK) { if(status != SMP::OK) {
std::cout << "Encountered a problem: " << status << std::endl; std::cout << "Encountered a problem: " << status << std::endl;
return 1; return EXIT_FAILURE;
} }
else { else {
std::cout << "Parameterized with Orbifold (SEAM SM)!" << std::endl; std::cout << "Parameterized with Orbifold (SEAM SM)!" << std::endl;
@ -481,5 +481,5 @@ int main(int, char**)
std::cout << "Done!" << std::endl; std::cout << "Done!" << std::endl;
return 0; return EXIT_SUCCESS;
} }

View File

@ -847,7 +847,8 @@ private:
{ {
typedef std::pair<Input_vertex_descriptor, vertex_descriptor> Vertex_pair; typedef std::pair<Input_vertex_descriptor, vertex_descriptor> Vertex_pair;
std::vector<Vertex_pair> v2v; std::vector<Vertex_pair> 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 // copy input vertices to keep correspondence
BOOST_FOREACH(const Vertex_pair& vp, v2v) BOOST_FOREACH(const Vertex_pair& vp, v2v)