Add a function generic_extrude_mesh() that takes up to 2 functors instead of a direction and a distance.

This commit is contained in:
Maxime Gimeno 2018-05-22 15:57:26 +02:00
parent 41d3c05f7f
commit 4efef4e15b
2 changed files with 164 additions and 40 deletions

View File

@ -22,7 +22,10 @@
#ifndef CGAL_POLYGON_MESH_PROCESSING_EXTRUDE_H #ifndef CGAL_POLYGON_MESH_PROCESSING_EXTRUDE_H
#define 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/license/Polygon_mesh_processing/meshing_hole_filling.h>
#include <CGAL/Polygon_mesh_processing/orientation.h> #include <CGAL/Polygon_mesh_processing/orientation.h>
#include <CGAL/boost/graph/named_params_helper.h> #include <CGAL/boost/graph/named_params_helper.h>
#include <CGAL/boost/graph/named_function_params.h> #include <CGAL/boost/graph/named_function_params.h>
@ -34,36 +37,46 @@ namespace CGAL {
namespace Polygon_mesh_processing { namespace Polygon_mesh_processing {
namespace internal{ namespace internal{
template<typename PMAP> template<typename PMAP, typename Vector>
struct ConstDistTranslation{ struct ConstDistTranslation{
ConstDistTranslation(PMAP map) ConstDistTranslation(PMAP map, const Vector& dir, const double d)
:map(map){} :map(map), dir(dir), d(d){}
template<typename VertexDescriptor, class Vector> template<typename VertexDescriptor>
void operator()(const VertexDescriptor vd, const Vector& dir, const double d) void operator()(const VertexDescriptor vd)
{ {
typename boost::property_traits<PMAP>::value_type p = get(map, vd) + d*dir; typename boost::property_traits<PMAP>::value_type p = get(map, vd) + d*dir;
put(map, vd, p); put(map, vd, p);
} }
PMAP map; PMAP map;
Vector dir;
double d;
};
struct IdentityFunctor
{
template<typename T>
void operator()(const T&){}
}; };
}//end internal }//end internal
/** /**
* \ingroup PMP_meshing_grp * \ingroup PMP_meshing_grp
* Extrudes `input` into `output` following the direction given by `dir` and * Extrudes `input` into `output` using `bot` and `top`. It means that
* at a distance `d`. * `input` will be copied twice and transformed once using `bot`, once using `top`,
* and these two copies will be joined with triangle strips.
* @tparam InputMesh a model of the concept `FaceListGraph` * @tparam InputMesh a model of the concept `FaceListGraph`
* @tparam OutputMesh a model of the concept `FaceListGraph` * @tparam OutputMesh a model of the concept `FaceListGraph`
* @tparam NamedParameters1 a sequence of \ref pmp_namedparameters "Named Parameters" for `InputMesh` * @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 NamedParameters2 a sequence of \ref pmp_namedparameters "Named Parameters" for `OutputMesh`
* @tparam BottomFunctor a functor that will apply a transformation to all points of * @tparam BottomFunctor a functor that will apply a transformation to all points of
* `input` in order to create the offsetted part of the extrusion. It must have a function * `input` in order to create the first offsetted part of the extrusion. It must have a function
* `void operator()(boost::graph_traits<OutputMesh>::vertex_descriptor, Vector_3 dir, const FT d)` * `void operator()(boost::graph_traits<OutputMesh>::vertex_descriptor);
* The default is the * @tparam TopFunctor a functor that will apply a transformation to all points of
* translation along `dir` of the constant distance `d`. * `input` in order to create the second offsetted part of the extrusion. It must have a function
* @param input the closed triangulated `InputMesh` to extrude. * `void operator()(boost::graph_traits<OutputMesh>::vertex_descriptor);
* @param input the open triangulated `InputMesh` to extrude.
* @param output the `OutputMesh` containing the result of the extrusion. * @param output the `OutputMesh` containing the result of the extrusion.
* @param np1 an optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below * @param np1 an optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below
* *
@ -85,27 +98,19 @@ struct ConstDistTranslation{
*/ */
template <class InputMesh, template <class InputMesh,
class OutputMesh, class OutputMesh,
class BottomFunctor,
class TopFunctor = internal::IdentityFunctor,
class NamedParameters1, class NamedParameters1,
class NamedParameters2, class NamedParameters2
#ifdef DOXYGEN_RUNNING
class BottomFunctor
#else
class BottomFunctor=internal::ConstDistTranslation<
typename GetVertexPointMap<OutputMesh, NamedParameters2>::type>
#endif
> >
void extrude_mesh(const InputMesh& input, void generic_extrude_mesh(const InputMesh& input,
OutputMesh& output, OutputMesh& output,
#ifdef DOXYGEN_RUNNING BottomFunctor& bot,
Vector_3 dir, TopFunctor& top,
const FT d, const NamedParameters1& np1,
#else const NamedParameters2& np2)
typename GetGeomTraits<OutputMesh, NamedParameters2>::type::Vector_3 dir,
const typename GetGeomTraits<OutputMesh, NamedParameters2>::type::FT d,
#endif
const NamedParameters1& np1,
const NamedParameters2& np2)
{ {
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<InputMesh>::halfedge_descriptor input_halfedge_descriptor;
typedef typename boost::graph_traits<OutputMesh>::vertex_descriptor output_vertex_descriptor; typedef typename boost::graph_traits<OutputMesh>::vertex_descriptor output_vertex_descriptor;
@ -122,32 +127,36 @@ void extrude_mesh(const InputMesh& input,
IVPMap input_vpm = choose_param(get_param(np1, internal_np::vertex_point), IVPMap input_vpm = choose_param(get_param(np1, internal_np::vertex_point),
get_const_property_map(vertex_point, input)); get_const_property_map(vertex_point, input));
boost::unordered_map<input_halfedge_descriptor, output_halfedge_descriptor> offset_h2h; boost::unordered_map<input_halfedge_descriptor, output_halfedge_descriptor> bottom_h2h;
copy_face_graph(input, output, Emptyset_iterator(), copy_face_graph(input, output, Emptyset_iterator(),
std::inserter(offset_h2h, offset_h2h.end()), Emptyset_iterator(), std::inserter(bottom_h2h, bottom_h2h.end()), Emptyset_iterator(),
input_vpm, output_vpm); input_vpm, output_vpm);
BottomFunctor bottom_functor(output_vpm);
// create the offset for the other side // create the offset for the other side
BOOST_FOREACH(output_vertex_descriptor v, vertices(output)) BOOST_FOREACH(output_vertex_descriptor v, vertices(output))
{ {
bottom_functor(v, dir, d); bot(v);
} }
CGAL::Polygon_mesh_processing::reverse_face_orientations(output); CGAL::Polygon_mesh_processing::reverse_face_orientations(output);
// collect border halfedges for the creation of the triangle strip // collect border halfedges for the creation of the triangle strip
boost::unordered_map<input_halfedge_descriptor, output_halfedge_descriptor> h2h; boost::unordered_map<input_vertex_descriptor, output_vertex_descriptor> top_v2v;
copy_face_graph(input, output, CGAL::Emptyset_iterator(), boost::unordered_map<input_halfedge_descriptor, output_halfedge_descriptor> top_h2h;
std::inserter(h2h, h2h.end()), Emptyset_iterator(), 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); input_vpm, output_vpm);
BOOST_FOREACH(input_vertex_descriptor v, vertices(input))
{
top(top_v2v[v]);
}
std::vector<output_halfedge_descriptor> border_hedges; std::vector<output_halfedge_descriptor> border_hedges;
std::vector<output_halfedge_descriptor> offset_border_hedges; std::vector<output_halfedge_descriptor> offset_border_hedges;
BOOST_FOREACH(input_halfedge_descriptor h, halfedges(input)) BOOST_FOREACH(input_halfedge_descriptor h, halfedges(input))
{ {
if( CGAL::is_border(h, input) ) if( CGAL::is_border(h, input) )
{ {
border_hedges.push_back(h2h[h]); border_hedges.push_back(top_h2h[h]);
offset_border_hedges.push_back(offset_h2h[h]); offset_border_hedges.push_back(bottom_h2h[h]);
CGAL_assertion(is_border(border_hedges.back(), output)); CGAL_assertion(is_border(border_hedges.back(), output));
CGAL_assertion(is_border(offset_border_hedges.back(), output)); CGAL_assertion(is_border(offset_border_hedges.back(), output));
} }
@ -222,6 +231,62 @@ void extrude_mesh(const InputMesh& input,
} }
} }
/**
* \ingroup PMP_meshing_grp
* Extrudes `input` into `output` following the direction given by `dir` and
* at a distance `d`.
* @tparam InputMesh a model of the concept `FaceListGraph`
* @tparam OutputMesh a model of the concept `FaceListGraph`
* @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 the open triangulated `InputMesh` to extrude.
* @param output the `OutputMesh` containing the result of the extrusion.
* @param np1 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
*
* * @param np2 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
*/
template <class InputMesh,
class OutputMesh,
class NamedParameters1,
class NamedParameters2>
void extrude_mesh(const InputMesh& input,
OutputMesh& output,
#ifdef DOXYGEN_RUNNING
Vector_3 dir,
const FT d,
#else
typename GetGeomTraits<OutputMesh, NamedParameters2>::type::Vector_3 dir,
const typename GetGeomTraits<OutputMesh, NamedParameters2>::type::FT d,
#endif
const NamedParameters1& np1,
const NamedParameters2& np2)
{
typedef typename GetVertexPointMap < OutputMesh, NamedParameters2>::type VPMap;
VPMap output_vpm = choose_param(get_param(np2, internal_np::vertex_point),
get_property_map(vertex_point, output));
internal::ConstDistTranslation<
typename GetVertexPointMap<OutputMesh, NamedParameters2>::type,
typename GetGeomTraits<OutputMesh, NamedParameters2>::type::Vector_3> bot(output_vpm,
dir, d);
internal::IdentityFunctor top;
generic_extrude_mesh(input, output, bot,top, np1, np2);
}
//convenience overload //convenience overload
template <class InputMesh, template <class InputMesh,
class OutputMesh, class OutputMesh,
@ -236,5 +301,30 @@ void extrude_mesh(const InputMesh& input,
parameters::all_default()); parameters::all_default());
} }
template <class InputMesh,
class OutputMesh,
class BottomFunctor,
class TopFunctor>
void generic_extrude_mesh(const InputMesh& input,
OutputMesh& output,
BottomFunctor& bot,
TopFunctor& top)
{
generic_extrude_mesh(input, output, bot, top,
parameters::all_default(), parameters::all_default());
}
template <class InputMesh,
class OutputMesh,
class BottomFunctor>
void generic_extrude_mesh(const InputMesh& input,
OutputMesh& output,
BottomFunctor& bot)
{
internal::IdentityFunctor top;
generic_extrude_mesh(input, output, bot, top,
parameters::all_default(), parameters::all_default());
}
}} //end CGAL::PMP }} //end CGAL::PMP
#endif //CGAL_POLYGON_MESH_PROCESSING_EXTRUDE_H #endif //CGAL_POLYGON_MESH_PROCESSING_EXTRUDE_H

View File

@ -7,7 +7,32 @@
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef CGAL::Surface_mesh<Kernel::Point_3> SMesh; typedef CGAL::Surface_mesh<Kernel::Point_3> SMesh;
template<typename MAP>
struct Bot
{
Bot(MAP map):map(map){}
template<typename VD>
void operator()(VD vd)
{
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>
void operator()(VD vd)
{
put(map, vd, get(map, vd)+Kernel::Vector_3(0.0,2.0,1.0));
}
MAP map;
};
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
@ -25,7 +50,16 @@ int main(int argc, char* argv[])
CGAL::Polygon_mesh_processing::extrude_mesh(in, out, Kernel::Vector_3(0.0, 0.0, -1.0), 1.0); CGAL::Polygon_mesh_processing::extrude_mesh(in, out, Kernel::Vector_3(0.0, 0.0, -1.0), 1.0);
std::ofstream extruded_off("extruded.off"); std::ofstream extruded_off("extruded.off");
extruded_off << out; extruded_off << out;
extruded_off.close(); extruded_off.close();
out.clear();
typedef typename boost::property_map<SMesh, 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::generic_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; std::cerr << "All done." << std::endl;
return 0; return 0;