document corefine_and_compute_boolean_operations()

This commit is contained in:
Sébastien Loriot 2018-05-28 17:07:05 +02:00
parent 67ec602795
commit f29d8339fa
7 changed files with 175 additions and 8 deletions

View File

@ -42,6 +42,8 @@ Release date: September 2018
(that replace the `bool` parameter in `corefine()`) that enables to check for
self-intersections faces involved in the intersection before trying to corefine the
input meshes.
- Document the function `corefine_and_compute_boolean_operations()` that can be used to
compute the result of several Boolean operations between 2 volumes at the same time.
Release 4.12
------------

View File

@ -145,6 +145,7 @@ and provides a list of the parameters that are used in this package.
- `CGAL::Polygon_mesh_processing::corefine_and_compute_union()`
- `CGAL::Polygon_mesh_processing::corefine_and_compute_difference()`
- `CGAL::Polygon_mesh_processing::corefine_and_compute_intersection()`
- `CGAL::Polygon_mesh_processing::corefine_and_compute_boolean_operations()`
- `CGAL::Polygon_mesh_processing::corefine()`
- `CGAL::Polygon_mesh_processing::surface_intersection()`
- `CGAL::Polygon_mesh_processing::does_bound_a_volume()`
@ -178,6 +179,4 @@ and provides a list of the parameters that are used in this package.
- `CGAL::Polygon_mesh_processing::border_halfedges()`
- `CGAL::Polygon_mesh_processing::transform()`
\todo add `clip_triangle_mesh()` using the code of `Polyhedron_place_clipping.h` and `PMP::corefine()`
\todo fix and restore remove_degenerate_faces in the user and the reference manual
*/

View File

@ -215,9 +215,10 @@ Considering two triangulated surface meshes, each bounding
a volume, the functions `CGAL::Polygon_mesh_processing::corefine_and_compute_union()`,
`CGAL::Polygon_mesh_processing::corefine_and_compute_intersection()` and
`CGAL::Polygon_mesh_processing::corefine_and_compute_difference()` respectively compute the union,
the intersection and the difference of the two volumes.
Note that there is no restriction on the topology of the input volumes.
the intersection and the difference of the two volumes. If several Boolean operations must be
computed at the same type, the function `corefine_and_compute_boolean_operations()` should be used.
There is no restriction on the topology of the input volumes.
However, there are some requirements on the input to guarantee that
the operation is possible. First, the input meshes must not self-intersect.
Second, the operation is possible only if the output

View File

@ -18,6 +18,7 @@
\example Poisson_surface_reconstruction_3/poisson_reconstruction_example.cpp
\example Polygon_mesh_processing/corefinement_difference_remeshed.cpp
\example Polygon_mesh_processing/corefinement_mesh_union.cpp
\example Polygon_mesh_processing/corefinement_mesh_union_and_intersection.cpp
\example Polygon_mesh_processing/corefinement_consecutive_bool_op.cpp
\example Polygon_mesh_processing/detect_features_example.cpp
*/

View File

@ -97,6 +97,7 @@ create_single_source_cgal_program( "corefinement_SM.cpp")
create_single_source_cgal_program( "corefinement_consecutive_bool_op.cpp" )
create_single_source_cgal_program( "corefinement_difference_remeshed.cpp" )
create_single_source_cgal_program( "corefinement_mesh_union.cpp" )
create_single_source_cgal_program( "corefinement_mesh_union_and_intersection.cpp" )
create_single_source_cgal_program( "corefinement_mesh_union_with_attributes.cpp" )
create_single_source_cgal_program( "corefinement_polyhedron_union.cpp" )
create_single_source_cgal_program( "random_perturbation_SM_example.cpp" )

View File

@ -0,0 +1,73 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/corefinement.h>
#include <fstream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Surface_mesh<K::Point_3> Mesh;
namespace PMP = CGAL::Polygon_mesh_processing;
namespace params = CGAL::Polygon_mesh_processing::parameters;
int main(int argc, char* argv[])
{
const char* filename1 = (argc > 1) ? argv[1] : "data/blobby.off";
const char* filename2 = (argc > 2) ? argv[2] : "data/eight.off";
std::ifstream input(filename1);
Mesh mesh1, mesh2;
if (!input || !(input >> mesh1))
{
std::cerr << "First mesh is not a valid off file." << std::endl;
return 1;
}
input.close();
input.open(filename2);
if (!input || !(input >> mesh2))
{
std::cerr << "Second mesh is not a valid off file." << std::endl;
return 1;
}
Mesh out_union, out_intersection;
CGAL::cpp11::array<boost::optional<Mesh*>, 4> output;
output[PMP::Corefinement::UNION] = &out_union;
output[PMP::Corefinement::INTERSECTION] = &out_intersection;
// for the example, we explicit the named parameters, this is identical to
// PMP::corefine_and_compute_boolean_operations(mesh1, mesh2, output)
CGAL::cpp11::array<bool, 4> res =
PMP::corefine_and_compute_boolean_operations(
mesh1, mesh2,
output,
params::all_default(), // mesh1 named parameters
params::all_default(), // mesh2 named parameters
CGAL::cpp11::make_tuple(
params::vertex_point_map(get(boost::vertex_point, out_union)), // named parameters for out_union
params::vertex_point_map(get(boost::vertex_point, out_intersection)), // named parameters for out_intersection
params::all_default(), // named parameters for mesh1-mesh2 not used
params::all_default() )// named parameters for mesh2-mesh1 not used)
);
if (res[PMP::Corefinement::UNION])
{
std::cout << "Union was successfully computed\n";
std::ofstream output("union.off");
output << out_union;
}
else
std::cout << "Union could not be computed\n";
if (res[PMP::Corefinement::INTERSECTION])
{
std::cout << "Intersection was successfully computed\n";
std::ofstream output("intersection.off");
output << out_intersection;
}
else
std::cout << "Intersection could not be computed\n";
return 1;
}

View File

@ -142,8 +142,15 @@ namespace Corefinement
*/
template <class TriangleMesh>
struct Default_new_face_visitor;
}
#ifdef DOXYGEN_RUNNING
/** \ingroup PMP_corefinement_grp
* Integer identifiers to refer to a particular Boolean operation in the function `corefine_and_compute_boolean_operations()`.
*/
enum Boolean_operation_type {UNION = 0, INTERSECTION=1,
TM1_MINUS_TM2=2, TM2_MINUS_TM1=3, NONE };
#endif
}
/** \ingroup PMP_corefinement_grp
*
@ -241,6 +248,7 @@ bool does_bound_a_volume(const TriangleMesh& tm)
{
return does_bound_a_volume(tm, parameters::all_default());
}
/// \endcond
#define CGAL_COREF_SET_OUTPUT_EDGE_MARK_MAP(I) \
typedef typename boost::lookup_named_param_def < \
@ -254,8 +262,90 @@ bool does_bound_a_volume(const TriangleMesh& tm)
/**
\todo document me
*/
* \ingroup PMP_corefinement_grp
* \link coref_def_subsec corefines \endlink `tm1` and `tm2` and for each triangle mesh `tm_out` passed
* as an optional in `output` different from `boost::none`, the triangulated surface mesh
* \link coref_def_subsec bounding \endlink the result of a particular Boolean operation
* between the volumes bounded by `tm1` and `tm2` will be put in the corresponding triangle mesh.
* The position of the meshes in the array `output` are specific to the Boolean operation to compute
* and `Corefinement::Boolean_operation_type` encodes and describes the ordering. Constructing the default array
* means that no Boolean operation will be done. Overwritting a default value will trigger the corresponding
* operation. In such a case, the address to a valid surface mesh must be provided.
* The optional named parameters for all output meshes are provided as a `tuple` and follow the same
* order as the array `output`. A call to `corefine_and_compute_boolean_operations()` with optional
* named parameters passed for output meshes should be done using `make_tuple()` as the types of
* named parameters is unspecified.
*
* If `tm1` and/or `tm2` are one of the output surface meshes, they will be updated to
* contain the output (in-place operation), in any other case, the corresponding result will
* be inserted into the mesh without clearing it first.
* \pre \link CGAL::Polygon_mesh_processing::does_self_intersect() `!CGAL::Polygon_mesh_processing::does_self_intersect(tm1)` \endlink
* \pre \link CGAL::Polygon_mesh_processing::does_self_intersect() `!CGAL::Polygon_mesh_processing::does_self_intersect(tm2)` \endlink
* \pre \link CGAL::Polygon_mesh_processing::does_bound_a_volume() `CGAL::Polygon_mesh_processing::does_bound_a_volume(tm1)` \endlink
* \pre \link CGAL::Polygon_mesh_processing::does_bound_a_volume() `CGAL::Polygon_mesh_processing::does_bound_a_volume(tm2)` \endlink
*
* @tparam TriangleMesh a model of `MutableFaceGraph`, `HalfedgeListGraph` and `FaceListGraph`.
* If `TriangleMesh` has an internal property map for `CGAL::face_index_t`,
* as a named parameter, then it must be initialized.
*
* @tparam NamedParameters1 a sequence of \ref pmp_namedparameters "Named Parameters"
* @tparam NamedParameters2 a sequence of \ref pmp_namedparameters "Named Parameters"
* @tparam NamedParametersOut0 a sequence of \ref pmp_namedparameters "Named Parameters" for computing the union of the volumes bounded by `tm1` and `tm2`
* @tparam NamedParametersOut1 a sequence of \ref pmp_namedparameters "Named Parameters" for computing the intersection of the volumes bounded by `tm1` and `tm2`
* @tparam NamedParametersOut2 a sequence of \ref pmp_namedparameters "Named Parameters" for computing the difference of the volumes bounded by `tm1` and `tm2`
* @tparam NamedParametersOut3 a sequence of \ref pmp_namedparameters "Named Parameters" for computing the difference of the volumes bounded by `tm2` and `tm1`
*
* @param tm1 first input triangulated surface mesh
* @param tm2 second input triangulated surface mesh
* @param output an array of output surface meshes
* @param np1 optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below
* @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 `tm1` (`tm2`).
* If this parameter is omitted, an internal property map for
* `CGAL::vertex_point_t` should be available in `TriangleMesh`
* \cgalParamEnd
* \cgalParamBegin{edge_is_constrained_map} a property map containing the
* constrained-or-not status of each edge of `tm1` (`tm2`).
* \cgalParamEnd
* \cgalParamBegin{face_index_map} a property map containing the index of each face of `tm1` (`tm2`).
* Note that if the property map is writable, the indices of the faces
* of `tm1` and `tm2` will be set after the corefinement is done.
* \cgalParamEnd
* \cgalParamBegin{new_face_visitor} a class model of `PMPCorefinementNewFaceVisitor`
* that is used to track the creation of new faces (`np1` only)
* \cgalParamEnd
* \cgalParamBegin{throw_on_self_intersection} if `true`, for each input triangle mesh,
* the set of triangles closed to the intersection of `tm1` and `tm2` will be
* checked for self-intersection and `CGAL::Polygon_mesh_processing::Corefinement::Self_intersection_exception`
* will be thrown if at least one is found (`np1` only).
* \cgalParamEnd
* \cgalNamedParamsEnd
*
* @param nps_out tuple of optional sequences of \ref pmp_namedparameters "Named Parameters" each among the ones listed below
* (`tm_out` being use to refer the output surface mesh in `output` corresponding to a given named parameter sequence)
*
* \cgalNamedParamsBegin
* \cgalParamBegin{vertex_point_map}
* the property map with the points associated to the vertices of `tm_out`.
* If this parameter is omitted, an internal property map for
* `CGAL::vertex_point_t` should be available in `TriangleMesh`
* \cgalParamEnd
* \cgalParamBegin{edge_is_constrained_map} a property map containing the
* constrained-or-not status of each edge of `tm_out`. An edge of `tm_out` is constrained
* if it is on the intersection of `tm1` and `tm2`, or if the edge corresponds to a
* constrained edge in `tm1` or `tm2`.
* \cgalParamEnd
* \cgalNamedParamsEnd
*
* @return an array filled as follow: for each operation computed, the position in the array
* will contains `true` iff the output surface mesh is manifold, and it is put in the surface mesh
* at the same position in `output`. Note that if a output surface mesh was also
* an input mesh but the output operation was generating a non-manifold mesh, the surface mesh
* will only be corefined.
*/
template <class TriangleMesh,
class NamedParameters1,
class NamedParameters2,
@ -462,7 +552,7 @@ corefine_and_compute_boolean_operations(
#undef CGAL_COREF_SET_OUTPUT_VERTEX_POINT_MAP
#undef CGAL_COREF_SET_OUTPUT_EDGE_MARK_MAP
/// \endcond
/**
* \ingroup PMP_corefinement_grp