diff --git a/BGL/include/CGAL/boost/graph/copy_face_graph.h b/BGL/include/CGAL/boost/graph/copy_face_graph.h index 19755ac8e46..a557aa9a73b 100644 --- a/BGL/include/CGAL/boost/graph/copy_face_graph.h +++ b/BGL/include/CGAL/boost/graph/copy_face_graph.h @@ -25,7 +25,6 @@ #include #include #include -#include namespace CGAL { @@ -212,36 +211,6 @@ void copy_face_graph_impl(const SourceMesh& sm, TargetMesh& tm, } } // end of namespace internal -namespace impl -{ -template -struct Output_iterator_functor -{ - typedef typename boost::property_traits::key_type input_t; - typedef typename boost::property_traits::value_type output_t; - PMAP map; - Output_iterator_functor(PMAP map) - :map(map) - { - } - void operator()(const typename std::pair& pair) - { - put(map, pair.first, pair.second); - } - -}; - -template -boost::function_output_iterator > make_functor(PMAP map) -{ - return boost::make_function_output_iterator(Output_iterator_functor(map)); -} - -inline Emptyset_iterator make_functor(const internal_np::Param_not_found&) -{ - return Emptyset_iterator(); -} -}//end of impl /*! \ingroup PkgBGLHelperFct diff --git a/BGL/include/CGAL/boost/graph/internal/helpers.h b/BGL/include/CGAL/boost/graph/internal/helpers.h index 98d3c7ec28b..262d0d36abc 100644 --- a/BGL/include/CGAL/boost/graph/internal/helpers.h +++ b/BGL/include/CGAL/boost/graph/internal/helpers.h @@ -13,7 +13,11 @@ #include #include +#include +#include #include +#include +#include namespace CGAL { @@ -200,6 +204,38 @@ adjust_incoming_halfedge(typename boost::graph_traits::vertex_descriptor } // internal + +namespace impl +{ + template + struct Output_iterator_functor + { + typedef typename boost::property_traits::key_type input_t; + typedef typename boost::property_traits::value_type output_t; + PMAP map; + Output_iterator_functor(PMAP map) + :map(map) + { + } + void operator()(const typename std::pair& pair) + { + put(map, pair.first, pair.second); + } + + }; + + template + boost::function_output_iterator > make_functor(PMAP map) + { + return boost::make_function_output_iterator(Output_iterator_functor(map)); + } + + inline Emptyset_iterator make_functor(const internal_np::Param_not_found&) + { + return Emptyset_iterator(); + } +}//end of impl + } // CGAL diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index a1fe60c5f75..c1f07f31606 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -32,6 +32,8 @@ CGAL_add_named_parameter(face_partition_id_t, face_partition_id, face_partition_ 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(point_to_vertex_output_iterator_t, point_to_vertex_output_iterator, point_to_vertex_output_iterator) +CGAL_add_named_parameter(polygon_to_face_output_iterator_t, polygon_to_face_output_iterator, polygon_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) @@ -198,6 +200,11 @@ CGAL_add_named_parameter(cell_selector_t, cell_selector, cell_selector) CGAL_add_named_parameter(facet_is_constrained_t, facet_is_constrained, facet_is_constrained_map) CGAL_add_named_parameter(smooth_constrained_edges_t, smooth_constrained_edges, smooth_constrained_edges) +// MDS_3 parameters +CGAL_add_named_parameter(surface_facets_t, surface_facets, surface_facets) +CGAL_add_named_parameter(all_vertices_t, all_vertices, all_vertices) +CGAL_add_named_parameter(all_cells_t, all_cells, all_cells) + // output parameters CGAL_add_named_parameter(face_proxy_map_t, face_proxy_map, face_proxy_map) CGAL_add_named_parameter(proxies_t, proxies, proxies) diff --git a/Documentation/doc/Documentation/packages.txt b/Documentation/doc/Documentation/packages.txt index 1ce8cb797a6..efc86338dd8 100644 --- a/Documentation/doc/Documentation/packages.txt +++ b/Documentation/doc/Documentation/packages.txt @@ -90,6 +90,7 @@ \package_listing{Mesh_2} \package_listing{Surface_mesher} \package_listing{Skin_surface_3} +\package_listing{MDS_3} \package_listing{Mesh_3} \package_listing{Tetrahedral_remeshing} \package_listing{Periodic_3_mesh_3} diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 216493431f7..b94ab2490ef 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -1,6 +1,18 @@ Release History =============== +[Release 5.4](https://github.com/CGAL/cgal/releases/tag/v5.4) +----------- + +Release date: + +### [Mesh Data Structure 3](https://doc.cgal.org/5.4/Manual/packages.html#PkgMDS3) (new package) + +- This new package wraps all the existing code that deals with a +` MeshComplex_3InTriangulation_3`, and makes the data structure independant +from the tetrahedral mesh generation package. + + [Release 5.3](https://github.com/CGAL/cgal/releases/tag/v5.3) ----------- diff --git a/Installation/include/CGAL/MDS_3/Mesh_complex_3_in_triangulation_3_fwd.h b/Installation/include/CGAL/MDS_3/Mesh_complex_3_in_triangulation_3_fwd.h new file mode 100644 index 00000000000..f21ddcb751b --- /dev/null +++ b/Installation/include/CGAL/MDS_3/Mesh_complex_3_in_triangulation_3_fwd.h @@ -0,0 +1,52 @@ +// Copyright (C) 2020 GeometryFactory Sarl +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// + +#ifndef CGAL_MDS_3_MESH_COMPLEX_3_IN_TRIANGULATION_3_FWD_H +#define CGAL_MDS_3_MESH_COMPLEX_3_IN_TRIANGULATION_3_FWD_H + +/// \file Mesh_complex_3_in_triangulation_3_fwd.h +/// Forward declarations of the MDS_3 package. + +#ifndef DOXYGEN_RUNNING +namespace CGAL { + +// fwdS for the public interface +template +class Mesh_complex_3_in_triangulation_3; + +namespace IO { + template + void output_to_medit(std::ostream& os, + const C3T3& c3t3, + bool rebind = false, + bool show_patches = false +#ifndef DOXYGEN_RUNNING + , bool all_vertices = true + , bool all_cells = false +#endif + ); +} + +namespace MDS_3 { + + template + bool build_triangulation_from_file(std::istream& is, + Tr& tr, + bool verbose = false, + bool replace_domain_0 = false); + +} // MDS_3 +} // CGAL +#endif + +#endif /* CGAL_MDS_3_MESH_COMPLEX_3_IN_TRIANGULATION_3_FWD_H */ + + diff --git a/Installation/include/CGAL/license/MDS_3.h b/Installation/include/CGAL/license/MDS_3.h new file mode 100644 index 00000000000..e3f38693334 --- /dev/null +++ b/Installation/include/CGAL/license/MDS_3.h @@ -0,0 +1,54 @@ +// Copyright (c) 2016 GeometryFactory SARL (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Andreas Fabri +// +// Warning: this file is generated, see include/CGAL/licence/README.md + +#ifndef CGAL_LICENSE_MDS_3_H +#define CGAL_LICENSE_MDS_3_H + +#include +#include + +#ifdef CGAL_MDS_3_COMMERCIAL_LICENSE + +# if CGAL_MDS_3_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE + +# if defined(CGAL_LICENSE_WARNING) + + CGAL_pragma_warning("Your commercial license for CGAL does not cover " + "this release of the 3D Mesh Data Structure package.") +# endif + +# ifdef CGAL_LICENSE_ERROR +# error "Your commercial license for CGAL does not cover this release \ + of the 3D Mesh Data Structure package. \ + You get this error, as you defined CGAL_LICENSE_ERROR." +# endif // CGAL_LICENSE_ERROR + +# endif // CGAL_MDS_3_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE + +#else // no CGAL_MDS_3_COMMERCIAL_LICENSE + +# if defined(CGAL_LICENSE_WARNING) + CGAL_pragma_warning("\nThe macro CGAL_MDS_3_COMMERCIAL_LICENSE is not defined." + "\nYou use the CGAL 3D Mesh Data Structure package under " + "the terms of the GPLv3+.") +# endif // CGAL_LICENSE_WARNING + +# ifdef CGAL_LICENSE_ERROR +# error "The macro CGAL_MDS_3_COMMERCIAL_LICENSE is not defined.\ + You use the CGAL 3D Mesh Data Structure package under the terms of \ + the GPLv3+. You get this error, as you defined CGAL_LICENSE_ERROR." +# endif // CGAL_LICENSE_ERROR + +#endif // no CGAL_MDS_3_COMMERCIAL_LICENSE + +#endif // CGAL_LICENSE_MDS_3_H diff --git a/Installation/include/CGAL/license/Orthtree.h b/Installation/include/CGAL/license/Orthtree.h index 9437a3ed4a4..8225e047ec3 100644 --- a/Installation/include/CGAL/license/Orthtree.h +++ b/Installation/include/CGAL/license/Orthtree.h @@ -24,12 +24,12 @@ # if defined(CGAL_LICENSE_WARNING) CGAL_pragma_warning("Your commercial license for CGAL does not cover " - "this release of the package.") + "this release of the Quadtrees, Octrees, and Orthrees package.") # endif # ifdef CGAL_LICENSE_ERROR # error "Your commercial license for CGAL does not cover this release \ - of the package. \ + of the Quadtrees, Octrees, and Orthrees package. \ You get this error, as you defined CGAL_LICENSE_ERROR." # endif // CGAL_LICENSE_ERROR @@ -39,13 +39,13 @@ # if defined(CGAL_LICENSE_WARNING) CGAL_pragma_warning("\nThe macro CGAL_ORTHTREE_COMMERCIAL_LICENSE is not defined." - "\nYou use the CGAL package under " + "\nYou use the CGAL Quadtrees, Octrees, and Orthrees package under " "the terms of the GPLv3+.") # endif // CGAL_LICENSE_WARNING # ifdef CGAL_LICENSE_ERROR # error "The macro CGAL_ORTHTREE_COMMERCIAL_LICENSE is not defined.\ - You use the CGAL package under the terms of \ + You use the CGAL Quadtrees, Octrees, and Orthrees package under the terms of \ the GPLv3+. You get this error, as you defined CGAL_LICENSE_ERROR." # endif // CGAL_LICENSE_ERROR diff --git a/Installation/include/CGAL/license/Triangulation_on_sphere_2.h b/Installation/include/CGAL/license/Triangulation_on_sphere_2.h index 5ec1bf7e76d..6e3447d7ae7 100644 --- a/Installation/include/CGAL/license/Triangulation_on_sphere_2.h +++ b/Installation/include/CGAL/license/Triangulation_on_sphere_2.h @@ -24,12 +24,12 @@ # if defined(CGAL_LICENSE_WARNING) CGAL_pragma_warning("Your commercial license for CGAL does not cover " - "this release of the 2D Triangulations on Sphere package.") + "this release of the 2D Triangulation on Sphere package.") # endif # ifdef CGAL_LICENSE_ERROR # error "Your commercial license for CGAL does not cover this release \ - of the 2D Triangulations on Sphere package. \ + of the 2D Triangulation on Sphere package. \ You get this error, as you defined CGAL_LICENSE_ERROR." # endif // CGAL_LICENSE_ERROR @@ -39,13 +39,13 @@ # if defined(CGAL_LICENSE_WARNING) CGAL_pragma_warning("\nThe macro CGAL_TRIANGULATION_ON_SPHERE_2_COMMERCIAL_LICENSE is not defined." - "\nYou use the CGAL 2D Triangulations on Sphere package under " + "\nYou use the CGAL 2D Triangulation on Sphere package under " "the terms of the GPLv3+.") # endif // CGAL_LICENSE_WARNING # ifdef CGAL_LICENSE_ERROR # error "The macro CGAL_TRIANGULATION_ON_SPHERE_2_COMMERCIAL_LICENSE is not defined.\ - You use the CGAL 2D Triangulations on Sphere package under the terms of \ + You use the CGAL 2D Triangulation on Sphere package under the terms of \ the GPLv3+. You get this error, as you defined CGAL_LICENSE_ERROR." # endif // CGAL_LICENSE_ERROR diff --git a/Installation/include/CGAL/license/gpl_package_list.txt b/Installation/include/CGAL/license/gpl_package_list.txt index 787702b4163..644258ed99c 100644 --- a/Installation/include/CGAL/license/gpl_package_list.txt +++ b/Installation/include/CGAL/license/gpl_package_list.txt @@ -27,6 +27,7 @@ Jet_fitting_3 Estimation of Local Differential Properties of Point-Sampled Surfa Matrix_search Monotone and Sorted Matrix Search Mesh_2 2D Conforming Triangulations and Meshes Mesh_3 3D Mesh Generation +MDS_3 3D Mesh Data Structure Minkowski_sum_2 2D Minkowski Sums Minkowski_sum_3 3D Minkowski Sum of Polyhedra Nef_2 2D Boolean Operations on Nef Polygons diff --git a/Mesh_3/doc/Mesh_3/Concepts/MeshComplexWithFeatures_3InTriangulation_3.h b/MDS_3/doc/MDS_3/Concepts/MeshComplexWithFeatures_3InTriangulation_3.h similarity index 99% rename from Mesh_3/doc/Mesh_3/Concepts/MeshComplexWithFeatures_3InTriangulation_3.h rename to MDS_3/doc/MDS_3/Concepts/MeshComplexWithFeatures_3InTriangulation_3.h index 50b2751ac74..9bfd0e07b60 100644 --- a/Mesh_3/doc/Mesh_3/Concepts/MeshComplexWithFeatures_3InTriangulation_3.h +++ b/MDS_3/doc/MDS_3/Concepts/MeshComplexWithFeatures_3InTriangulation_3.h @@ -1,5 +1,5 @@ /*! -\ingroup PkgMesh3Concepts +\ingroup PkgMDS3Concepts \cgalConcept The concept `MeshComplexWithFeatures_3InTriangulation_3` describes a data structure diff --git a/Mesh_3/doc/Mesh_3/Concepts/MeshComplex_3InTriangulation_3.h b/MDS_3/doc/MDS_3/Concepts/MeshComplex_3InTriangulation_3.h similarity index 99% rename from Mesh_3/doc/Mesh_3/Concepts/MeshComplex_3InTriangulation_3.h rename to MDS_3/doc/MDS_3/Concepts/MeshComplex_3InTriangulation_3.h index 3d3e28c7e2f..993d9bd1a34 100644 --- a/Mesh_3/doc/Mesh_3/Concepts/MeshComplex_3InTriangulation_3.h +++ b/MDS_3/doc/MDS_3/Concepts/MeshComplex_3InTriangulation_3.h @@ -1,5 +1,5 @@ /*! -\ingroup PkgMesh3Concepts +\ingroup PkgMDS3Concepts \cgalConcept The concept `MeshComplex_3InTriangulation_3` describes a data structure diff --git a/MDS_3/doc/MDS_3/Doxyfile.in b/MDS_3/doc/MDS_3/Doxyfile.in new file mode 100644 index 00000000000..c7b9e9a3e10 --- /dev/null +++ b/MDS_3/doc/MDS_3/Doxyfile.in @@ -0,0 +1,21 @@ +@INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS} + +PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - 3D Mesh Data Structures" + +#custom options +EXTRACT_ALL = false +HIDE_UNDOC_CLASSES = true +HIDE_UNDOC_MEMBERS = true +WARN_IF_UNDOCUMENTED = false + +# macros to be used inside the code +#ALIASES += "cgalDescribePolylineType=A polyline is defined as a sequence of points, each pair of contiguous points defines a segment of the polyline. If the first and last points of the polyline are identical, the polyline is closed." + +INPUT += ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/IO + +EXCLUDE = ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/internal/MDS_3 + +HTML_EXTRA_FILES = ${CGAL_PACKAGE_DOC_DIR}/fig/c3t3.jpg \ +# ${CGAL_PACKAGE_DOC_DIR}/fig/no-protection-complex.png + +EXAMPLE_PATH += ${CGAL_PACKAGE_INCLUDE_DIR} diff --git a/MDS_3/doc/MDS_3/MDS_3.txt b/MDS_3/doc/MDS_3/MDS_3.txt new file mode 100644 index 00000000000..c43160517c5 --- /dev/null +++ b/MDS_3/doc/MDS_3/MDS_3.txt @@ -0,0 +1,90 @@ +namespace CGAL { +/*! + +\mainpage User Manual +\anchor Chapter_3D_Mesh_Data_Structures +\anchor userchaptermds3 +\authors Pierre Alliez, Clément Jamin, Laurent Rineau, Stéphane Tayeb, Jane Tournois, Mariette Yvinec +\cgalAutoToc + +\cgalFigureBegin{figuremultilabel_mesher,multilabel_mesher.jpg} +Cut-view of a multi-domain 3D mesh generated from a segmented image. +\cgalFigureEnd + +\section MDS_3_section_intro Introduction + +This package is devoted to the representation of 3-Dimensional Mesh Data Structures. + +A 3D mesh is a discretization of a given bounded subset of the 3D space, +that holds all geometric and combinatorial data to construct a valid +and consistent discretization. +In this chapter, we describe higher-level data structures available +for the description of such meshes. + +\section MDS_3_section_c3t3 Mesh Complex + +A 3D simplicial complex is composed of points, line segments, polygons, +polyhedral, and the combinatorial description of their n-dimension counterparts +(namely vertices, edges, faces and cells). +CGAL provides 3D triangulations, that describe +both the geometry and connectivity of a 3D simplicial complex made +of triangles, implemented in the +the \ref PkgTriangulation3 and \ref PkgTDS3 packages. + +We introduce the concept of \em mesh \em complex, that encodes extra information +on top of a 3D triangulation to represent a complete simplicial +complex. A mesh complex describes four sub-complexes +of simplices +of the support 3D triangulation per dimension from 0 to 3 : +- corner vertices in 0D, +- feature edges in 1D, +- surface facets in 2D, +- domain cells in 3D. + +The concept `MeshComplex_3InTriangulation_3` is a data structure devised to +represent the three dimensional complexes embedded in a `Triangulation_3`. + +\todo add figure + + +\section MDS_3_section_examples Examples + +\subsection TetSoupExample From Tetrahedron Soup to `Triangulation_3` + +In the example first example of this section, we build a random +`Delaunay_triangulation_3` and use it to build a consistent though +connectivity-free tetrahedron soup. +The tetrahedron soup is then put back together in a +`CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3` before +being set as the reference triangulation of a `Mesh_complex_3_in_triangulation_3`. + +\cgalExample{MDS_3/tetrahedron_soup_to_c3t3_example.cpp} + + +\subsection IOExample Input/Output Example + +The example below illustrates how to use the IO functions +for reading and writing a triangulation with the `Medit` file format. + +\cgalExample{MDS_3/c3t3_example.cpp} + + +\subsection MoreExamples More Examples in other packages + +The `Mesh_complex_3_in_triangulation_3` is widely used in the \ref PkgMesh3 package. +Numerous more usage examples can be found in its \ref Mesh_3_section_examples section. + +The package \ref PkgTetrahedralRemeshing also makes use of the +`Mesh_complex_3_in_triangulation_3`, since it serves as a post-processing for +tetrahedral mesh generation. Some examples can be found in the \ref secTetRemeshingExamples +section. + + +\section MDS_3History Implementation History + +The code of the `MeshComplex_3InTriangulation_3` and its variants was initially part of the package `Mesh_3`. +With the meshing and remeshing processes becoming more versatile, it was moved to its own package in the +release 5.4 of \cgal. + +*/ +} /* namespace CGAL */ diff --git a/MDS_3/doc/MDS_3/PackageDescription.txt b/MDS_3/doc/MDS_3/PackageDescription.txt new file mode 100644 index 00000000000..7afe36645fe --- /dev/null +++ b/MDS_3/doc/MDS_3/PackageDescription.txt @@ -0,0 +1,73 @@ +/// \defgroup PkgMDS3Ref 3D Mesh Data Structures Reference + +/// \defgroup PkgMDS3Concepts Concepts +/// \ingroup PkgMDS3Ref +/// The main concepts of this package. + +/// \defgroup PkgMDS3Classes Classes +/// \ingroup PkgMDS3Ref +/// The classes in this group are the main classes involved . + +/// \defgroup PkgMDS3Functions Functions +/// \ingroup PkgMDS3Ref +/// The functions to work with the 3D mesh data structures. + +/// \defgroup PkgMDS3ExportFunctions Export Functions +/// \ingroup PkgMDS3Ref +/// The free functions that can be used to export meshes to given output file formats. + +/// \defgroup PkgMDS3IOFunctions Input/Output Functions +/// \ingroup PkgMDS3Ref +/// The free functions that can be used to read and write meshes. + +/*! +\addtogroup PkgMDS3Ref +\todo check generated documentation +\cgalPkgDescriptionBegin{3D Mesh Data Structures,PkgMDS3} +\todo add pkg picture +\cgalPkgPicture{MDS_3/fig/c3t3.jpg} +\cgalPkgSummaryBegin +\cgalPkgAuthors{Pierre Alliez, Clément Jamin, Laurent Rineau, Stéphane Tayeb, Jane Tournois, Mariette Yvinec} +\cgalPkgDesc{This package is devoted to the description of 3D Mesh Data Structures.} +\cgalPkgManuals{Chapter_3D_Mesh_Data_Structures,PkgMDS3Ref} +\cgalPkgSummaryEnd +\cgalPkgShortInfoBegin +\cgalPkgSince{5.4} +\cgalPkgDependsOn{\ref PkgTriangulation3} +\cgalPkgBib{cgal:ajrtty-mds3} +\cgalPkgLicense{\ref licensesGPL "GPL"} +\cgalPkgDemo{Polyhedron demo,polyhedron_3.zip} +\cgalPkgShortInfoEnd +\cgalPkgDescriptionEnd + +\cgalClassifedRefPages + +\cgalCRPSection{Concepts} + +Here are the main concepts of this package: + +- `MeshComplex_3InTriangulation_3` +- `MeshComplexWithFeatures_3InTriangulation_3` + +\cgalCRPSection{Classes} + +- `CGAL::Mesh_complex_3_in_triangulation_3` + +\cgalCRPSection{Function Templates} + +- `CGAL::facets_in_complex_3_to_triangle_mesh()` +- `CGAL::tetrahedron_soup_to_triangulation_3()` + +\cgalCRPSection{Export Functions} + +- `CGAL::output_to_medit()` +- `CGAL::output_to_vtu()` +- `CGAL::output_to_tetgen()` +- `CGAL::output_to_avizo()` + +\cgalCRPSection{Input/Output Functions} + +- `CGAL::write_MEDIT()` +- `CGAL::read_MEDIT()` +*/ + diff --git a/MDS_3/doc/MDS_3/dependencies b/MDS_3/doc/MDS_3/dependencies new file mode 100644 index 00000000000..aba33fcd34a --- /dev/null +++ b/MDS_3/doc/MDS_3/dependencies @@ -0,0 +1,14 @@ +Manual +BGL +Kernel_23 +STL_Extension +Algebraic_foundations +BGL +Stream_support +Triangulation_3 +Periodic_3_triangulation_3 +TDS_3 +Polyhedron +Miscellany +Mesh_3 +Tetrahedral_remeshing diff --git a/MDS_3/doc/MDS_3/examples.txt b/MDS_3/doc/MDS_3/examples.txt new file mode 100644 index 00000000000..e152939aa57 --- /dev/null +++ b/MDS_3/doc/MDS_3/examples.txt @@ -0,0 +1,4 @@ +/*! +\example MDS_3/c3t3_example.cpp +\example MDS_3/tetrahedron_soup_to_c3t3_example.cpp +*/ diff --git a/MDS_3/examples/MDS_3/CMakeLists.txt b/MDS_3/examples/MDS_3/CMakeLists.txt new file mode 100644 index 00000000000..2093c8a33df --- /dev/null +++ b/MDS_3/examples/MDS_3/CMakeLists.txt @@ -0,0 +1,17 @@ +# Created by the script cgal_create_CMakeLists +# This is the CMake script for compiling a set of CGAL applications. + +cmake_minimum_required(VERSION 3.1...3.20) + +project(MDS_3_Examples) + +# CGAL and its components +find_package(CGAL REQUIRED) + +# Boost and its components +find_package(Boost REQUIRED) + +# Creating entries for all C++ files with "main" routine +# ########################################################## +create_single_source_cgal_program( "c3t3_example.cpp" ) +create_single_source_cgal_program( "tetrahedron_soup_to_c3t3_example.cpp" ) diff --git a/MDS_3/examples/MDS_3/c3t3_example.cpp b/MDS_3/examples/MDS_3/c3t3_example.cpp new file mode 100644 index 00000000000..953e5648e7d --- /dev/null +++ b/MDS_3/examples/MDS_3/c3t3_example.cpp @@ -0,0 +1,30 @@ +#include + +#include + +#include + +#include + +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; + +int main(int argc, char* argv[]) +{ + const char* filename = (argc > 1) ? argv[1] : "data/sphere.mesh"; + + Remeshing_triangulation tr; + + std::ifstream is(filename, std::ios_base::in); + CGAL::IO::read_MEDIT(is, tr); + + // [call to a remeshing algorithm] + + std::ofstream os("after_remeshing.mesh"); + CGAL::IO::write_MEDIT(os, tr); + + return EXIT_SUCCESS; +} diff --git a/MDS_3/examples/MDS_3/tetrahedron_soup_to_c3t3_example.cpp b/MDS_3/examples/MDS_3/tetrahedron_soup_to_c3t3_example.cpp new file mode 100644 index 00000000000..09a9c0235d7 --- /dev/null +++ b/MDS_3/examples/MDS_3/tetrahedron_soup_to_c3t3_example.cpp @@ -0,0 +1,76 @@ +#include + +#include +#include +#include +#include + +#include + +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef CGAL::Delaunay_triangulation_3 DT3; +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; +typedef CGAL::Mesh_complex_3_in_triangulation_3 C3T3; + +typedef K::Point_3 Point_3; +typedef K::Tetrahedron_3 Tetrahedron_3; +typedef DT3::Vertex_handle Vertex_handle; + +int main(int , char* []) +{ + const int nbv = 100; + + //a triangulation + DT3 delaunay; + boost::unordered_map v2i; + boost::container::vector points(nbv); + boost::container::vector tetrahedra; + boost::container::vector > tets_by_indices; + + //insert random points + CGAL::Random_points_in_cube_3 randp(2.); + int i = 0; + while (i < nbv) + { + points[i] = *randp++; + Vertex_handle v = delaunay.insert(points[i]); + v2i[v] = i++; + } + + tetrahedra.reserve(delaunay.number_of_finite_cells()); + tets_by_indices.reserve(delaunay.number_of_finite_cells()); + for (DT3::Cell_handle c : delaunay.finite_cell_handles()) + { + tetrahedra.push_back(delaunay.tetrahedron(c)); + + std::array tet; + tet[0] = v2i.at(c->vertex(0)); + tet[1] = v2i.at(c->vertex(1)); + tet[2] = v2i.at(c->vertex(2)); + tet[3] = v2i.at(c->vertex(3)); + tet[4] = Remeshing_triangulation::Cell::Subdomain_index(1); + + tets_by_indices.push_back(tet); + } + + //build triangulation from tetrahedra + Remeshing_triangulation tr; + CGAL::tetrahedron_soup_to_triangulation_3(tetrahedra, tr); + + //buid triangulation from indices + Remeshing_triangulation tr2; + CGAL::tetrahedron_soup_to_triangulation_3(points, tets_by_indices, tr2); + + //build a C3T3 + C3T3 c3t3; + c3t3.triangulation() = tr; + + std::ofstream ofs("c3t3_output.mesh"); + c3t3.output_to_medit(ofs); + + return EXIT_SUCCESS; +} diff --git a/Mesh_3/include/CGAL/IO/Complex_3_in_triangulation_3_to_vtk.h b/MDS_3/include/CGAL/IO/Complex_3_in_triangulation_3_to_vtk.h similarity index 100% rename from Mesh_3/include/CGAL/IO/Complex_3_in_triangulation_3_to_vtk.h rename to MDS_3/include/CGAL/IO/Complex_3_in_triangulation_3_to_vtk.h diff --git a/Mesh_3/include/CGAL/IO/File_avizo.h b/MDS_3/include/CGAL/IO/File_avizo.h similarity index 100% rename from Mesh_3/include/CGAL/IO/File_avizo.h rename to MDS_3/include/CGAL/IO/File_avizo.h diff --git a/Mesh_3/include/CGAL/IO/File_binary_mesh_3.h b/MDS_3/include/CGAL/IO/File_binary_mesh_3.h similarity index 96% rename from Mesh_3/include/CGAL/IO/File_binary_mesh_3.h rename to MDS_3/include/CGAL/IO/File_binary_mesh_3.h index a2a87ee45ca..94972317b76 100644 --- a/Mesh_3/include/CGAL/IO/File_binary_mesh_3.h +++ b/MDS_3/include/CGAL/IO/File_binary_mesh_3.h @@ -13,13 +13,13 @@ #ifndef CGAL_IO_FILE_BINARY_MESH_3_H #define CGAL_IO_FILE_BINARY_MESH_3_H -#include +#include #include #include #include -#include +#include namespace CGAL { diff --git a/Mesh_3/include/CGAL/IO/File_maya.h b/MDS_3/include/CGAL/IO/File_maya.h similarity index 99% rename from Mesh_3/include/CGAL/IO/File_maya.h rename to MDS_3/include/CGAL/IO/File_maya.h index 4546132bb95..e4f4803744c 100644 --- a/Mesh_3/include/CGAL/IO/File_maya.h +++ b/MDS_3/include/CGAL/IO/File_maya.h @@ -12,7 +12,7 @@ #ifndef CGAL_IO_FILE_MAYA_H #define CGAL_IO_FILE_MAYA_H -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/IO/File_medit.h b/MDS_3/include/CGAL/IO/File_medit.h similarity index 77% rename from Mesh_3/include/CGAL/IO/File_medit.h rename to MDS_3/include/CGAL/IO/File_medit.h index 95585dc1b82..019a381652a 100644 --- a/Mesh_3/include/CGAL/IO/File_medit.h +++ b/MDS_3/include/CGAL/IO/File_medit.h @@ -14,10 +14,11 @@ #ifndef CGAL_IO_FILE_MEDIT_H #define CGAL_IO_FILE_MEDIT_H -#include +#include -#include -#include +#include +#include +#include #include #include @@ -26,6 +27,9 @@ #include #include +#include +#include + #include #include #include @@ -35,7 +39,7 @@ namespace CGAL { -namespace Mesh_3 { +namespace MDS_3 { //------------------------------------------------------- // Needed in verbose mode @@ -703,7 +707,9 @@ struct Medit_pmap_generator template void output_to_medit(std::ostream& os, - const C3T3& c3t3) + const C3T3& c3t3, + const bool all_vertices, + const bool all_cells) { #ifdef CGAL_MESH_3_IO_VERBOSE std::cerr << "Output to medit:\n"; @@ -726,7 +732,9 @@ output_to_medit(std::ostream& os, facet_pmap, cell_pmap, facet_pmap_twice, - Generator().print_twice()); + Generator().print_twice(), + all_vertices, + all_cells); #ifdef CGAL_MESH_3_IO_VERBOSE std::cerr << "done.\n"; @@ -747,14 +755,15 @@ output_to_medit(std::ostream& os, const Facet_index_property_map& facet_pmap, const Cell_index_property_map& cell_pmap, const Facet_index_property_map_twice& facet_twice_pmap = Facet_index_property_map_twice(), - const bool print_each_facet_twice = false) + const bool print_each_facet_twice = false, + const bool all_vertices = true, + const bool all_cells = true) { typedef typename C3T3::Triangulation Tr; typedef typename C3T3::Facets_in_complex_iterator Facet_iterator; - typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; - typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; typedef typename Tr::Point Point; //can be weighted or not const Tr& tr = c3t3.triangulation(); @@ -779,23 +788,46 @@ output_to_medit(std::ostream& os, boost::unordered_map V; int inum = 1; - for( Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); - ++vit) + if (all_vertices) { - V[vit] = inum++; - Point p = tr.point(vit); - os << CGAL::to_double(p.x()) << ' ' - << CGAL::to_double(p.y()) << ' ' - << CGAL::to_double(p.z()) << ' ' - << get(vertex_pmap, vit) - << '\n'; + for (Vertex_handle vit : tr.finite_vertex_handles()) + { + V[vit] = inum++; + Point p = tr.point(vit); + os << CGAL::to_double(p.x()) << ' ' + << CGAL::to_double(p.y()) << ' ' + << CGAL::to_double(p.z()) << ' ' + << get(vertex_pmap, vit) + << '\n'; + } + } + else + { + for (Cell_handle c : c3t3.cells_in_complex()) + { + for (int i = 0; i < 4; ++i) + { + Vertex_handle vit = c->vertex(i); + if (V.find(vit) == V.end()) + { + V[vit] = inum++; + Point p = tr.point(vit); + os << CGAL::to_double(p.x()) << ' ' + << CGAL::to_double(p.y()) << ' ' + << CGAL::to_double(p.z()) << ' ' + << get(vertex_pmap, vit) + << '\n'; + } + } + } } //------------------------------------------------------- // Facets //------------------------------------------------------- - typename C3T3::size_type number_of_triangles = c3t3.number_of_facets_in_complex(); + typename C3T3::size_type number_of_triangles + = std::distance(c3t3.facets_in_complex_begin(), + c3t3.facets_in_complex_end()); if ( print_each_facet_twice ) number_of_triangles += number_of_triangles; @@ -840,17 +872,31 @@ output_to_medit(std::ostream& os, //------------------------------------------------------- // Tetrahedra //------------------------------------------------------- + typename C3T3::size_type number_of_cells + = std::distance(c3t3.cells_in_complex_begin(), + c3t3.cells_in_complex_end()); os << "Tetrahedra\n" - << c3t3.number_of_cells_in_complex() << '\n'; + << number_of_cells << '\n'; - for( Cell_iterator cit = c3t3.cells_in_complex_begin() ; - cit != c3t3.cells_in_complex_end() ; - ++cit ) + if (all_cells) { - for (int i=0; i<4; i++) - os << V[cit->vertex(i)] << ' '; + for (Cell_handle cit : c3t3.triangulation().finite_cell_handles()) + { + for (int i = 0; i < 4; i++) + os << V[cit->vertex(i)] << ' '; - os << get(cell_pmap, cit) << '\n'; + os << get(cell_pmap, cit) << '\n'; + } + } + else + { + for (Cell_handle cit : c3t3.cells_in_complex()) + { + for (int i = 0; i < 4; i++) + os << V[cit->vertex(i)] << ' '; + + os << get(cell_pmap, cit) << '\n'; + } } //------------------------------------------------------- @@ -865,45 +911,125 @@ output_to_medit(std::ostream& os, namespace IO { /** - * @brief outputs mesh to medit format - * @param os the stream - * @param c3t3 the mesh - * @param rebind if true, labels of cells are rebinded into [1..nb_of_labels] - * @param show_patches if true, patches are labeled with different labels than - * cells. If false, each surface facet is written twice, using label of - * each adjacent cell. + * @ingroup PkgMDS3ExportFunctions + * @brief outputs a mesh complex to the medit (`.mesh`) file format. + See \cgalCite{frey:inria-00069921} for a comprehensive description of this file format. + * @param os the output stream + * @param c3t3 the mesh complex + * @param rebind if `true`, labels of cells are rebinded into `[1..nb_of_labels]` + * @param show_patches if `true`, patches are labeled with different labels than + * cells. If `false`, each surface facet is written twice, + * using the label of each adjacent cell. * \see \ref IOStreamMedit */ template void output_to_medit(std::ostream& os, const C3T3& c3t3, - bool rebind = false, - bool show_patches = false) + bool rebind, // = false, + bool show_patches // = false +#ifndef DOXYGEN_RUNNING + , bool all_vertices // = true + , bool all_cells // = false +#endif +) { if ( rebind ) { if ( show_patches ) - Mesh_3::output_to_medit(os,c3t3); + CGAL::MDS_3::output_to_medit(os, c3t3, + all_vertices, all_cells); else - Mesh_3::output_to_medit(os,c3t3); + CGAL::MDS_3::output_to_medit(os, c3t3, + all_vertices, all_cells); } else { if ( show_patches ) - Mesh_3::output_to_medit(os,c3t3); + CGAL::MDS_3::output_to_medit(os, c3t3, + all_vertices, all_cells); else - Mesh_3::output_to_medit(os,c3t3); + CGAL::MDS_3::output_to_medit(os, c3t3, + all_vertices, all_cells); } } - -template -void write_MEDIT(std::ostream& os, const T3& t3) +/** + * @ingroup PkgMDS3IOFunctions + * @brief outputs a mesh complex to the medit (`.mesh`) file format. + * See \cgalCite{frey:inria-00069921} for a comprehensive description of this file format. + * @tparam T3 can be instantiated with any 3D triangulation of \cgal provided that its + * vertex and cell base class are models of the concepts `MeshVertexBase_3` and `MeshCellBase_3`, respectively. + * @tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" + * + * @param os the output stream + * @param t3 the triangulation + * @param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below + * + * \cgalNamedParamsBegin + * \cgalParamNBegin{all_vertices} + * \cgalParamDescription{If `true`, all the vertices in `t3` are written in `os`. + * Otherwise, only the vertices that belong to a cell `c` for which + * `c->subdomain_index() != Subdomain_index()` are written} + * \cgalParamType{Boolean} + * \cgalParamDefault{`true`} + * \cgalParamExtra{This parameter should be set to `false` for the file to be readable by `read_MEDIT()`.} + * \cgalParamNEnd + * \cgalParamNBegin{all_cells} + * \cgalParamDescription{If `true`, all the cells in `t3` are written in `os`, + * however they belong to the complex or not. + * Otherwise, only the cells `c` for which + * `c->subdomain_index() != Subdomain_index()` are written} + * \cgalParamType{Boolean} + * \cgalParamDefault{`true`} + * \cgalParamExtra{If `all_vertices` is `true`, this parameter is ignored.} + * \cgalParamNEnd + * \see \ref IOStreamMedit + */ +template +void write_MEDIT(std::ostream& os, + const T3& t3, + const NamedParameters& np) { CGAL::Mesh_complex_3_in_triangulation_3 c3t3; c3t3.triangulation() = t3; c3t3.rescan_after_load_of_triangulation(); + + using parameters::get_parameter; + using parameters::choose_parameter; + + bool all_v = choose_parameter(get_parameter(np, internal_np::all_vertices), true); + bool rebind = false; + bool show_patches = false; + bool all_c = all_v || + choose_parameter(get_parameter(np, internal_np::all_cells), true); + + output_to_medit(os, c3t3, rebind, show_patches, all_v, all_c); +} + +template +void write_MEDIT(std::ostream& os, + const T3& t3) +{ + write_MEDIT(os, t3, parameters::all_default()); +} + +/** + * @ingroup PkgMDS3IOFunctions + * @brief outputs a mesh complex to the medit (`.mesh`) file format. + * See \cgalCite{frey:inria-00069921} for a comprehensive description of this file format. + * @tparam T3 can be instantiated with any 3D triangulation of \cgal provided that its + * vertex and cell base class are models of the concepts `MeshVertexBase_3` and `MeshCellBase_3`, respectively. + * @param os the output stream + * @param c3t3 the mesh complex + * + * \see \ref IOStreamMedit + */ +template +void write_MEDIT(std::ostream& os, + const CGAL::Mesh_complex_3_in_triangulation_3& c3t3) +{ + c3t3.rescan_after_load_of_triangulation(); output_to_medit(os, c3t3); } @@ -911,7 +1037,7 @@ template bool read_MEDIT(std::istream& in, T3& t3) { CGAL_assertion(!(!in)); - return CGAL::build_triangulation_from_file(in, t3); + return CGAL::MDS_3::build_triangulation_from_file(in, t3); } } // namespace IO diff --git a/Mesh_3/include/CGAL/IO/File_tetgen.h b/MDS_3/include/CGAL/IO/File_tetgen.h similarity index 89% rename from Mesh_3/include/CGAL/IO/File_tetgen.h rename to MDS_3/include/CGAL/IO/File_tetgen.h index 03fad2e7998..997ad1deacc 100644 --- a/Mesh_3/include/CGAL/IO/File_tetgen.h +++ b/MDS_3/include/CGAL/IO/File_tetgen.h @@ -25,7 +25,7 @@ namespace CGAL { -namespace Mesh_3 { +namespace MDS_3 { template void @@ -189,6 +189,18 @@ output_to_tetgen(std::string filename, namespace IO { + +/** + * \ingroup PkgMDS3IOFunctions + * @brief outputs a mesh complex to tetgen format + * @param filename the path to the output file + * @param c3t3 the mesh + * @param rebind if true, labels of cells are rebinded into [1..nb_of_labels] + * @param show_patches if true, patches are labeled with different labels than + * cells. If false, each surface facet is written twice, using label of + * each adjacent cell. + * \see \ref IOStreamTetgen + */ template void output_to_tetgen(std::string filename, @@ -199,16 +211,16 @@ output_to_tetgen(std::string filename, if ( rebind ) { if ( show_patches ) - Mesh_3::output_to_tetgen(filename,c3t3); + MDS_3::output_to_tetgen(filename,c3t3); else - Mesh_3::output_to_tetgen(filename,c3t3); + MDS_3::output_to_tetgen(filename,c3t3); } else { if ( show_patches ) - Mesh_3::output_to_tetgen(filename,c3t3); + MDS_3::output_to_tetgen(filename,c3t3); else - Mesh_3::output_to_tetgen(filename,c3t3); + MDS_3::output_to_tetgen(filename,c3t3); } } diff --git a/Mesh_3/include/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h b/MDS_3/include/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h similarity index 94% rename from Mesh_3/include/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h rename to MDS_3/include/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h index 95b6d7eeddf..4ac835a78d0 100644 --- a/Mesh_3/include/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h +++ b/MDS_3/include/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h @@ -14,7 +14,7 @@ #ifndef CGAL_IO_FACETS_IN_COMPLEX_3_TO_TRIANGLE_MESH_H #define CGAL_IO_FACETS_IN_COMPLEX_3_TO_TRIANGLE_MESH_H -#include +#include #ifndef CGAL_NO_DEPRECATED_CODE #include diff --git a/Mesh_3/include/CGAL/IO/output_to_vtu.h b/MDS_3/include/CGAL/IO/output_to_vtu.h similarity index 96% rename from Mesh_3/include/CGAL/IO/output_to_vtu.h rename to MDS_3/include/CGAL/IO/output_to_vtu.h index d553ddfdfed..3be8847e08b 100644 --- a/Mesh_3/include/CGAL/IO/output_to_vtu.h +++ b/MDS_3/include/CGAL/IO/output_to_vtu.h @@ -351,7 +351,17 @@ void output_to_vtu_with_attributes(std::ostream& os, } // namespace internal -//public API +//! \ingroup PkgMDS3IOFunctions +//! +//! \brief writes a tetrahedron mesh using the `UnstructuredGrid` XML format. +//! +//! \tparam C3T3 a model of `MeshComplexWithFeatures_3InTriangulation_3`. +//! +//! \param os the stream used for writing. +//! \param c3t3 the instance of `C3T3` to be written. +//! \param mode decides if the data should be written in binary (`IO::BINARY`) +//! or in ASCII (`IO::ASCII`). +//! template void output_to_vtu(std::ostream& os, const C3T3& c3t3, diff --git a/Mesh_3/include/CGAL/Mesh_3/Dump_c3t3.h b/MDS_3/include/CGAL/MDS_3/Dump_c3t3.h similarity index 97% rename from Mesh_3/include/CGAL/Mesh_3/Dump_c3t3.h rename to MDS_3/include/CGAL/MDS_3/Dump_c3t3.h index 5a798e665e0..69b73bcd8e0 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Dump_c3t3.h +++ b/MDS_3/include/CGAL/MDS_3/Dump_c3t3.h @@ -13,12 +13,11 @@ #ifndef CGAL_MESH_3_DUMP_C3T3_H #define CGAL_MESH_3_DUMP_C3T3_H -#include +#include #include -#include -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/io_signature.h b/MDS_3/include/CGAL/MDS_3/io_signature.h similarity index 100% rename from Mesh_3/include/CGAL/Mesh_3/io_signature.h rename to MDS_3/include/CGAL/MDS_3/io_signature.h diff --git a/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h b/MDS_3/include/CGAL/MDS_3/tet_soup_to_c3t3.h similarity index 86% rename from Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h rename to MDS_3/include/CGAL/MDS_3/tet_soup_to_c3t3.h index 5c2f6d69a08..91007cf3170 100644 --- a/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h +++ b/MDS_3/include/CGAL/MDS_3/tet_soup_to_c3t3.h @@ -14,10 +14,10 @@ // //****************************************************************************** -#ifndef CGAL_MESH_3_TET_SOUP_TO_C3T3_H -#define CGAL_MESH_3_TET_SOUP_TO_C3T3_H +#ifndef CGAL_MDS_3_TET_SOUP_TO_C3T3_H +#define CGAL_MDS_3_TET_SOUP_TO_C3T3_H -#include +#include #include #include @@ -32,7 +32,8 @@ namespace CGAL { - +namespace MDS_3 +{ template std::array make_ordered_vertex_array(const Vh vh0, const Vh vh1, const Vh vh2) { @@ -43,9 +44,9 @@ std::array make_ordered_vertex_array(const Vh vh0, const Vh vh1, const Vh return ft; } -template +template void build_vertices(Tr& tr, - const std::vector& points, + const PointRange& points, std::vector& vertex_handle_vector) { typedef typename Tr::Vertex_handle Vertex_handle; @@ -99,15 +100,15 @@ bool add_facet_to_incident_cells_map(const typename Tr::Cell_handle c, int i, return true; } -template +template bool build_finite_cells(Tr& tr, - const std::vector >& finite_cells, + const CellRange& finite_cells, const std::vector& vertex_handle_vector, boost::unordered_map, std::vector > >& incident_cells_map, - const std::map, typename Tr::Cell::Surface_patch_index>& border_facets, + const FacetPatchMap& border_facets, const bool verbose, - bool replace_domain_0 = false) + bool replace_domain_0 = false) { typedef std::array Tet_with_ref; // 4 ids + 1 reference @@ -118,6 +119,8 @@ bool build_finite_cells(Tr& tr, CGAL_assertion_code( typename Tr::Geom_traits::Construct_point_3 cp = tr.geom_traits().construct_point_3_object(); + typename Tr::Geom_traits::Orientation_3 orientation = + tr.geom_traits().orientation_3_object(); ) int max_domain = 0; if(replace_domain_0) @@ -145,8 +148,8 @@ bool build_finite_cells(Tr& tr, } // this assertion also tests for degeneracy - CGAL_assertion(CGAL::orientation(cp(tr.point(vs[0])), cp(tr.point(vs[1])), - cp(tr.point(vs[2])), cp(tr.point(vs[3]))) + CGAL_assertion(orientation(cp(tr.point(vs[0])), cp(tr.point(vs[1])), + cp(tr.point(vs[2])), cp(tr.point(vs[3]))) == POSITIVE); Cell_handle c = tr.tds().create_cell(vs[0], vs[1], vs[2], vs[3]); @@ -335,11 +338,14 @@ bool assign_neighbors(Tr& tr, return true; } -template +template bool build_triangulation(Tr& tr, - const std::vector& points, - const std::vector >& finite_cells, - const std::map, typename Tr::Cell::Surface_patch_index>& border_facets, + const PointRange& points, + const CellRange& finite_cells, + const FacetPatchMap& border_facets, std::vector& vertex_handle_vector, const bool verbose = false, bool replace_domain_0 = false) @@ -390,15 +396,34 @@ bool build_triangulation(Tr& tr, if(verbose) std::cout << tr.number_of_vertices() << " vertices" << std::endl; - if(c3t3_loader_failed) - return true; - else - return tr.tds().is_valid(); + return true;// tr.tds().is_valid(); + //TDS not valid when cells do not cover the convex hull of vertices } -template +template +bool build_triangulation(Tr& tr, + const PointRange& points, + const CellRange& finite_cells, + const FacetPatchMap& border_facets, + const bool verbose = false, + bool replace_domain_0 = false) +{ + BOOST_STATIC_ASSERT(boost::is_same::value); + std::vector vertex_handle_vector; + + return build_triangulation(tr, points, finite_cells, border_facets, + vertex_handle_vector, + verbose, replace_domain_0); +} + +template bool build_triangulation_from_file(std::istream& is, Tr& tr, + const bool verbose, bool replace_domain_0) { typedef typename Tr::Point Point_3; @@ -420,7 +445,9 @@ bool build_triangulation_from_file(std::istream& is, CGAL_assertion(dim == 3); - std::cout << "Reading .mesh file..." << std::endl; + if(verbose) + std::cout << "Reading .mesh file..." << std::endl; + while(is >> word && word != "End") { if(word == "Vertices") @@ -479,27 +506,24 @@ bool build_triangulation_from_file(std::istream& is, } } - std::cout << points.size() << " points" << std::endl; - std::cout << border_facets.size() << " border facets" << std::endl; - std::cout << finite_cells.size() << " cells" << std::endl; + if (verbose) + { + std::cout << points.size() << " points" << std::endl; + std::cout << border_facets.size() << " border facets" << std::endl; + std::cout << finite_cells.size() << " cells" << std::endl; + } if(finite_cells.empty()) return false; - std::vector vertices(points.size() + 1); - bool is_well_built = build_triangulation(tr, - points, finite_cells, border_facets, vertices, false, replace_domain_0); - return is_well_built; + return build_triangulation(tr, + points, finite_cells, border_facets, + verbose, replace_domain_0); } -template -bool build_triangulation_from_file(std::istream& is, - Tr& tr) -{ - return build_triangulation_from_file(is, tr, false); -} +} // namespace MDS_3 } // namespace CGAL #include -#endif // CGAL_MESH_3_TET_SOUP_TO_C3T3_H +#endif // CGAL_MDS_3_TET_SOUP_TO_C3T3_H diff --git a/Mesh_3/include/CGAL/Mesh_3/utilities.h b/MDS_3/include/CGAL/MDS_3/utilities.h similarity index 93% rename from Mesh_3/include/CGAL/Mesh_3/utilities.h rename to MDS_3/include/CGAL/MDS_3/utilities.h index 5e49f7a617e..02bbd8454f1 100644 --- a/Mesh_3/include/CGAL/Mesh_3/utilities.h +++ b/MDS_3/include/CGAL/MDS_3/utilities.h @@ -14,10 +14,10 @@ // File Description : //****************************************************************************** -#ifndef CGAL_MESH_3_UTILITIES_H -#define CGAL_MESH_3_UTILITIES_H +#ifndef CGAL_MDS_3_UTILITIES_H +#define CGAL_MDS_3_UTILITIES_H -#include +#include #include #include @@ -25,7 +25,7 @@ #include namespace CGAL { -namespace Mesh_3 { +namespace MDS_3 { namespace internal { struct Debug_messages_tools { @@ -115,7 +115,7 @@ public: } // end namespace internal -} // end namespace Mesh_3 +} // end namespace MDS_3 } //namespace CGAL -#endif // CGAL_MESH_3_UTILITIES_H +#endif // CGAL_MDS_3_UTILITIES_H diff --git a/MDS_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h b/MDS_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h new file mode 100644 index 00000000000..84434a57714 --- /dev/null +++ b/MDS_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h @@ -0,0 +1,2006 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// Copyright (c) 2010-2013 GeometryFactory Sarl (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Stephane Tayeb, Clement Jamin +// +//****************************************************************************** +// File Description : +//****************************************************************************** + +#ifndef CGAL_MESH_COMPLEX_3_IN_TRIANGULATION_3_H +#define CGAL_MESH_COMPLEX_3_IN_TRIANGULATION_3_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +#ifdef CGAL_LINKED_WITH_TBB +#include +#include + +namespace CGAL { + template < class DSC, bool Const > + std::size_t tbb_hasher(const CGAL::internal::CC_iterator& it) + { + return CGAL::internal::hash_value(it); + } + + // As Marc Glisse pointed out the TBB hash of a std::pair is + // simplistic and leads to the + // TBB Warning: Performance is not optimal because the hash function + // produces bad randomness in lower bits in class + // tbb::interface5::concurrent_hash_map + template < class DSC, bool Const > + std::size_t tbb_hasher(const std::pair, + CGAL::internal::CC_iterator >& p) + { + return boost::hash, + CGAL::internal::CC_iterator > >()(p); + } +}//end namespace CGAL +#endif + +namespace CGAL { + + namespace MDS_3 { + + namespace details { + + template + class C3t3_helper_class + { + protected: + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Facet Facet; + typedef typename Tr::Edge Edge; + + typedef std::pair Pair_of_vertices; + + // computes and returns an ordered pair of Vertex + Pair_of_vertices + make_ordered_pair(const Vertex_handle vh1, const Vertex_handle vh2) const { + if (vh1 < vh2) { + return std::make_pair(vh1, vh2); + } + else { + return std::make_pair(vh2, vh1); + } + } + // same from an Edge + Pair_of_vertices + make_ordered_pair(const Edge e) const { + return make_ordered_pair(e.first->vertex(e.second), + e.first->vertex(e.third)); + } + Facet canonical_facet(Cell_handle c, int i) const { + Cell_handle c2 = c->neighbor(i); + return (c2 < c) ? std::make_pair(c2, c2->index(c)) : std::make_pair(c, i); + } + }; // end class template C3t3_helper_class + + } // end namespace MDS_3::details + } //end namesapce MDS_3 + +/*! + \ingroup PkgMDS3Classes + + * @brief A data-structure to represent and maintain a 3D complex embedded + * in a 3D triangulation. + + The class `Mesh_complex_3_in_triangulation_3` implements a data structure + to store the 3D restricted Delaunay triangulation used by a mesh + generation process. + + This class is a model of the concept + `MeshComplexWithFeatures_3InTriangulation_3`. + + + \tparam Tr can be instantiated with any 3D + regular triangulation of \cgal provided that its + vertex and cell base class are models of the concepts + `MeshVertexBase_3` and `MeshCellBase_3`, respectively. + + \tparam CornerIndex is the type of the indices for corners. It must match the `Corner_index` of the model + of the `MeshDomainWithFeatures_3` concept used for mesh generation. + + \tparam CurveIndex is the type of the indices for curves. + It must match the `Curve_index` types of the model + of the `MeshDomainWithFeatures_3` concept used for mesh generation. + + Those two last template parameters defaults to `int`, so that they can be ignored + if the domain used for mesh generation does not include 0 and 1-dimensionnal features (i.e + is a model of the concept `MeshDomain_3`). + + \cgalModels `MeshComplexWithFeatures_3InTriangulation_3` + + \sa `CGAL::make_mesh_3()` + \sa `CGAL::refine_mesh_3()` + \sa `MeshComplex_3InTriangulation_3` + \sa `MeshComplexWithFeatures_3InTriangulation_3` + \sa `MeshCellBase_3`, + \sa `MeshVertexBase_3` + +*/ +template +class Mesh_complex_3_in_triangulation_3 +#ifndef DOXYGEN_RUNNING + : public CGAL::MDS_3::details::C3t3_helper_class + , public CGAL::MDS_3::internal::Debug_messages_tools +#endif +{ +public: + typedef typename Tr::Concurrency_tag Concurrency_tag; + +private: + typedef Mesh_complex_3_in_triangulation_3< + Tr,CornerIndex,CurveIndex> Self; + typedef MDS_3::details::C3t3_helper_class Base; + typedef CGAL::Hash_handles_with_or_without_timestamps Hash_fct; + +public: + +#ifndef CGAL_NO_DEPRECATED_CODE + typedef CurveIndex Curve_segment_index; +#endif + +/// \name Types +/// @{ + typedef Tr Triangulation; + typedef typename Tr::size_type size_type; + typedef typename Tr::Point Point; + typedef typename Tr::Edge Edge; + typedef typename Tr::Facet Facet; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + /*! + Index type. + */ + typedef typename Tr::Vertex::Index Index; + /*! + Surface index type. + */ + typedef typename Tr::Cell::Surface_patch_index Surface_patch_index; + /*! + Subdomain index type. + */ + typedef typename Tr::Cell::Subdomain_index Subdomain_index; + /*! + Corner index type. + */ + typedef CornerIndex Corner_index; + /*! + Curve index type. + */ + typedef CurveIndex Curve_index; +/// @} + + +private: + // Type to store the edges: + // - a set of std::pair (ordered at insertion) + // - which allows fast lookup from one Vertex_handle + // - each element of the set has an associated info (Curve_index) value + typedef boost::bimaps::bimap< + boost::bimaps::multiset_of, + boost::bimaps::multiset_of, + boost::bimaps::set_of_relation<>, + boost::bimaps::with_info > Edge_map; + + typedef typename Edge_map::value_type Internal_edge; + + // Type to store the corners + typedef boost::unordered_map Corner_map; + + // Type to store far vertices + typedef std::vector Far_vertices_vec; + +public: + enum Face_status { + NOT_IN_COMPLEX = 0, + ISOLATED = 1, // - An ISOLATED edge is a marked edge, + // without any incident facets. + BOUNDARY, // - An edge is on BOUNDARY if it has only + // one incident facet. + // - A vertex is on BOUNDARY if all its + // incident edges are REGULAR or on + // BOUNDARY, at least one is on + // BOUNDARY, and the incident facets + // form only one connected component. + REGULAR, // - A facet that is in the complex is + // REGULAR. + // - An edge is REGULAR if it has + // exactly two incident facets. + // - A vertex is REGULAR if all it + // incident edges are REGULAR, and the + // incident facets form only one + // connected component. + SINGULAR // - SINGULAR is for all other cases. + }; + +/// \name Creation +/// @{ + /** + * @brief Constructor + * Builds an empty 3D complex. + */ + Mesh_complex_3_in_triangulation_3(); + /** + * Copy constructor + */ + Mesh_complex_3_in_triangulation_3(const Self& rhs); + + /** + * Move constructor + */ + Mesh_complex_3_in_triangulation_3(Self&& rhs); + + /** + * Assignement operator, also serves as move-assignement + */ + Self& operator=(Self rhs) + { + swap(rhs); + return *this; + } + + /** + * Swaps `this` and `rhs` + */ + void swap(Self& rhs) + { + Swap_elements swapper; + swapper(rhs.number_of_facets_, number_of_facets_); + tr_.swap(rhs.tr_); + swapper(rhs.number_of_cells_, number_of_cells_); + + edges_.swap(rhs.edges_); + corners_.swap(rhs.corners_); + far_vertices_.swap(rhs.far_vertices_); + } + +/// @} + +/// \name Access Functions +/// @{ + /// Returns a const reference to the triangulation + const Triangulation& triangulation() const { return tr_; } +/// @} + +/// \name Non const access +/// @{ + /// Returns the reference to the triangulation + Triangulation& triangulation() { return tr_; } +/// @} + + +/// \name Modifiers +/// @{ + /** + * Clears data of c3t3 + */ + void clear() + { + number_of_cells_ = 0; + number_of_facets_ = 0; + clear_manifold_info(); + tr_.clear(); + edges_.clear(); + corners_.clear(); + far_vertices_.clear(); + } + + /** Adds cell \c cell to the 3D complex, with subdomain index \c index + */ + void add_to_complex(const Cell_handle& cell, const Subdomain_index& index) + { + CGAL_precondition(!(index == Subdomain_index())); + + if (!is_in_complex(cell)) + { + set_subdomain_index(cell, index); + ++number_of_cells_; + } + } + /** Adds facet \c facet to the 2D complex, with surface index \c index + */ + void add_to_complex(const Facet& facet, const Surface_patch_index& index) + { + add_to_complex(facet.first, facet.second, index); + } + /** Adds facet(\c cell, \c i) to the 2D complex, with surface index \c index + */ + void add_to_complex(const Cell_handle& cell, + const int i, + const Surface_patch_index& index); + + /** Adds edge e to complex, with Curve_index index + */ + void add_to_complex(const Edge& e, + const Curve_index& index) + { + add_to_complex(e.first->vertex(e.second), + e.first->vertex(e.third), + index); + } + + /** + * Adds edge (v1,v2) to complex, with Curve_index index + */ + void add_to_complex(const Vertex_handle& v1, + const Vertex_handle& v2, + const Curve_index& index) + { + add_to_complex(make_internal_edge(v1,v2), index); + } + + /** + * Mark vertex \c v as a corner of the complex + */ + void add_to_complex(const Vertex_handle& v, const Corner_index& index) + { + v->set_dimension(0); + corners_.insert(std::make_pair(v,index)); + } + + /** Removes cell \c cell from the 3D complex + */ + void remove_from_complex(const Cell_handle& cell) + { + if (is_in_complex(cell)) + { + set_subdomain_index(cell, Subdomain_index()); + --number_of_cells_; + } + } + /** Removes facet \c facet from 2D complex + */ + void remove_from_complex(const Facet& facet); + + /** Removes facet(\c cell, \c i) from 2D complex + */ + void remove_from_complex(const Cell_handle& c, const int i) { + remove_from_complex(Facet(c, i)); + } + /** + * Remove edge \c e from complex + */ + void remove_from_complex(const Edge& e) + { + remove_from_complex(e.first->vertex(e.second), e.first->vertex(e.third)); + } + + /** + * Remove edge (v1,v2) from complex + */ + void remove_from_complex(const Vertex_handle& v1, const Vertex_handle& v2) + { + remove_from_complex(make_internal_edge(v1,v2)); + } + + /** + * Remove vertex \c v from complex + */ + void remove_from_complex(const Vertex_handle& v) + { + corners_.erase(v); + v->set_dimension(-1); + } + + /** Sets index of vertex \c vertex to \c index + */ + void set_index(const Vertex_handle& vertex, const Index& index) const + { + vertex->set_index(index); + } + /** Sets surface index of facet \c facet to \c index + */ + void set_surface_patch_index(const Facet& f, const Surface_patch_index& index) + { + set_surface_patch_index(f.first, f.second, index); + } + /** Sets surface index of facet(\c cell, \c i) to \c index + */ + void set_surface_patch_index(const Cell_handle& cell, + const int i, + const Surface_patch_index& index) const + { + cell->set_surface_patch_index(i, index); + } + /** Sets subdomain index of cell \c cell to \c index + */ + void set_subdomain_index(const Cell_handle& cell, + const Subdomain_index& index) const + { + cell->set_subdomain_index(index); + } + /** Sets dimension of vertex \c vertex to \c dimension + */ + void set_dimension(const Vertex_handle& vertex, int dimension) const + { + vertex->set_dimension(dimension); + } +/// @} + +/// \name Queries on the identifier of the face complex including triangulation cells, facets and vertices. +/// @{ + /** Returns the index of vertex \c v + */ + Index index(const Vertex_handle& v) const { return v->index(); } + + /** Returns the subdomain index of cell \c cell + */ + Subdomain_index subdomain_index(const Cell_handle& cell) const + { + return cell->subdomain_index(); + } + /** Returns surface index of facet \c f + */ + Surface_patch_index surface_patch_index(const Facet& f) const + { + return surface_patch_index(f.first, f.second); + } + + /** Returns surface index of facet(\c cell, \c i) + */ + Surface_patch_index surface_patch_index(const Cell_handle& cell, + const int i) const + { + return cell->surface_patch_index(i); + } + /** Returns the dimension of the lowest dimensional face of the input 3D + * complex that contains the vertex + */ + int in_dimension(const Vertex_handle& v) const { return v->in_dimension(); } + + /** + * Returns Curve_index of edge \c e + */ + Curve_index curve_index(const Edge& e) const + { + return curve_index(e.first->vertex(e.second), + e.first->vertex(e.third)); + } + + /** + * Returns Curve_index of the edge formed by \c v1 and \c v2 + */ + Curve_index curve_index(const Vertex_handle& v1, + const Vertex_handle& v2) const + { + return curve_index(make_internal_edge(v1, v2)); + } + + /** + * Returns Corner_index of vertex \c v + */ + Corner_index corner_index(const Vertex_handle& v) const + { + typename Corner_map::const_iterator it = corners_.find(v); + if (corners_.end() != it) { return it->second; } + return Corner_index(); + } +/// @} + +#ifndef CGAL_NO_DEPRECATED_CODE + CGAL_DEPRECATED + Curve_index curve_segment_index(const Edge& e) const + { + return curve_index(e); + } + + CGAL_DEPRECATED + Curve_index curve_segment_index(const Vertex_handle& v1, + const Vertex_handle& v2) const + { + return curve_index(v1, v2); + } +#endif // CGAL_NO_DEPRECATED_CODE + + std::size_t number_of_far_points() const + { + return far_vertices_.size(); + } + + void add_far_point(const Point &p) + { + far_vertices_.push_back(triangulation().insert(p)); + } + + void add_far_point(Vertex_handle vh) + { + far_vertices_.push_back(vh); + } + + void remove_far_points() + { + Triangulation &tr = triangulation(); + //triangulation().remove(far_vertices_.begin(), far_vertices_.end()); + typename Far_vertices_vec::const_iterator it = far_vertices_.begin(); + typename Far_vertices_vec::const_iterator it_end = far_vertices_.end(); + for ( ; it != it_end ; ++it) + { + std::vector new_cells; + new_cells.reserve(32); + tr.remove_and_give_new_cells(*it, std::back_inserter(new_cells)); + + typename std::vector::iterator nc_it = new_cells.begin(); + typename std::vector::iterator nc_it_end = new_cells.end(); + for ( ; nc_it != nc_it_end ; ++nc_it) + { + Cell_handle c = *nc_it; + for (int i = 0 ; i < 4 ; ++i) + { + Facet mirror_facet = tr.mirror_facet(std::make_pair(c, i)); + if (is_in_complex(mirror_facet)) + { + set_surface_patch_index(c, i, + surface_patch_index(mirror_facet)); + c->set_facet_surface_center(i, + mirror_facet.first->get_facet_surface_center(mirror_facet.second)); + } + } + /*int i_inf; + if (c->has_vertex(tr.infinite_vertex(), i_inf)) + { + Facet mirror_facet = tr.mirror_facet(std::make_pair(c, i_inf)); + if (is_in_complex(mirror_facet)) + { + set_surface_patch_index(c, i_inf, + surface_patch_index(mirror_facet)); + } + }*/ + } + } + far_vertices_.clear(); + } + + void rescan_after_load_of_triangulation(); + +/// \name Queries on the faces of the embedded complex +/// @{ + /** + * Returns the number of cells which belongs to the 3D complex + */ + size_type number_of_cells_in_complex() const { return number_of_cells_; } + /** + * Returns the number of cells which belongs to the 3D complex + */ + size_type number_of_cells() const + { + return number_of_cells_in_complex(); + } + /** + * Returns the number of surface facets of c3t3 + */ + size_type number_of_facets_in_complex() const { return number_of_facets_; } + /** + * Returns the number of surface facets of c3t3 + */ + size_type number_of_facets() const + { + return number_of_facets_in_complex(); + } + /** + * Returns the number of edges of c3t3 + */ + size_type number_of_edges_in_complex() const + { + return edges_.size(); + } + /** + * Returns the number of edges of c3t3 + */ + size_type number_of_edges() const + { + return edges_.size(); + } + /** + * Returns the number of corners of c3t3 + */ + size_type number_of_vertices_in_complex() const + { + return corners_.size(); + } + /** + * Returns the number of corners of c3t3 + */ + size_type number_of_corners() const + { + return corners_.size(); + } + /** + * Returns \c true if cell \c cell belongs to the 3D complex + */ + bool is_in_complex(const Cell_handle& cell) const + { + return !(subdomain_index(cell) == Subdomain_index()); + } + /** Returns true if facet \c facet is in complex + */ + bool is_in_complex(const Facet& facet) const + { + return is_in_complex(facet.first, facet.second); + } + + /** Returns true if facet (\c cell, \c i) is in 2D complex + */ + bool is_in_complex(const Cell_handle& cell, const int i) const + { + return (cell->is_facet_on_surface(i)); + } + /** + * Returns true if edge \c e is in complex + */ + bool is_in_complex(const Edge& e) const + { + return is_in_complex(e.first->vertex(e.second), e.first->vertex(e.third)); + } + + /** + * Returns true if edge (v1,v2) is in C3T3 + */ + bool is_in_complex(const Vertex_handle& v1, const Vertex_handle& v2) const + { + return is_in_complex(make_internal_edge(v1,v2)); + } + + /** + * Returns true if \c v is a 0-dimensionnal feature in the c3t3 + */ + bool is_in_complex(const Vertex_handle& v) const + { + return (corners_.find(v) != corners_.end()); + } +/// @} + + + /// \name I/O Functions + /// @{ + /** + * Outputs the outer boundary of the entire domain with facets oriented outward. + */ + std::ostream& output_boundary_to_off(std::ostream& out) const + { + internal::output_boundary_of_c3t3_to_off(*this, 0, out, false); + return out; + } + + /** + * Outputs the outer boundary of the selected subdomain with facets oriented outward. + */ + std::ostream& output_boundary_to_off(std::ostream& out, Subdomain_index subdomain) const + { + output_boundary_of_c3t3_to_off(*this, subdomain, out); + return out; + } + + /** + * Outputs the surface facets with a consistent orientation at the interface of two subdomains. + */ + std::ostream& output_facets_in_complex_to_off(std::ostream& out) const + { + internal::output_facets_in_complex_to_off(*this, out); + return out; + } + + /*! + Outputs the mesh to `os` + in Medit format. + */ +#ifdef DOXYGEN_RUNNING + void output_to_medit(std::ostream& os) const +#else + void output_to_medit(std::ostream& os, + bool rebind = true, + bool show_patches = false) const +#endif + { + // Call global function + bool all_vertices = true; + bool all_cells = false; + CGAL::IO::output_to_medit(os, *this, rebind, show_patches, + all_vertices, all_cells); + } + + /*! + * Outputs the mesh to `os` in Maya format. + */ + void output_to_maya(std::ostream& os, bool surfaceOnly = true) const + { + // Call global function + CGAL::IO::output_to_maya(os, *this, surfaceOnly); + } + + /// @} + + /** + * Fills \c out with incident edges (1-dimensional features of \c v. + * OutputIterator value type is std::pair + * \pre v->in_dimension() < 2 + */ + template + OutputIterator + adjacent_vertices_in_complex(const Vertex_handle& v, OutputIterator out) const; + + // ----------------------------------- + // Undocumented + // ----------------------------------- + + bool is_valid(bool verbose = false) const; + + // ----------------------------------- + // Complex traversal + // ----------------------------------- +private: + /** + * @class Cell_not_in_complex + * @brief A class to filter cells which do not belong to the complex + */ + class Cell_not_in_complex + { + const Self* r_self_; + Subdomain_index index_;//needed by SWIG, should be const Subdomain_index + public: + Cell_not_in_complex() {}//needed by SWIG + Cell_not_in_complex(const Self& self, + const Subdomain_index& index = Subdomain_index()) + : r_self_(&self) + , index_(index) { } + + bool operator()(Cell_handle ch) const + { + if (index_ == Subdomain_index()) { return !r_self_->is_in_complex(ch); } + else { return !(r_self_->subdomain_index(ch) == index_); } + } + }; // end class Cell_not_in_complex + + typedef MDS_3::internal::Iterator_not_in_complex Iterator_not_in_complex; + + class Facet_iterator_not_in_complex + { + const Self* c3t3_; + Surface_patch_index index_; //need by SWIG: should be const Surface_patch_index + public: + Facet_iterator_not_in_complex() {} //need by SWIG + Facet_iterator_not_in_complex(const Self& c3t3, + const Surface_patch_index& index = Surface_patch_index()) + : c3t3_(&c3t3) + , index_(index) { } + + template + bool operator()(Iterator it) const + { + if (index_ == Surface_patch_index()) { return !c3t3_->is_in_complex(*it); } + else { return !(c3t3_->surface_patch_index(*it) == index_); } + } + }; + + class Edge_iterator_not_in_complex + { + const Self& c3t3_; + const Curve_index index_; + public: + Edge_iterator_not_in_complex(const Self& c3t3, + const Curve_index& index = Curve_index()) + : c3t3_(c3t3) + , index_(index) { } + + template + bool operator()(Iterator it) const + { + if ( index_ == Curve_index() ) { return ! c3t3_.is_in_complex(*it); } + else { return c3t3_.curve_index(*it) != index_; } + } + }; + + class Vertex_iterator_not_in_complex + { + const Self& c3t3_; + const Corner_index index_; + public: + Vertex_iterator_not_in_complex(const Self& c3t3, + const Corner_index& index = Corner_index()) + : c3t3_(c3t3) + , index_(index) { } + + template + bool operator()(const ItMap it) const + { + if ( index_ == Corner_index() ) { return false; } + else { return it->second != index_; } + } + }; + + // Filtered iterator + typedef Filter_iterator< + typename Corner_map::const_iterator, + Vertex_iterator_not_in_complex > Vertex_map_filter_iterator; + + // Iterator type to get the first element of pair + typedef boost::transform_iterator < + MDS_3::internal::First_of, + Vertex_map_filter_iterator > Vertex_map_iterator_first; + + // Iterator type to remove a level of referencing + class Vertex_map_iterator_first_dereference + : public boost::iterator_adaptor < + Vertex_map_iterator_first_dereference, + Vertex_map_iterator_first, + typename Vertex_map_iterator_first::value_type::value_type, + boost::use_default, + typename Vertex_map_iterator_first::value_type::reference > + { + typedef Vertex_map_iterator_first_dereference Self; + typedef boost::iterator_adaptor < + Vertex_map_iterator_first_dereference, + Vertex_map_iterator_first, + typename Vertex_map_iterator_first::value_type::value_type, + boost::use_default, + typename Vertex_map_iterator_first::value_type::reference > iterator_adaptor_; + public: + typedef typename Vertex_map_iterator_first::reference pointer; + typedef typename iterator_adaptor_::reference reference; + + Vertex_map_iterator_first_dereference() : Self::iterator_adaptor_() { } + + template < typename Iterator > + Vertex_map_iterator_first_dereference(Iterator i) + : Self::iterator_adaptor_(typename Self::iterator_adaptor_::base_type(i)) + { } + + pointer operator->() const { return *(this->base()); } + reference operator*() const { return **(this->base()); } + + operator Vertex_handle() { return Vertex_handle(*(this->base())); } + }; + +public: +/// \name Traversal of the complex +/// @{ +#ifdef DOXYGEN_RUNNING + /// Iterator type to visit the cells of the 3D complex + typedef unspecified_type Cells_in_complex_iterator; + /// Iterator type to visit the facets of the 2D complex + typedef unspecified_type Facets_in_complex_iterator; + /// Iterator type to visit the edges of the 1D complex + typedef unspecified_type Edges_in_complex_iterator; + /// Iterator type to visit the vertices of the 0D complex + typedef unspecified_type Vertices_in_complex_iterator; + + /// Range type for iterating over all cells of the 3D complex, + /// with a nested type iterator that has as value type `Cell_handle`. + typedef Iterator_range Cells_in_complex; + /// Range type for iterating over all facets of the 2D complex, + /// with a nested type iterator that has as value type `Facet`. + typedef Iterator_range Facets_in_complex; + /// Range type for iterating over all cells of the 1D complex, + /// with a nested type iterator that has as value type `Edge`. + typedef Iterator_range Edges_in_complex; + /// Range type for iterating over all vertices of the 0D complex, + /// with a nested type iterator that has as value type `Vertex_handle`. + typedef Iterator_range Vertices_in_complex; + +#else + typedef Filter_iterator< + typename Triangulation::Finite_edges_iterator, + Edge_iterator_not_in_complex > Edges_in_complex_iterator; + typedef Vertex_map_iterator_first_dereference Vertices_in_complex_iterator; + typedef Filter_iterator< + typename Triangulation::Finite_facets_iterator, + Facet_iterator_not_in_complex > Facets_in_complex_iterator; + + /** + * @class Cells_in_complex_iterator + * @brief Iterator type to visit the cells of triangulation belonging + * to the 3D complex + * + * This class is useful to ensure that Cells_in_complex_iterator is convertible + * to Cell_handle + */ + class Cells_in_complex_iterator : + public Filter_iterator + { + private: + typedef typename Triangulation::Finite_cells_iterator Tr_iterator; + typedef Filter_iterator Base; + typedef Cells_in_complex_iterator Self; + + public: + Cells_in_complex_iterator() : Base() { } + Cells_in_complex_iterator(Base i) : Base(i) { } + + Self& operator++() { Base::operator++(); return *this; } + Self& operator--() { Base::operator--(); return *this; } + Self operator++(int) { Self tmp(*this); ++(*this); return tmp; } + Self operator--(int) { Self tmp(*this); --(*this); return tmp; } + + operator Cell_handle() const { return Cell_handle(this->base()); } + }; // end class Cells_in_complex_iterator + + typedef Iterator_range > Vertices_in_complex; + typedef Iterator_range Edges_in_complex; + typedef Iterator_range Facets_in_complex; + typedef Iterator_range > Cells_in_complex; + +#endif + +/// \name Iterators +/// @{ + + /// Returns a \c Cells_in_complex_iterator to the first cell of the 3D complex + Cells_in_complex_iterator cells_in_complex_begin() const + { + return CGAL::filter_iterator(tr_.finite_cells_end(), + Cell_not_in_complex(*this), + tr_.finite_cells_begin()); + } + + /// Returns a \c Cells_in_complex_iterator to the first cell of the 3D complex + Cells_in_complex_iterator cells_in_complex_begin(const Subdomain_index& index) const + { + return CGAL::filter_iterator(tr_.finite_cells_end(), + Cell_not_in_complex(*this, index), + tr_.finite_cells_begin()); + } + + /// Returns the past-the-end iterator for the cells of the 3D complex + Cells_in_complex_iterator cells_in_complex_end() const + { + return CGAL::filter_iterator(tr_.finite_cells_end(), + Cell_not_in_complex(*this)); + } + + /// Returns a `Facets_in_complex_iterator` to the first facet of the 2D complex + Facets_in_complex_iterator facets_in_complex_begin() const + { + return CGAL::filter_iterator(tr_.finite_facets_end(), + Facet_iterator_not_in_complex(*this), + tr_.finite_facets_begin()); + } + + /// Returns a `Facets_in_complex_iterator` to the first facet of the 2D complex + Facets_in_complex_iterator + facets_in_complex_begin(const Surface_patch_index& index) const + { + return CGAL::filter_iterator(tr_.finite_facets_end(), + Facet_iterator_not_in_complex(*this, index), + tr_.finite_facets_begin()); + } + + /// Returns past-the-end iterator on facet of the 2D complex + Facets_in_complex_iterator facets_in_complex_end(const Surface_patch_index = Surface_patch_index()) const + { + return CGAL::filter_iterator(tr_.finite_facets_end(), + Facet_iterator_not_in_complex(*this)); + } + + /// Returns a `Edges_in_complex_iterator` to the first edge of the 1D complex + Edges_in_complex_iterator edges_in_complex_begin() const + { + return CGAL::filter_iterator(this->triangulation().finite_edges_end(), + Edge_iterator_not_in_complex(*this), + this->triangulation().finite_edges_begin()); + } + + /// Returns a `Edges_in_complex_iterator` to the first edge of the 1D complex + Edges_in_complex_iterator + edges_in_complex_begin(const Curve_index& index) const + { + return CGAL::filter_iterator(this->triangulation().finite_edges_end(), + Edge_iterator_not_in_complex(*this,index), + this->triangulation().finite_edges_begin()); + } + + /// Returns past-the-end iterator on edges of the 1D complex + Edges_in_complex_iterator edges_in_complex_end(const Curve_index& = Curve_index()) const + { + return CGAL::filter_iterator(this->triangulation().finite_edges_end(), + Edge_iterator_not_in_complex(*this)); + } + + /// Returns a `Vertices_in_complex_iterator` to the first vertex of the 0D complex + Vertices_in_complex_iterator vertices_in_complex_begin() const + { + return CGAL::filter_iterator(corners_.end(), + Vertex_iterator_not_in_complex(*this), + corners_.begin()); + } + + /// Returns a `Vertices_in_complex_iterator` to the first vertex of the 0D complex + Vertices_in_complex_iterator + vertices_in_complex_begin(const Corner_index& index) const + { + return CGAL::filter_iterator(corners_.end(), + Vertex_iterator_not_in_complex(*this,index), + corners_.begin()); + } + + /// Returns past-the-end iterator on vertices of the 0D complex + Vertices_in_complex_iterator vertices_in_complex_end() const + { + return CGAL::filter_iterator(corners_.end(), + Vertex_iterator_not_in_complex(*this)); + } + + /*! + returns a range of iterators over vertices of the 0D complex + \note The value type of `Vertices_in_complex::iterator` is `Vertex_handle`. + */ + Vertices_in_complex vertices_in_complex() const + { + return make_prevent_deref_range(vertices_in_complex_begin(), + vertices_in_complex_end()); + } + /*! + returns a range of iterators over the edges of the 1D complex, + starting at an arbitrary edge. + Returns an empty range when `t.dimension() < 2`. + */ + Edges_in_complex edges_in_complex() const + { + return make_prevent_deref_range(edges_in_complex_begin(), + edges_in_complex_end()); + } + /*! + returns a range of iterators over the facets of the 2D complex, + starting at an arbitrary facet. + Returns an empty range when `t.dimension() < 2`. + */ + Facets_in_complex facets_in_complex() const + { + return make_prevent_deref_range(facets_in_complex_begin(), + facets_in_complex_end()); + } + /*! + returns a range of iterators over cells of the 3D complex. + Returns an empty range when `triangulation().number_of_cells() == 0` + or complex is empty. + \note The value type of `Cells_in_complex::iterator` is `Cell_handle`. + */ + Cells_in_complex cells_in_complex() const + { + return make_prevent_deref_range(cells_in_complex_begin(), + cells_in_complex_end()); + } +/// @} + +public: + template + friend + std::istream& operator>>(std::istream& is, + Mesh_complex_3_in_triangulation_3& c3t3); + + static std::string io_signature() + { + return Get_io_signature()(); + } + + /** + * @cond SKIP_IN_MANUAL + * Creates an Internal_edge object (i.e a pair of ordered Vertex_handle) + * @endcond + */ + Internal_edge make_internal_edge(const Vertex_handle& v1, + const Vertex_handle& v2) const + { + if ( v1 < v2 ) { return Internal_edge(v1,v2); } + else { return Internal_edge(v2,v1); } + } + + /** + * @cond SKIP_IN_MANUAL + * Returns true if \c edge is in C3T3 + * @endcond + */ + bool is_in_complex(const Internal_edge& edge) const + { + return (curve_index(edge) != Curve_index() ); + } + + /** + * @cond SKIP_IN_MANUAL + * Add edge \c edge to complex, with `Curve_index` `index` + * @endcond + */ + void add_to_complex(const Internal_edge& edge, const Curve_index& index) + { + CGAL_precondition(!is_in_complex(edge)); +#if CGAL_MESH_3_PROTECTION_DEBUG & 1 + std::cerr << "Add edge ( " << disp_vert(edge.left) + << " , " << disp_vert(edge.right) << " ), curve_index=" << index + << " to c3t3.\n"; +#endif // CGAL_MESH_3_PROTECTION_DEBUG + std::pair it = edges_.insert(edge); + it.first->info = index; + } + + /** + * @cond SKIP_IN_MANUAL + * Remove edge \c edge from complex + * @endcond + */ + void remove_from_complex(const Internal_edge& edge) + { + edges_.erase(edge); + } + + /** + * @cond SKIP_IN_MANUAL + * Returns Curve_index of edge \c edge + * @endcond + */ + Curve_index curve_index(const Internal_edge& edge) const + { + typename Edge_map::const_iterator it = edges_.find(edge); + if ( edges_.end() != it ) { return it->info; } + return Curve_index(); + } + + /// @cond SKIP_IN_MANUAL + /// Returns `NOT_IN_COMPLEX`, `BOUNDARY`, `REGULAR`, or `SINGULAR`, + /// depending on the number of incident facets in the complex, and the + /// number of connected components of its link + /// @endcond + Face_status face_status(const Vertex_handle v) const + { + if (!manifold_info_initialized_) init_manifold_info(); + const std::size_t n = v->cached_number_of_incident_facets(); + + if (n == 0) return NOT_IN_COMPLEX; + + //test incident edges for REGULARITY and count BOUNDARY edges + typename std::vector edges; + edges.reserve(64); + if (tr_.is_parallel()) { + tr_.incident_edges_threadsafe(v, std::back_inserter(edges)); + } + else { + tr_.incident_edges(v, std::back_inserter(edges)); + } + int number_of_boundary_incident_edges = 0; // could be a bool + for (typename std::vector::iterator + eit = edges.begin(), end = edges.end(); + eit != end; eit++) + { + switch (face_status(*eit)) + { + case NOT_IN_COMPLEX: case REGULAR: break; + case BOUNDARY: ++number_of_boundary_incident_edges; break; + default: +#ifdef CGAL_MESHES_DEBUG_REFINEMENT_POINTS + std::cerr << "singular edge...\n"; + std::cerr << tr_.point(v) << std::endl; +#endif // CGAL_MESHES_DEBUG_REFINEMENT_POINTS + return SINGULAR; + } + } + + // From here all incident edges (in complex) are REGULAR or BOUNDARY. + const std::size_t nb_components = union_find_of_incident_facets(v); + if (nb_components > 1) { +#ifdef CGAL_MESHES_DEBUG_REFINEMENT_POINTS + std::cerr << "singular vertex: nb_components=" << nb_components << std::endl; + std::cerr << tr_.point(v) << std::endl; +#endif // CGAL_MESHES_DEBUG_REFINEMENT_POINTS + return SINGULAR; + } + else { // REGULAR OR BOUNDARY +#ifdef CGAL_MESHES_DEBUG_REFINEMENT_POINTS + std::cerr << "regular or boundary: " << tr_.point(v) << std::endl; +#endif // CGAL_MESHES_DEBUG_REFINEMENT_POINTS + if (number_of_boundary_incident_edges != 0) + return BOUNDARY; + else + return REGULAR; + } + } + + /// @cond SKIP_IN_MANUAL + /// This function should be called only when incident edges + /// are known to be REGULAR OR BOUNDARY + /// @endcond + bool is_regular_or_boundary_for_vertices(Vertex_handle v) const { + return union_find_of_incident_facets(v) == 1; + } + + /// @cond SKIP_IN_MANUAL + /// Returns `NOT_IN_COMPLEX`, `BOUNDARY`, `REGULAR`, or `SINGULAR`, + /// depending on the number of incident facets in the complex + /// @endcond + Face_status face_status(const Edge& edge) const + { + if (!manifold_info_initialized_) init_manifold_info(); + +#ifdef CGAL_LINKED_WITH_TBB + typename Edge_facet_counter::const_accessor accessor; + if (!edge_facet_counter_.find(accessor, + this->make_ordered_pair(edge))) + return NOT_IN_COMPLEX; + switch (accessor->second) +#else // not CGAL_LINKED_WITH_TBB + switch (edge_facet_counter_[this->make_ordered_pair(edge)]) +#endif // not CGAL_LINKED_WITH_TBB + { + case 0: return NOT_IN_COMPLEX; + case 1: return BOUNDARY; + case 2: return REGULAR; + default: return SINGULAR; + } + } + + /// Returns true if the vertex \c v has is incident to at least a facet + /// of the complex + bool has_incident_facets_in_complex(const Vertex_handle& v) const + { + if (!manifold_info_initialized_) init_manifold_info(); + return v->cached_number_of_incident_facets() > 0; + } + + /** + * @cond SKIP_IN_MANUAL + * @brief insert \c [first,last[ in the triangulation (with dimension 2) + * @param first the iterator on the first point to insert + * @param last the iterator past the last point to insert + * + * InputIterator value type must be \c std::pair + * @endcond + */ + template + void insert_surface_points(InputIterator first, InputIterator last) + { + typename Tr::Geom_traits::Construct_weighted_point_3 cwp = + tr_.geom_traits().construct_weighted_point_3_object(); + + while (first != last) + { + Vertex_handle vertex = tr_.insert(cwp((*first).first)); + vertex->set_index((*first).second); + vertex->set_dimension(2); + ++first; + } + } + + /** + * @cond SKIP_IN_MANUAL + * @brief insert \c [first,last[ in the triangulation (with dimension 2 and + * index \c default_index) + * @param first the iterator on the first point to insert + * @param last the iterator past the last point to insert + * @param default_index the index to be used to insert points + * + * InputIterator value type must be \c Tr::Point + * @endcond + */ + template + void insert_surface_points(InputIterator first, + InputIterator last, + const Index& default_index) + { + typename Tr::Geom_traits::Construct_weighted_point_3 cwp = + tr_.geom_traits().construct_weighted_point_3_object(); + + while (first != last) + { + Vertex_handle vertex = tr_.insert(cwp(*first)); + vertex->set_index(default_index); + vertex->set_dimension(2); + ++first; + } + } + + void clear_cells_and_facets_from_c3t3() { + for (typename Tr::Finite_cells_iterator + cit = this->triangulation().finite_cells_begin(), + end = this->triangulation().finite_cells_end(); + cit != end; ++cit) + { + set_subdomain_index(cit, Subdomain_index()); + } + this->number_of_cells_ = 0; + for (typename Tr::Finite_facets_iterator + fit = this->triangulation().finite_facets_begin(), + end = this->triangulation().finite_facets_end(); + fit != end; ++fit) + { + Facet facet = *fit; + set_surface_patch_index(facet.first, facet.second, Surface_patch_index()); + if (this->triangulation().dimension() > 2) { + Facet mirror = tr_.mirror_facet(facet); + set_surface_patch_index(mirror.first, mirror.second, Surface_patch_index()); + } + } + this->number_of_facets_ = 0; + clear_manifold_info(); + } + + void clear_manifold_info() { + edge_facet_counter_.clear(); + manifold_info_initialized_ = false; + } + + /** @cond SKIP_IN_MANUAL + * Returns bbox + * @endcond + */ + Bbox_3 bbox() const; + +private: + // Sequential: non-atomic + // "dummy" is here to allow the specialization (see below) + // See http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/285ab1eec49e1cb6 + template + struct Number_of_elements + { + typedef size_type type; + }; + + template + struct Init_number_of_elements + { + template + void operator()(T& a, const T& b) + { + a = b; + } + template + void operator()(T& a) + { + a = 0; + } + }; + + template + struct Swap_elements + { + template + void operator()(T& a, T& b) + { + std::swap(a, b); + } + }; +#ifdef CGAL_LINKED_WITH_TBB + // Parallel: atomic + template + struct Number_of_elements + { + typedef std::atomic type; + }; + + template + struct Init_number_of_elements + { + template + void operator()(T& a, const T& b) + { + a = b.load(); + } + template + void operator()(T& a) + { + a = 0; + } + }; + + template + struct Swap_elements + { + template + void operator()(T& a, T& b) + { + T tmp; + tmp.exchange(a); + a.exchange(b); + b.exchange(tmp); + } + }; +#endif // CGAL_LINKED_WITH_TBB + +private: + void init_manifold_info() const + { + for (typename Tr::All_vertices_iterator + vit = triangulation().finite_vertices_begin(), + end = triangulation().finite_vertices_end(); + vit != end; ++vit) + { + vit->set_c2t3_cache(0, (std::numeric_limits::max)()); + } + + edge_facet_counter_.clear(); + + for (typename Tr::Finite_facets_iterator + fit = triangulation().finite_facets_begin(), + end = triangulation().finite_facets_end(); + fit != end; ++fit) + { + if (is_in_complex(*fit)) { + const Cell_handle cell = fit->first; + const int i = fit->second; + for (int j = 0; j < 3; ++j) + { + const int edge_index_va = tr_.vertex_triple_index(i, j); + const int edge_index_vb = tr_.vertex_triple_index(i, (j == 2) ? 0 : (j + 1)); + const Vertex_handle edge_va = cell->vertex(edge_index_va); + const Vertex_handle edge_vb = cell->vertex(edge_index_vb); +#ifndef CGAL_LINKED_WITH_TBB + ++edge_facet_counter_[this->make_ordered_pair(edge_va, edge_vb)]; +#else // CGAL_LINKED_WITH_TBB + { + typename Edge_facet_counter::accessor accessor; + edge_facet_counter_.insert(accessor, + this->make_ordered_pair(edge_va, edge_vb)); + ++accessor->second; + } +#endif // CGAL_LINKED_WITH_TBB + + const std::size_t n = edge_va->cached_number_of_incident_facets(); + edge_va->set_c2t3_cache(n + 1, (std::numeric_limits::max)()); + } + } + } + manifold_info_initialized_ = true; + } + + /// Extract the subset `F` of facets of the complex incident to `v` and + /// return the number of connected component of the adjacency graph of `F`. + std::size_t union_find_of_incident_facets(const Vertex_handle v) const + { + if (v->is_c2t3_cache_valid()) + { + const std::size_t n = v->cached_number_of_components(); + if (n != (std::numeric_limits::max)()) return n; + } + + Union_find facets; + { // fill the union find + std::vector non_filtered_facets; + if (tr_.is_parallel()) { + tr_.incident_facets_threadsafe(v, std::back_inserter(non_filtered_facets)); + } + else { + tr_.incident_facets(v, std::back_inserter(non_filtered_facets)); + } + + for (typename std::vector::iterator + fit = non_filtered_facets.begin(), + end = non_filtered_facets.end(); + fit != end; ++fit) + { + if (is_in_complex(*fit)) facets.push_back(*fit); + } + } + + typedef boost::unordered_map::handle, + Hash_fct> Vertex_set_map; + typedef typename Vertex_set_map::iterator Vertex_set_map_iterator; + + Vertex_set_map vsmap; + + for (typename Union_find::iterator + it = facets.begin(), end = facets.end(); + it != end; ++it) + { + const Cell_handle& ch = (*it).first; + const int& i = (*it).second; + for (int j = 0; j < 3; ++j) { + const Vertex_handle w = ch->vertex(tr_.vertex_triple_index(i, j)); + if (w != v) { + Vertex_set_map_iterator vsm_it = vsmap.find(w); + if (vsm_it != vsmap.end()) { + facets.unify_sets(vsm_it->second, it); + } + else { + vsmap.insert(std::make_pair(w, it)); + } + } + } + } + const std::size_t nb_components = facets.number_of_sets(); + + const std::size_t n = v->cached_number_of_incident_facets(); + v->set_c2t3_cache(n, nb_components); + return nb_components; + } + +public: + // ----------------------------------- + // Backward Compatibility + // ----------------------------------- +#ifndef DOXYGEN_RUNNING +#ifndef CGAL_MESH_3_NO_DEPRECATED_SURFACE_INDEX + typedef Surface_patch_index Surface_index; + + void set_surface_index(const Facet& f, const Surface_index& index) + { + set_surface_patch_index(f, index); + } + + void set_surface_index(const Cell_handle& c, const int i, const Surface_index& index) + { + set_surface_patch_index(c, i, index); + } + + Surface_index surface_index(const Facet& f) const + { + return surface_patch_index(f); + } + + Surface_index surface_index(const Cell_handle& c, const int i) const + { + return surface_patch_index(c, i); + } +#endif // CGAL_MESH_3_NO_DEPRECATED_SURFACE_INDEX + +#ifndef CGAL_MESH_3_NO_DEPRECATED_C3T3_ITERATORS + typedef Facets_in_complex_iterator Facet_iterator; + typedef Cells_in_complex_iterator Cell_iterator; + + Facet_iterator facets_begin() const + { + return facets_in_complex_begin(); + } + + Facet_iterator facets_end() const + { + return facets_in_complex_end(); + } + + Cell_iterator cells_begin() const + { + return cells_in_complex_begin(); + } + + Cell_iterator cells_end() const + { + return cells_in_complex_end(); + } +#endif // CGAL_MESH_3_NO_DEPRECATED_C3T3_ITERATORS +#endif // DOXYGEN_RUNNING + // ----------------------------------- + // End backward Compatibility + // ----------------------------------- + + +private: + // Private data members + Triangulation tr_; + + typedef typename Base::Pair_of_vertices Pair_of_vertices; +#ifdef CGAL_LINKED_WITH_TBB + typedef tbb::concurrent_hash_map Edge_facet_counter; +#else // not CGAL_LINKED_WITH_TBB + typedef std::map Edge_facet_counter; +#endif // not CGAL_LINKED_WITH_TBB + + mutable Edge_facet_counter edge_facet_counter_; + + typename Number_of_elements::type number_of_facets_; + typename Number_of_elements::type number_of_cells_; + + mutable bool manifold_info_initialized_; + + Edge_map edges_; + Corner_map corners_; + Far_vertices_vec far_vertices_; +}; + +template +Mesh_complex_3_in_triangulation_3:: +Mesh_complex_3_in_triangulation_3() + : Base() + , tr_() + , edge_facet_counter_() //TODO: parallel! + , manifold_info_initialized_(false) //TODO: parallel! +{ + // We don't put it in the initialization list because + // std::atomic has no contructors + number_of_facets_ = 0; + number_of_cells_ = 0; +} + +template +Mesh_complex_3_in_triangulation_3:: +Mesh_complex_3_in_triangulation_3(const Self& rhs) + : Base(rhs) + , tr_(rhs.tr_) + , edge_facet_counter_(rhs.edge_facet_counter_) + , manifold_info_initialized_(rhs.manifold_info_initialized_) + , edges_() + , corners_() +{ + Init_number_of_elements init; + init(number_of_facets_, rhs.number_of_facets_); + init(number_of_cells_, rhs.number_of_cells_); + + // Copy edges + for ( typename Edge_map::const_iterator it = rhs.edges_.begin(), + end = rhs.edges_.end() ; it != end ; ++it ) + { + const Vertex_handle& va = it->right; + const Vertex_handle& vb = it->left; + + Vertex_handle new_va; + this->triangulation().is_vertex(rhs.triangulation().point(va), new_va); + + Vertex_handle new_vb; + this->triangulation().is_vertex(rhs.triangulation().point(vb), new_vb); + + this->add_to_complex(make_internal_edge(new_va,new_vb), it->info); + } + + // Copy corners + for ( typename Corner_map::const_iterator it = rhs.corners_.begin(), + end = rhs.corners_.end() ; it != end ; ++it ) + { + Vertex_handle new_v; + this->triangulation().is_vertex(rhs.triangulation().point(it->first), new_v); + this->add_to_complex(new_v, it->second); + } + + // Parse vertices to identify far vertices + if (rhs.far_vertices_.size() > 0) + { + Triangulation &tr = triangulation(); + typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(); + for(typename Tr::Finite_vertices_iterator end = tr.finite_vertices_end(); + vit != end ; ++vit) + { + if (vit->in_dimension() == -1) + far_vertices_.push_back(vit); + } + CGAL_assertion(far_vertices_.size() == rhs.far_vertices_.size()); + } +} + +template +Mesh_complex_3_in_triangulation_3:: +Mesh_complex_3_in_triangulation_3(Self&& rhs) + : Base() + , tr_(std::move(rhs.tr_)) + , edge_facet_counter_(std::move(rhs.edge_facet_counter_)) + , manifold_info_initialized_(std::exchange(rhs.manifold_info_initialized_, false)) + , edges_(std::move(rhs.edges_)) + , corners_(std::move(rhs.corners_)) + , far_vertices_(std::move(rhs.far_vertices_)) +{ + Init_number_of_elements init; + init(number_of_facets_, rhs.number_of_facets_); + init(number_of_cells_, rhs.number_of_cells_); + init(rhs.number_of_facets_); // set to 0 + init(rhs.number_of_cells_); // set to 0 +} + +template +template +OutputIterator +Mesh_complex_3_in_triangulation_3:: +adjacent_vertices_in_complex(const Vertex_handle& v, OutputIterator out) const +{ + CGAL_precondition(v->in_dimension() < 2); + + typedef typename Edge_map::right_const_iterator Rcit; + typedef typename Edge_map::left_const_iterator Lcit; + + // Add edges containing v is on the left + std::pair range_right = edges_.right.equal_range(v); + for ( Rcit rit = range_right.first ; rit != range_right.second ; ++rit ) + { + *out++ = std::make_pair(rit->second, rit->info); + } + + // Add edges containing v on the right + std::pair range_left = edges_.left.equal_range(v); + for ( Lcit lit = range_left.first ; lit != range_left.second ; ++lit ) + { + *out++ = std::make_pair(lit->second, lit->info); + } + + return out; +} + + +template +bool +Mesh_complex_3_in_triangulation_3:: +is_valid(bool verbose) const +{ + typedef typename Tr::Weighted_point Weighted_point; + typedef boost::unordered_map Vertex_map; + + Vertex_map vertex_map; + + // Fill map counting neighbor number for each vertex of an edge + for ( typename Edge_map::const_iterator it = edges_.begin(), + end = edges_.end() ; it != end ; ++it ) + { + const Vertex_handle& v1 = it->right; + if ( vertex_map.find(v1) == vertex_map.end() ) { vertex_map[v1] = 1; } + else { vertex_map[v1] += 1; } + + const Vertex_handle& v2 = it->left; + if ( vertex_map.find(v2) == vertex_map.end() ) { vertex_map[v2] = 1; } + else { vertex_map[v2] += 1; } + } + + // Verify that each vertex has 2 neighbors if it's not a corner + for ( typename Vertex_map::iterator vit = vertex_map.begin(), + vend = vertex_map.end() ; vit != vend ; ++vit ) + { + if ( vit->first->in_dimension() != 0 && vit->second != 2 ) + { + if(verbose) + std::cerr << "Validity error: vertex " << (void*)(&*vit->first) + << " (" << this->triangulation().point(vit->first) << ") " + << "is not a corner (dimension " << vit->first->in_dimension() + << ") but has " << vit->second << " neighbor(s)!\n"; + return false; + } + } + + // Verify that balls of each edge intersect + for ( typename Edge_map::const_iterator it = edges_.begin(), + end = edges_.end() ; it != end ; ++it ) + { + typename Tr::Geom_traits::Compute_weight_3 cw = + this->triangulation().geom_traits().compute_weight_3_object(); + typename Tr::Geom_traits::Construct_point_3 cp = + this->triangulation().geom_traits().construct_point_3_object(); + typename Tr::Geom_traits::Construct_sphere_3 sphere = + this->triangulation().geom_traits().construct_sphere_3_object(); + typename Tr::Geom_traits::Do_intersect_3 do_intersect = + this->triangulation().geom_traits().do_intersect_3_object(); + + const Weighted_point& itrwp = this->triangulation().point(it->right); + const Weighted_point& itlwp = this->triangulation().point(it->left); + + if ( ! do_intersect(sphere(cp(itrwp), cw(itrwp)), sphere(cp(itlwp), cw(itlwp))) ) + { + std::cerr << "Points p[" << disp_vert(it->right) << "], dim=" << it->right->in_dimension() + << " and q[" << disp_vert(it->left) << "], dim=" << it->left->in_dimension() + << " form an edge but do not intersect !\n"; + return false; + } + } + + return true; +} + +template +void +Mesh_complex_3_in_triangulation_3:: +add_to_complex(const Cell_handle& cell, + const int i, + const Surface_patch_index& index) +{ + CGAL_precondition(!(index == Surface_patch_index())); + + if (!is_in_complex(cell, i)) + { + Facet mirror = tr_.mirror_facet(std::make_pair(cell, i)); + set_surface_patch_index(cell, i, index); + set_surface_patch_index(mirror.first, mirror.second, index); + ++number_of_facets_; + if (manifold_info_initialized_) { + for (int j = 0; j < 3; ++j) + { + int edge_index_va = tr_.vertex_triple_index(i, j); + int edge_index_vb = tr_.vertex_triple_index(i, (j == 2) ? 0 : (j + 1)); + Vertex_handle edge_va = cell->vertex(edge_index_va); + Vertex_handle edge_vb = cell->vertex(edge_index_vb); +#ifdef CGAL_LINKED_WITH_TBB + { + typename Edge_facet_counter::accessor accessor; + edge_facet_counter_.insert(accessor, + this->make_ordered_pair(edge_va, edge_vb)); + ++accessor->second; + } +#else // not CGAL_LINKED_WITH_TBB + ++edge_facet_counter_[this->make_ordered_pair(edge_va, edge_vb)]; +#endif // not CGAL_LINKED_WITH_TBB + + const std::size_t n = edge_va->cached_number_of_incident_facets(); + const std::size_t m = edge_va->cached_number_of_components(); + edge_va->set_c2t3_cache(n + 1, m); + } + const int dimension_plus_1 = tr_.dimension() + 1; + // update c2t3 for vertices of f + for (int j = 0; j < dimension_plus_1; j++) { + if (j != i) { +#ifdef CGAL_MESHES_DEBUG_REFINEMENT_POINTS + if (cell->vertex(j)->is_c2t3_cache_valid()) + std::cerr << "(" << tr_.point(cell, j) << ")->invalidate_c2t3_cache()\n"; +#endif // CGAL_MESHES_DEBUG_REFINEMENT_POINTS + cell->vertex(j)->invalidate_c2t3_cache(); + } + } + } + } +} + +template +void +Mesh_complex_3_in_triangulation_3:: +remove_from_complex(const Facet& facet) +{ + if (is_in_complex(facet)) + { + Facet mirror = tr_.mirror_facet(facet); + set_surface_patch_index(facet.first, facet.second, Surface_patch_index()); + set_surface_patch_index(mirror.first, mirror.second, Surface_patch_index()); + --number_of_facets_; + if (manifold_info_initialized_) { + const Cell_handle cell = facet.first; + const int i = facet.second; + for (int j = 0; j < 3; ++j) + { + const int edge_index_va = tr_.vertex_triple_index(i, j); + const int edge_index_vb = tr_.vertex_triple_index(i, (j == 2) ? 0 : (j + 1)); + const Vertex_handle edge_va = cell->vertex(edge_index_va); + const Vertex_handle edge_vb = cell->vertex(edge_index_vb); +#ifdef CGAL_LINKED_WITH_TBB + { + typename Edge_facet_counter::accessor accessor; + edge_facet_counter_.insert(accessor, + this->make_ordered_pair(edge_va, edge_vb)); + --accessor->second; + } +#else // not CGAL_LINKED_WITH_TBB + --edge_facet_counter_[this->make_ordered_pair(edge_va, edge_vb)]; +#endif // not CGAL_LINKED_WITH_TBB + + const std::size_t n = edge_va->cached_number_of_incident_facets(); + CGAL_assertion(n > 0); + const std::size_t m = edge_va->cached_number_of_components(); + edge_va->set_c2t3_cache(n - 1, m); + } + const int dimension_plus_1 = tr_.dimension() + 1; + // update c2t3 for vertices of f + for (int j = 0; j < dimension_plus_1; j++) { + if (j != facet.second) { +#ifdef CGAL_MESHES_DEBUG_REFINEMENT_POINTS + if (cell->vertex(j)->is_c2t3_cache_valid()) + std::cerr << "(" << tr_.point(cell, j) << ")->invalidate_c2t3_cache()\n"; +#endif // CGAL_MESHES_DEBUG_REFINEMENT_POINTS + cell->vertex(j)->invalidate_c2t3_cache(); + } + } + } + } +} + +template +Bbox_3 +Mesh_complex_3_in_triangulation_3:: +bbox() const +{ + if (0 == triangulation().number_of_vertices()) + { + return Bbox_3(); + } + + typename Tr::Finite_vertices_iterator vit = tr_.finite_vertices_begin(); + Bbox_3 result = tr_.point(vit++).bbox(); + + for (typename Tr::Finite_vertices_iterator end = tr_.finite_vertices_end(); + vit != end; ++vit) + { + result = result + tr_.point(vit).bbox(); + } + + return result; +} + +template +void +Mesh_complex_3_in_triangulation_3:: +rescan_after_load_of_triangulation() +{ + corners_.clear(); + for(typename Tr::Finite_vertices_iterator + vit = this->triangulation().finite_vertices_begin(), + end = this->triangulation().finite_vertices_end(); + vit != end; ++vit) + { + if ( vit->in_dimension() == 0 ) { + add_to_complex(vit, Corner_index(1)); + } + } + + this->number_of_facets_ = 0; + for (typename Tr::Finite_facets_iterator + fit = this->triangulation().finite_facets_begin(), + end = this->triangulation().finite_facets_end(); + fit != end; ++fit) + { + if (this->is_in_complex(*fit)) { + ++this->number_of_facets_; + } + } + + this->number_of_cells_ = 0; + for (typename Tr::Finite_cells_iterator + cit = this->triangulation().finite_cells_begin(), + end = this->triangulation().finite_cells_end(); + cit != end; ++cit) + { + if (this->is_in_complex(cit)) { + ++this->number_of_cells_; + } + } +} + +template +std::ostream & +operator<< (std::ostream& os, + const Mesh_complex_3_in_triangulation_3 &c3t3) +{ + // TODO: implement edge saving + typedef typename Mesh_complex_3_in_triangulation_3::Concurrency_tag Concurrency_tag; + return os << c3t3.triangulation(); +} + + +template +std::istream & +operator>> (std::istream& is, + Mesh_complex_3_in_triangulation_3 &c3t3) +{ + // TODO: implement edge loading + c3t3.clear(); + is >> c3t3.triangulation(); + + if (!is) { + c3t3.clear(); + return is; + } + + c3t3.rescan_after_load_of_triangulation(); + return is; +} + +} //namespace CGAL + +#include + +#endif // CGAL_MESH_COMPLEX_3_IN_TRIANGULATION_3_H diff --git a/MDS_3/include/CGAL/facets_in_complex_3_to_triangle_mesh.h b/MDS_3/include/CGAL/facets_in_complex_3_to_triangle_mesh.h new file mode 100644 index 00000000000..052c0585767 --- /dev/null +++ b/MDS_3/include/CGAL/facets_in_complex_3_to_triangle_mesh.h @@ -0,0 +1,245 @@ +// Copyright (c) 2009-2017 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Maxime Gimeno, +// Mael Rouxel-Labbé + +#ifndef CGAL_FACETS_IN_COMPLEX_3_TO_TRIANGLE_MESH_H +#define CGAL_FACETS_IN_COMPLEX_3_TO_TRIANGLE_MESH_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace CGAL { + +namespace MDS_3 { + +namespace internal { + +template +void resize(Polygon& p, std::size_t size) +{ + p.resize(size); +} + +template +void resize(std::array&, std::size_t CGAL_assertion_code(size)) +{ + CGAL_assertion(size == N); +} + +template +void facets_in_complex_3_to_triangle_soup(const C3T3& c3t3, + const typename C3T3::Subdomain_index sd_index, + PointContainer& points, + FaceContainer& faces, + PatchIndexContainer& patches, + const bool normals_point_outside_of_the_subdomain = true, + const bool export_all_facets = false) +{ + typedef typename PointContainer::value_type Point_3; + typedef typename FaceContainer::value_type Face; + + typedef typename C3T3::Triangulation Tr; + typedef typename C3T3::Surface_patch_index Surface_patch_index; + + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Weighted_point Weighted_point; + + typedef typename C3T3::Facets_in_complex_iterator Ficit; + + typedef CGAL::Hash_handles_with_or_without_timestamps Hash_fct; + typedef boost::unordered_map VHmap; + + typedef typename C3T3::size_type size_type; + + size_type nf = c3t3.number_of_facets_in_complex(); + faces.reserve(faces.size() + nf); + patches.reserve(faces.size() + nf); + points.reserve(points.size() + nf/2); // approximating Euler + + VHmap vh_to_ids; + std::size_t inum = 0; + + for(Ficit fit = c3t3.facets_in_complex_begin(), + end = c3t3.facets_in_complex_end(); fit != end; ++fit) + { + Cell_handle c = fit->first; + int s = fit->second; + const Surface_patch_index spi = c->surface_patch_index(s); + Face f; + resize(f, 3); + + typename C3T3::Subdomain_index cell_sdi = c3t3.subdomain_index(c); + typename C3T3::Subdomain_index opp_sdi = c3t3.subdomain_index(c->neighbor(s)); + + if(!export_all_facets && cell_sdi != sd_index && opp_sdi != sd_index) + continue; + + for(std::size_t i=1; i<4; ++i) + { + typename VHmap::iterator map_entry; + bool is_new; + Vertex_handle v = c->vertex((s+i)&3); + CGAL_assertion(v != Vertex_handle() && !c3t3.triangulation().is_infinite(v)); + + boost::tie(map_entry, is_new) = vh_to_ids.insert(std::make_pair(v, inum)); + if(is_new) + { + const Weighted_point& p = c3t3.triangulation().point(c, (s+i)&3); + const Point_3 bp = Point_3(CGAL::to_double(p.x()), + CGAL::to_double(p.y()), + CGAL::to_double(p.z())); + points.push_back(bp); + ++inum; + } + + f[i-1] = map_entry->second; + } + + if(export_all_facets) + { + if((cell_sdi > opp_sdi) == (s%2 == 1)) + std::swap(f[0], f[1]); + } + else + { + if(((cell_sdi == sd_index) == (s%2 == 1)) == normals_point_outside_of_the_subdomain) + std::swap(f[0], f[1]); + } + + faces.push_back(f); + patches.push_back(spi); + } +} + +template +void facets_in_complex_3_to_triangle_soup(const C3T3& c3t3, + PointContainer& points, + FaceContainer& faces, + SurfacePatchContainer& patches) +{ + typedef typename C3T3::Subdomain_index Subdomain_index; + Subdomain_index useless = Subdomain_index(); + facets_in_complex_3_to_triangle_soup(c3t3, useless, points, faces, patches, + true/*point outward*/, true /*extract all facets*/); +} + +template +void set_face_patches(const Index2FaceMap&, + const SurfacePatchRange&, + const internal_np::Param_not_found&) +{ + return; +} + +template +void set_face_patches(const Index2FaceMap& i2f, + const SurfacePatchRange& patches, + const FacePatchMap& fpmap) +{ + for (auto index_and_face : i2f) + { + put(fpmap, index_and_face.second, patches[index_and_face.first]); + } +} + +} // end namespace internal + +} // end namespace MDS_3 + + /** + * @ingroup PkgMDS3Functions + * + * @brief builds a `TriangleMesh` from the surface facets, with a consistent orientation at the interface of two subdomains. + * + * This function exports the surface as a `TriangleMesh` and appends it to `graph`, using `orient_polygon_soup()`. + * + * @tparam C3T3 a model of `MeshComplexWithFeatures_3InTriangulation_3`. + * @tparam TriangleMesh a model of `MutableFaceGraph` with an internal point property map. The point type should be compatible with the one used in `C3T3`. + * @tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" + * + * @param c3t3 an instance of `C3T3`. + * @param graph an instance of `TriangleMesh`. + * @param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below + * + * \cgalNamedParamsBegin + * \cgalParamNBegin{face_patch_map} + * \cgalParamDescription{a property map with the patch id's associated to the faces of `faces(graph)`} + * \cgalParamType{a class model of `ReadWritePropertyMap` with `boost::graph_traits::%face_descriptor` + * as key type and the desired property, model of `CopyConstructible` and `LessThanComparable` as value type.} + * \cgalParamDefault{If not provided, faces patch ids are ignored.} + * \cgalParamExtra{The map is updated during the remeshing process while new faces are created.} + * \cgalParamNEnd + * \cgalNamedParamsEnd + */ + template + void facets_in_complex_3_to_triangle_mesh(const C3T3& c3t3, + TriangleMesh& graph, + const NamedParameters& np) + { + namespace PMP = CGAL::Polygon_mesh_processing; + + typedef typename boost::property_map::type VertexPointMap; + typedef typename boost::property_traits::value_type Point_3; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename C3T3::Surface_patch_index Surface_patch_index; + + typedef std::array Face; + + std::vector faces; + std::vector patches; + std::vector points; + + MDS_3::internal::facets_in_complex_3_to_triangle_soup(c3t3, points, faces, patches); + + if (!PMP::is_polygon_soup_a_polygon_mesh(faces)) + PMP::orient_polygon_soup(points, faces); + CGAL_postcondition(PMP::is_polygon_soup_a_polygon_mesh(faces)); + + boost::unordered_map i2f; + PMP::polygon_soup_to_polygon_mesh(points, faces, graph, + CGAL::parameters::polygon_to_face_output_iterator(std::inserter(i2f, i2f.end()))); + + using parameters::choose_parameter; + using parameters::get_parameter; + + MDS_3::internal::set_face_patches(i2f, + patches, + get_parameter(np, internal_np::face_patch)); + } + + template + void facets_in_complex_3_to_triangle_mesh(const C3T3& c3t3, TriangleMesh& graph) + { + facets_in_complex_3_to_triangle_mesh(c3t3, graph, parameters::all_default()); + } + +} // namespace CGAL + +#endif // CGAL_FACETS_IN_COMPLEX_3_TO_TRIANGLE_MESH_H diff --git a/Mesh_3/include/CGAL/internal/Mesh_3/Boundary_of_subdomain_of_complex_3_in_triangulation_3_to_off.h b/MDS_3/include/CGAL/internal/MDS_3/Boundary_of_subdomain_of_complex_3_in_triangulation_3_to_off.h similarity index 81% rename from Mesh_3/include/CGAL/internal/Mesh_3/Boundary_of_subdomain_of_complex_3_in_triangulation_3_to_off.h rename to MDS_3/include/CGAL/internal/MDS_3/Boundary_of_subdomain_of_complex_3_in_triangulation_3_to_off.h index 93f5b70d430..22ad3eaffd7 100644 --- a/Mesh_3/include/CGAL/internal/Mesh_3/Boundary_of_subdomain_of_complex_3_in_triangulation_3_to_off.h +++ b/MDS_3/include/CGAL/internal/MDS_3/Boundary_of_subdomain_of_complex_3_in_triangulation_3_to_off.h @@ -12,7 +12,7 @@ #ifndef CGAL_INTERNAL_MESH_3_BOUNDARY_OF_SUDDOMAIN_OF_COMPLEX_3_IN_TRIANGULATION_3_TO_OFF_H #define CGAL_INTERNAL_MESH_3_BOUNDARY_OF_SUDDOMAIN_OF_COMPLEX_3_IN_TRIANGULATION_3_TO_OFF_H -#include +#include #include @@ -58,11 +58,14 @@ output_boundary_of_c3t3_to_off(const C3T3& c3t3, { typedef typename C3T3::Triangulation::Geom_traits::Point_3 Point; typedef std::vector Face; + typedef typename C3T3::Surface_patch_index Surface_patch_index; std::vector points; std::vector faces; + std::vector patches; - CGAL::Mesh_3::internal::facets_in_complex_3_to_triangle_soup(c3t3, sd_index, points, faces, normals_point_outside_of_the_subdomain); + CGAL::MDS_3::internal::facets_in_complex_3_to_triangle_soup(c3t3, sd_index, points, faces, + patches, normals_point_outside_of_the_subdomain); return output_polygon_soup_to_off(points, faces, out); } @@ -73,12 +76,14 @@ output_facets_in_complex_to_off(const C3T3& c3t3, std::ostream& out) { typedef typename C3T3::Triangulation::Geom_traits::Point_3 Point; + typedef typename C3T3::Surface_patch_index Surface_patch_index; typedef std::vector Face; std::vector points; std::vector faces; + std::vector patches; - CGAL::Mesh_3::internal::facets_in_complex_3_to_triangle_soup(c3t3, points, faces); + CGAL::MDS_3::internal::facets_in_complex_3_to_triangle_soup(c3t3, points, faces, patches); return output_polygon_soup_to_off(points, faces, out); } diff --git a/Mesh_3/include/CGAL/internal/Mesh_3/Handle_IO_for_pair_of_int.h b/MDS_3/include/CGAL/internal/MDS_3/Handle_IO_for_pair_of_int.h similarity index 97% rename from Mesh_3/include/CGAL/internal/Mesh_3/Handle_IO_for_pair_of_int.h rename to MDS_3/include/CGAL/internal/MDS_3/Handle_IO_for_pair_of_int.h index b8b9c0c6182..99d6bdb71a9 100644 --- a/Mesh_3/include/CGAL/internal/Mesh_3/Handle_IO_for_pair_of_int.h +++ b/MDS_3/include/CGAL/internal/MDS_3/Handle_IO_for_pair_of_int.h @@ -13,12 +13,12 @@ #ifndef CGAL_INTERNAL_MESH_3_INTERNAL_HANDLE_IO_FOR_PAIR_OF_INT_H #define CGAL_INTERNAL_MESH_3_INTERNAL_HANDLE_IO_FOR_PAIR_OF_INT_H -#include +#include #include #include -#include +#include #include #include #include diff --git a/MDS_3/include/CGAL/internal/MDS_3/MDS_3_helper.h b/MDS_3/include/CGAL/internal/MDS_3/MDS_3_helper.h new file mode 100644 index 00000000000..4aa2c59ad09 --- /dev/null +++ b/MDS_3/include/CGAL/internal/MDS_3/MDS_3_helper.h @@ -0,0 +1,69 @@ +// Copyright (c) 2021 GeometryFactory +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois + +#ifndef CGAL_INTERNAL_MDS_3_HELPERS_H +#define CGAL_INTERNAL_MDS_3_HELPERS_H + +#include + +#include + +#include +#include + +namespace CGAL { +namespace MDS_3 { +namespace internal { + + template + bool is_convex(const Triangulation& tr) + { + typedef typename Triangulation::Facet Facet; + typedef typename Triangulation::Vertex_handle Vertex_handle; + typedef typename Triangulation::Cell_handle Cell_handle; + typedef typename Triangulation::Geom_traits::Point_3 Point_3; + typename Triangulation::Geom_traits::Construct_point_3 cp + = tr.geom_traits().construct_point_3_object(); + typename Triangulation::Geom_traits::Orientation_3 orientation = + tr.geom_traits().orientation_3_object(); + + std::vector infcells; + tr.incident_cells(tr.infinite_vertex(), std::back_inserter(infcells)); + for (Cell_handle c : infcells) + { + const Cell_handle neigh = c->neighbor(c->index(tr.infinite_vertex())); + const int i = neigh->index(c); + + const std::array pfacet = { cp(neigh->vertex((i + 1) % 4)->point()), + cp(neigh->vertex((i + 2) % 4)->point()), + cp(neigh->vertex((i + 3) % 4)->point())}; + const CGAL::Orientation o = orientation( + pfacet[0], pfacet[1], pfacet[2], cp(neigh->vertex(i)->point())); + + for (Vertex_handle v : tr.finite_vertex_handles()) + { + if (c->has_vertex(v)) + continue; + if (o != orientation(pfacet[0], pfacet[1], pfacet[2], + cp(neigh->vertex(i)->point()))) + return false; + } + } + + return true; + } + +} // end namespace internal +} // end namespace MDS_3 +} // end namespace CGAL + +#endif // CGAL_INTERNAL_MDS_3_HELPERS_H diff --git a/MDS_3/include/CGAL/tetrahedron_soup_to_triangulation_3.h b/MDS_3/include/CGAL/tetrahedron_soup_to_triangulation_3.h new file mode 100644 index 00000000000..ca6262fcc12 --- /dev/null +++ b/MDS_3/include/CGAL/tetrahedron_soup_to_triangulation_3.h @@ -0,0 +1,164 @@ +// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). +// Copyright (c) 2010-2013 GeometryFactory Sarl (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Mael Rouxel-Labbé, Maxime Gimeno, Jane Tournois +// +//****************************************************************************** +// File Description : +//****************************************************************************** + +#ifndef CGAL_MDS_3_TETRAHEDRON_SOUP_TO_C3T3_H +#define CGAL_MDS_3_TETRAHEDRON_SOUP_TO_C3T3_H + +#include + +#include +#include +#include + +#include +#include +#include + +namespace CGAL { + + /** \ingroup PkgMDS3Functions + * builds a 3D triangulation from a soup of tetrahedra. + * + * @tparam TetrahedronRange a model of `Range` whose value type is + * a `Tetrahedron_3` + * @tparam Triangulation a valid triangulation class that has + * a vertex base model of `MeshVertexBase_3` + * and a cell base model of `MeshCellBase_3` + * + * @param tets each element in the range is the geometric description of the + * corresponding cell in `tr` + * @param tr the 3D triangulation to be built + * + * @post the output triangulation should be a triangulation of the convex hull of `tets` + */ + template + void tetrahedron_soup_to_triangulation_3(const TetrahedronRange& tets, + Triangulation& tr) + { + typedef Triangulation Tr; + typedef typename Tr::Point Point; + + std::vector points; + std::vector > finite_cells; + std::map, typename Tr::Cell::Surface_patch_index> border_facets; + std::map p2i; + + CGAL_assertion_code( + typename Triangulation::Geom_traits::Orientation_3 orientation = + tr.geom_traits().orientation_3_object(); + ); + + for (typename TetrahedronRange::value_type tet : tets) + { + CGAL_assertion(tet.orientation() == CGAL::POSITIVE); + std::array cell; + + for (int i = 0; i < 4; ++i) + { + const Point& pi = tet[i]; + if (p2i.find(pi) == p2i.end()) + { + points.push_back(pi); + int index = static_cast(points.size() - 1); + p2i.insert(std::make_pair(pi, index)); + cell[i] = index; + } + else + cell[i] = p2i.at(pi); + } + cell[4] = 1; + + CGAL_assertion(orientation(points[cell[0]], + points[cell[1]], points[cell[2]], points[cell[3]]) == CGAL::POSITIVE); + + finite_cells.push_back(cell); + } + + CGAL::MDS_3::build_triangulation(tr, points, finite_cells, border_facets); + + CGAL_assertion(CGAL::MDS_3::internal::is_convex(tr)); + } + + /** \ingroup PkgMDS3Functions + * builds a 3D triangulation from a soup of tetrahedra. + * + * @tparam PointRange a model of the concept `RandomAccessContainer` + * whose value type is the point type + * @tparam TetrahedronRange a model of the concept `RandomAccessContainer` whose + * value type is a model of the concept `RandomAccessContainer` whose value type is `std::size_t` + * @tparam Triangulation a valid triangulation class that has + * a vertex base model of `MeshVertexBase_3` + * and a cell base model of `MeshCellBase_3` + * @tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" + * + * @param points points of the soup of tetrahedra + * @param tets each element in the range describes a tetrahedron using the indices of the points + * in `points` (indices 0 to 3), and the associated `Subdomain_index` (index 4) + * @param tr the 3D triangulation to be built + * @param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below + * + * \cgalNamedParamsBegin + * \cgalParamNBegin{surface_facets} + * \cgalParamDescription{each element in the range describes a surface facet using the indices of points + * in `points` (indices 0 to 2), and the associated `Surface_patch_index` (index 3)} + * \cgalParamType{a class model of `AssociativeContainer` + * whose key type is model of `RandomAccessContainer` containing `int` + * and mapped type is `Tr::Cell::Surface_patch_index`} + * \cgalParamDefault{An empty `std::map, typename Tr::Cell::Surface_patch_index>`} + * \cgalParamNEnd + * \cgalNamedParamsEnd + * + * @pre `points` contains each point only once + * @post the output triangulation should be a triangulation of the convex hull of `points` + * + * @sa `CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh()` + */ + template + void tetrahedron_soup_to_triangulation_3(const PointRange& points, + const TetrahedronRange& tets, + Triangulation& tr, + const NamedParameters& np) + { + using parameters::choose_parameter; + using parameters::get_parameter; + + std::map, + typename Triangulation::Cell::Surface_patch_index> empty_map; + auto facets = choose_parameter(get_parameter(np, internal_np::surface_facets), empty_map); + + CGAL::MDS_3::build_triangulation(tr, points, tets, facets); + + CGAL_assertion(CGAL::MDS_3::internal::is_convex(tr)); + } + + template + void tetrahedron_soup_to_triangulation_3(const PointRange& points, + const TetrahedronRange& tets, + Triangulation& tr) + { + tetrahedron_soup_to_triangulation_3(points, tets, tr, parameters::all_default()); + } + +} //namespace CGAL + + +#endif // CGAL_MDS_3_TETRAHEDRON_SOUP_TO_C3T3_H diff --git a/MDS_3/package_info/MDS_3/copyright b/MDS_3/package_info/MDS_3/copyright new file mode 100644 index 00000000000..8932b3233d2 --- /dev/null +++ b/MDS_3/package_info/MDS_3/copyright @@ -0,0 +1,2 @@ +INRIA Sophia-Antipolis (France) + diff --git a/MDS_3/package_info/MDS_3/dependencies b/MDS_3/package_info/MDS_3/dependencies new file mode 100644 index 00000000000..63b1fb79d40 --- /dev/null +++ b/MDS_3/package_info/MDS_3/dependencies @@ -0,0 +1,30 @@ +Algebraic_foundations +Arithmetic_kernel +BGL +Cartesian_kernel +Circulator +Distance_2 +Distance_3 +Filtered_kernel +Hash_map +Homogeneous_kernel +Installation +Intersections_2 +Intersections_3 +Interval_support +Kernel_23 +Kernel_d +MDS_3 +Modular_arithmetic +Number_types +Polygon +Polygon_mesh_processing +Profiling_tools +Property_map +Random_numbers +STL_Extension +Spatial_sorting +Stream_support +TDS_3 +Triangulation_3 +Union_find diff --git a/MDS_3/package_info/MDS_3/description.txt b/MDS_3/package_info/MDS_3/description.txt new file mode 100644 index 00000000000..7a83f60476c --- /dev/null +++ b/MDS_3/package_info/MDS_3/description.txt @@ -0,0 +1,2 @@ +Package MDS_3 : +Mesh Data Structures for dimension <=3 \ No newline at end of file diff --git a/MDS_3/package_info/MDS_3/license.txt b/MDS_3/package_info/MDS_3/license.txt new file mode 100644 index 00000000000..8bb8efcb72b --- /dev/null +++ b/MDS_3/package_info/MDS_3/license.txt @@ -0,0 +1 @@ +GPL (v3 or later) diff --git a/MDS_3/package_info/MDS_3/maintainer b/MDS_3/package_info/MDS_3/maintainer new file mode 100644 index 00000000000..880cb264269 --- /dev/null +++ b/MDS_3/package_info/MDS_3/maintainer @@ -0,0 +1,2 @@ +Laurent Rineau +Jane Tournois diff --git a/MDS_3/test/MDS_3/CMakeLists.txt b/MDS_3/test/MDS_3/CMakeLists.txt new file mode 100644 index 00000000000..25923742e40 --- /dev/null +++ b/MDS_3/test/MDS_3/CMakeLists.txt @@ -0,0 +1,29 @@ +# Created by the script cgal_create_cmake_script +# This is the CMake script for compiling a CGAL application. + +cmake_minimum_required(VERSION 3.1...3.20) +project( MDS_3_Tests ) + +find_package(CGAL REQUIRED) + +# Use Eigen +find_package(Eigen3 3.1.0 REQUIRED) #(requires 3.1.0 or greater) +include(CGAL_Eigen3_support) + +create_single_source_cgal_program( "test_c3t3.cpp" ) +create_single_source_cgal_program( "test_c3t3_io.cpp" ) +create_single_source_cgal_program( "test_c3t3_with_features.cpp" ) +create_single_source_cgal_program( "test_c3t3_into_facegraph.cpp" ) +create_single_source_cgal_program( "test_c3t3_extract_subdomains_boundaries.cpp" ) +create_single_source_cgal_program( "test_c3t3_io_MEDIT.cpp" ) + +foreach(target + test_c3t3 + test_c3t3_io + test_c3t3_with_features + test_c3t3_into_facegraph + test_c3t3_extract_subdomains_boundaries) + if(TARGET ${target}) + target_link_libraries(${target} PUBLIC CGAL::Eigen3_support) + endif() +endforeach() diff --git a/Mesh_3/test/Mesh_3/test_c3t3.cpp b/MDS_3/test/MDS_3/test_c3t3.cpp similarity index 98% rename from Mesh_3/test/Mesh_3/test_c3t3.cpp rename to MDS_3/test/MDS_3/test_c3t3.cpp index ffbc80d090a..0a6b56cafbb 100644 --- a/Mesh_3/test/Mesh_3/test_c3t3.cpp +++ b/MDS_3/test/MDS_3/test_c3t3.cpp @@ -37,10 +37,6 @@ struct Tester typedef typename CGAL::Mesh_triangulation_3::type Tr; typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3; - typedef CGAL::Mesh_3::Mesh_complex_3_in_triangulation_3_base C3t3_base_sequential; - typedef CGAL::Mesh_3::Mesh_complex_3_in_triangulation_3_base C3t3_base_parallel; typedef typename Tr::Bare_point Bare_point; typedef typename Tr::Weighted_point Weighted_point; diff --git a/Mesh_3/test/Mesh_3/test_c3t3_extract_subdomains_boundaries.cpp b/MDS_3/test/MDS_3/test_c3t3_extract_subdomains_boundaries.cpp similarity index 100% rename from Mesh_3/test/Mesh_3/test_c3t3_extract_subdomains_boundaries.cpp rename to MDS_3/test/MDS_3/test_c3t3_extract_subdomains_boundaries.cpp diff --git a/Mesh_3/test/Mesh_3/test_c3t3_into_facegraph.cpp b/MDS_3/test/MDS_3/test_c3t3_into_facegraph.cpp similarity index 95% rename from Mesh_3/test/Mesh_3/test_c3t3_into_facegraph.cpp rename to MDS_3/test/MDS_3/test_c3t3_into_facegraph.cpp index 9a953580e1b..7cb5e3e144d 100644 --- a/Mesh_3/test/Mesh_3/test_c3t3_into_facegraph.cpp +++ b/MDS_3/test/MDS_3/test_c3t3_into_facegraph.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include @@ -42,7 +42,7 @@ int main (int argc, char** argv){ return 1; } C3t3 c3t3; - if(CGAL::build_triangulation_from_file(in, c3t3.triangulation())) + if(CGAL::MDS_3::build_triangulation_from_file(in, c3t3.triangulation())) { for( C3t3::Triangulation::Finite_cells_iterator cit = c3t3.triangulation().finite_cells_begin(); @@ -88,6 +88,7 @@ int main (int argc, char** argv){ std::ofstream out("graph.off"); out << poly; + out.close(); CGAL_assertion(is_valid(poly)); return EXIT_SUCCESS; diff --git a/Mesh_3/test/Mesh_3/test_c3t3_io.cpp b/MDS_3/test/MDS_3/test_c3t3_io.cpp similarity index 99% rename from Mesh_3/test/Mesh_3/test_c3t3_io.cpp rename to MDS_3/test/MDS_3/test_c3t3_io.cpp index 5e75b344e14..c2398fa4402 100644 --- a/Mesh_3/test/Mesh_3/test_c3t3_io.cpp +++ b/MDS_3/test/MDS_3/test_c3t3_io.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include diff --git a/MDS_3/test/MDS_3/test_c3t3_io_MEDIT.cpp b/MDS_3/test/MDS_3/test_c3t3_io_MEDIT.cpp new file mode 100644 index 00000000000..1e697632c63 --- /dev/null +++ b/MDS_3/test/MDS_3/test_c3t3_io_MEDIT.cpp @@ -0,0 +1,34 @@ +#include + +#include +#include + +#include + +#include +#include + +int main (int argc, char** argv) +{ + typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + + typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Tr; + typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3; + + // Open file + std::ifstream in(argc > 1 ? argv[1] : "data/elephant.mesh", + std::ios_base::in); + if(!in) { + std::cerr << "Error! Cannot open file " << argv[1] << std::endl; + return 1; + } + Tr tr; + CGAL::IO::read_MEDIT(in, tr); + + std::ofstream os("elephant_out.mesh"); + CGAL::IO::write_MEDIT(os, tr, + CGAL::parameters::all_vertices(false)); + os.close(); + + return EXIT_SUCCESS; +} diff --git a/Mesh_3/test/Mesh_3/test_c3t3_with_features.cpp b/MDS_3/test/MDS_3/test_c3t3_with_features.cpp similarity index 100% rename from Mesh_3/test/Mesh_3/test_c3t3_with_features.cpp rename to MDS_3/test/MDS_3/test_c3t3_with_features.cpp diff --git a/MDS_3/test/MDS_3/test_utilities.h b/MDS_3/test/MDS_3/test_utilities.h new file mode 100644 index 00000000000..16797ae26bc --- /dev/null +++ b/MDS_3/test/MDS_3/test_utilities.h @@ -0,0 +1,51 @@ +// Copyright (c) 2009 INRIA Sophia-Antipolis (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Stephane Tayeb +// +//****************************************************************************** +// File Description : +// +//****************************************************************************** + +#ifndef CGAL_MESH_3_TEST_TEST_UTILITIES_H +#define CGAL_MESH_3_TEST_TEST_UTILITIES_H + +#include +#include + +#include +#include + +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K_e_i; +typedef CGAL::Exact_predicates_exact_constructions_kernel K_e_e; + +namespace CGAL { +namespace details { + +template<> +struct Mesh_geom_traits_generator +{ +private: + typedef K_e_e Geom_traits; + +public: + typedef Geom_traits type; + typedef type Type; +}; // end struct Mesh_geom_traits_generator<...> + +} // end namespace details +} // end namespace CGAL + +#include + +#endif // CGAL_MESH_3_TEST_TEST_UTILITIES_H diff --git a/Mesh_3/doc/Mesh_3/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h b/Mesh_3/doc/Mesh_3/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h deleted file mode 100644 index b672d4d3273..00000000000 --- a/Mesh_3/doc/Mesh_3/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h +++ /dev/null @@ -1,16 +0,0 @@ -namespace CGAL { -//! \ingroup PkgMesh3Functions -//! -//! \brief builds a `TriangleMesh` from the surface facets, with a consistent orientation at the interface of two subdomains. -//! -//! This function exports the surface as a `TriangleMesh` and appends it to `graph`, using -//! `orient_polygon_soup()`. -//! -//! @tparam C3T3 a model of `MeshComplexWithFeatures_3InTriangulation_3`. -//! @tparam TriangleMesh a model of `MutableFaceGraph` with an internal point property map. The point type should be compatible with the one used in `C3T3`. -//! -//! @param c3t3 an instance of `C3T3`. -//! @param graph an instance of `TriangleMesh`. -template -void facets_in_complex_3_to_triangle_mesh(const C3T3& c3t3, TriangleMesh& graph); -} diff --git a/Mesh_3/doc/Mesh_3/CGAL/Mesh_complex_3_in_triangulation_3.h b/Mesh_3/doc/Mesh_3/CGAL/Mesh_complex_3_in_triangulation_3.h deleted file mode 100644 index d46c9ea2b83..00000000000 --- a/Mesh_3/doc/Mesh_3/CGAL/Mesh_complex_3_in_triangulation_3.h +++ /dev/null @@ -1,101 +0,0 @@ -namespace CGAL { - -/*! -\ingroup PkgMesh3MeshClasses - -The class `Mesh_complex_3_in_triangulation_3` implements a data structure -to store the 3D restricted Delaunay triangulation used by a mesh -generation process. - -This class is a model of the concept -`MeshComplexWithFeatures_3InTriangulation_3`. - - -\tparam Tr can be instantiated with any 3D -regular triangulation of \cgal provided that its -vertex and cell base class are models of the concepts -`MeshVertexBase_3` and `MeshCellBase_3`, respectively. - -\tparam CornerIndex is the type of the indices for corners. It must match the `Corner_index` of the model -of the `MeshDomainWithFeatures_3` concept used for mesh generation. - -\tparam CurveIndex is the type of the indices for curves. -It must match the `Curve_index` types of the model -of the `MeshDomainWithFeatures_3` concept used for mesh generation. - -Those two last template parameters defaults to `int`, so that they can be ignored -if the domain used for mesh generation does not include 0 and 1-dimensionnal features (i.e -is a model of the concept `MeshDomain_3`). - -\cgalModels `MeshComplexWithFeatures_3InTriangulation_3` - -\sa `CGAL::make_mesh_3()` -\sa `CGAL::refine_mesh_3()` -\sa `MeshComplex_3InTriangulation_3` -\sa `MeshComplexWithFeatures_3InTriangulation_3` -\sa `MeshCellBase_3`, -\sa `MeshVertexBase_3` - -*/ -template< typename Tr, typename CornerIndex, typename CurveIndex > -class Mesh_complex_3_in_triangulation_3 { -public: - -/// \name Types -/// @{ - -/*! -%Index type. -*/ -typedef Tr::Vertex::Index Index; - -/*! -Surface index type. -*/ -typedef Tr::Cell::Surface_patch_index Surface_patch_index; - -/*! -Subdomain index type. -*/ -typedef Tr::Cell::Subdomain_index Subdomain_index; - -/*! - Corner index type. -*/ -typedef CornerIndex Corner_index; - -/*! -Curve index type. -*/ -typedef CurveIndex Curve_index; - -/// @} - -/// \name Operations -/// @{ - -/*! -Outputs the mesh to `os` -in medit format. -*/ -void output_to_medit(std::ofstream& os); - -/** - * Outputs the outer boundary of the entire domain with facets oriented outward. - */ -std::ostream& output_boundary_to_off(std::ostream& out) const; - -/** - * Outputs the outer boundary of the selected subdomain with facets oriented outward. - */ -std::ostream& output_boundary_to_off(std::ostream& out, Subdomain_index subdomain) const; - -/** - * Outputs the surface facets with a consistent orientation at the interface of two subdomains. - */ -std::ostream& output_facets_in_complex_to_off(std::ostream& out) const; - -/// @} - -}; /* end Mesh_complex_3_in_triangulation_3 */ -} /* end namespace CGAL */ diff --git a/Mesh_3/doc/Mesh_3/CGAL/make_mesh_3.h b/Mesh_3/doc/Mesh_3/CGAL/make_mesh_3.h index 08bd5ee1761..312b556343f 100644 --- a/Mesh_3/doc/Mesh_3/CGAL/make_mesh_3.h +++ b/Mesh_3/doc/Mesh_3/CGAL/make_mesh_3.h @@ -33,7 +33,10 @@ traverse the resulting mesh data structure or can be written to a file \tparam C3T3 is required to be a model of -the concept `MeshComplex_3InTriangulation_3`. This is the return type. +the concept `MeshComplex_3InTriangulation_3`, +and a model of `MeshComplexWithFeatures_3InTriangulation_3` +if the domain is a model of `MeshDomainWithFeatures_3`. +This is the return type. The type `C3T3` is in particular required to provide a nested type `C3T3::Triangulation` for the 3D triangulation embedding the mesh. The vertex and cell base classes of the diff --git a/Mesh_3/doc/Mesh_3/CGAL/refine_mesh_3.h b/Mesh_3/doc/Mesh_3/CGAL/refine_mesh_3.h index 25ddc7311ed..afeebe8c634 100644 --- a/Mesh_3/doc/Mesh_3/CGAL/refine_mesh_3.h +++ b/Mesh_3/doc/Mesh_3/CGAL/refine_mesh_3.h @@ -39,7 +39,9 @@ not change from one refinement to the next one. \tparam C3T3 is required to be a model of the concept -`MeshComplex_3InTriangulation_3`. +`MeshComplex_3InTriangulation_3`, +and a model of `MeshComplexWithFeatures_3InTriangulation_3` +if the domain is a model of `MeshDomainWithFeatures_3`. The argument `c3t3` is passed by reference as this object is modified by the refinement process. As the refinement process only adds points to the triangulation, all diff --git a/Mesh_3/doc/Mesh_3/PackageDescription.txt b/Mesh_3/doc/Mesh_3/PackageDescription.txt index f7a09d8f473..5795120abe5 100644 --- a/Mesh_3/doc/Mesh_3/PackageDescription.txt +++ b/Mesh_3/doc/Mesh_3/PackageDescription.txt @@ -29,7 +29,7 @@ /// \defgroup PkgMesh3IOFunctions Input/Output Functions /// \ingroup PkgMesh3Ref -/// The free functions that can be used to read and write meshes. +/// See \ref PkgMDS3IOFunctions from 3D Mesh Data Structures. /*! \addtogroup PkgMesh3Ref @@ -57,8 +57,6 @@ Here are the main concepts of this package: - `MeshTriangulationTraits_3` -- `MeshComplex_3InTriangulation_3` -- `MeshComplexWithFeatures_3InTriangulation_3` - `MeshDomain_3` - `MeshDomainWithFeatures_3` - `MeshCriteria_3` @@ -80,7 +78,6 @@ related to the template parameters of some models of the main concepts: \cgalCRPSection{Classes} -- `CGAL::Mesh_complex_3_in_triangulation_3` - `CGAL::Mesh_triangulation_3` - `CGAL::Mesh_vertex_base_3` - `CGAL::Compact_mesh_cell_base_3` @@ -114,7 +111,6 @@ and their associated classes: - `CGAL::perturb_mesh_3()` - `CGAL::lloyd_optimize_mesh_3()` - `CGAL::odt_optimize_mesh_3()` -- `CGAL::facets_in_complex_3_to_triangle_mesh()` \cgalCRPSection{CGAL::parameters Functions} @@ -141,4 +137,3 @@ and their associated classes: - `CGAL::IO::output_to_medit()` - `CGAL::IO::output_to_vtu()` */ - diff --git a/Mesh_3/doc/Mesh_3/dependencies b/Mesh_3/doc/Mesh_3/dependencies index 8dc427e241e..8d1e9d646e9 100644 --- a/Mesh_3/doc/Mesh_3/dependencies +++ b/Mesh_3/doc/Mesh_3/dependencies @@ -13,3 +13,5 @@ Polyhedron Miscellany Mesh_2 Polygon_mesh_processing +MDS_3 + diff --git a/Mesh_3/examples/Mesh_3/mesh_3D_image_with_custom_initialization.cpp b/Mesh_3/examples/Mesh_3/mesh_3D_image_with_custom_initialization.cpp index 7a326ee1b2f..5de1774377f 100644 --- a/Mesh_3/examples/Mesh_3/mesh_3D_image_with_custom_initialization.cpp +++ b/Mesh_3/examples/Mesh_3/mesh_3D_image_with_custom_initialization.cpp @@ -11,7 +11,7 @@ #include #include -#include +#include // Domain typedef CGAL::Exact_predicates_inexact_constructions_kernel K; diff --git a/Mesh_3/examples/Mesh_3/mesh_hybrid_mesh_domain.cpp b/Mesh_3/examples/Mesh_3/mesh_hybrid_mesh_domain.cpp index 7e6cc3202ed..33ab594d1f0 100644 --- a/Mesh_3/examples/Mesh_3/mesh_hybrid_mesh_domain.cpp +++ b/Mesh_3/examples/Mesh_3/mesh_hybrid_mesh_domain.cpp @@ -13,7 +13,7 @@ #include // Ouput -#include +#include // Read 1D features from input file #include "read_polylines.h" diff --git a/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h b/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h index 765c2a373c9..5201a9b9a86 100644 --- a/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h +++ b/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h @@ -28,7 +28,7 @@ #include #include -#include +#include #include diff --git a/Mesh_3/include/CGAL/Labeled_mesh_domain_3.h b/Mesh_3/include/CGAL/Labeled_mesh_domain_3.h index 6a755990d5e..59da02ae1cf 100644 --- a/Mesh_3/include/CGAL/Labeled_mesh_domain_3.h +++ b/Mesh_3/include/CGAL/Labeled_mesh_domain_3.h @@ -33,7 +33,7 @@ #include -#include +#include #include // support for `CGAL::Image_3` diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesh_surface_cell_base_3.h b/Mesh_3/include/CGAL/Mesh_3/Mesh_surface_cell_base_3.h index 3e5437c8244..e2b1873281f 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesh_surface_cell_base_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesh_surface_cell_base_3.h @@ -24,7 +24,7 @@ #include #include -#include +#include #ifdef CGAL_LINKED_WITH_TBB # include diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h b/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h index de889e42acf..1293735a210 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h @@ -36,7 +36,7 @@ #include -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h b/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h index 36a48742614..296c5d441bc 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h +++ b/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h @@ -28,11 +28,11 @@ #include #include -#include +#include #ifdef CGAL_MESH_3_DUMP_FEATURES_PROTECTION_ITERATIONS # include #endif -#include +#include #include #include #include @@ -108,7 +108,7 @@ void debug_dump_c3t3(const std::string filename, const C3t3& c3t3) template class Protect_edges_sizing_field - : public CGAL::Mesh_3::internal::Debug_messages_tools + : public CGAL::MDS_3::internal::Debug_messages_tools { typedef Protect_edges_sizing_field Self; diff --git a/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h b/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h index 952ae641ed9..548d41d2fe0 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h @@ -38,7 +38,7 @@ #ifdef CGAL_MESH_3_PROFILING #include #endif -#include +#include #include diff --git a/Mesh_3/include/CGAL/Mesh_cell_base_3.h b/Mesh_3/include/CGAL/Mesh_cell_base_3.h index b944bdad4ac..b659a74c2b3 100644 --- a/Mesh_3/include/CGAL/Mesh_cell_base_3.h +++ b/Mesh_3/include/CGAL/Mesh_cell_base_3.h @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h b/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h deleted file mode 100644 index 0eb11a1f3c6..00000000000 --- a/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h +++ /dev/null @@ -1,799 +0,0 @@ -// Copyright (c) 2009-2014 INRIA Sophia-Antipolis (France). -// Copyright (c) 2010-2013 GeometryFactory Sarl (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Stephane Tayeb, Clement Jamin -// -//****************************************************************************** -// File Description : -//****************************************************************************** - -#ifndef CGAL_MESH_COMPLEX_3_IN_TRIANGULATION_3_H -#define CGAL_MESH_COMPLEX_3_IN_TRIANGULATION_3_H - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -namespace CGAL { - - -template -class Mesh_complex_3_in_triangulation_3 : - public Mesh_3::Mesh_complex_3_in_triangulation_3_base< - Tr, typename Tr::Concurrency_tag> - , public CGAL::Mesh_3::internal::Debug_messages_tools -{ -public: - typedef typename Tr::Concurrency_tag Concurrency_tag; - -private: - typedef Mesh_complex_3_in_triangulation_3< - Tr,CornerIndex,CurveIndex> Self; - typedef Mesh_3::Mesh_complex_3_in_triangulation_3_base< - Tr,Concurrency_tag> Base; - -public: - typedef typename Base::size_type size_type; - - typedef typename Tr::Point Point; - typedef typename Base::Edge Edge; - typedef typename Base::Facet Facet; - typedef typename Base::Vertex_handle Vertex_handle; - typedef typename Base::Cell_handle Cell_handle; - typedef CornerIndex Corner_index; - typedef CurveIndex Curve_index; - - typedef CGAL::Hash_handles_with_or_without_timestamps Hash_fct; - -#ifndef CGAL_NO_DEPRECATED_CODE - typedef CurveIndex Curve_segment_index; -#endif - - typedef typename Base::Triangulation Triangulation; - typedef typename Base::Subdomain_index Subdomain_index; - - using Base::surface_patch_index; - -private: - // Type to store the edges: - // - a set of std::pair (ordered at insertion) - // - which allows fast lookup from one Vertex_handle - // - each element of the set has an associated info (Curve_index) value - typedef boost::bimaps::bimap< - boost::bimaps::multiset_of, - boost::bimaps::multiset_of, - boost::bimaps::set_of_relation<>, - boost::bimaps::with_info > Edge_map; - - typedef typename Edge_map::value_type Internal_edge; - - // Type to store the corners - typedef boost::unordered_map Corner_map; - - // Type to store far vertices - typedef std::vector Far_vertices_vec; - -public: - /** - * Constructor - */ - Mesh_complex_3_in_triangulation_3() = default; - - /** - * Copy constructor - */ - Mesh_complex_3_in_triangulation_3(const Self& rhs); - - /** - * Move constructor - */ - Mesh_complex_3_in_triangulation_3(Self&& rhs) - : Base(std::move(rhs)) - , edges_(std::move(rhs.edges_)) - , corners_(std::move(rhs.corners_)) - , far_vertices_(std::move(rhs.far_vertices_)) - {} - - /** - * Assignement operator, also serves as move-assignement - */ - Self& operator=(Self rhs) - { - swap(rhs); - return *this; - } - - /** - * Swaps this & rhs - */ - void swap(Self& rhs) - { - Base::swap(rhs); - edges_.swap(rhs.edges_); - corners_.swap(rhs.corners_); - far_vertices_.swap(rhs.far_vertices_); - } - - /** - * Clears data of c3t3 - */ - void clear() - { - Base::clear(); - edges_.clear(); - corners_.clear(); - far_vertices_.clear(); - } - - /// Import Base functions - using Base::is_in_complex; - using Base::add_to_complex; - using Base::remove_from_complex; - using Base::triangulation; - using Base::set_surface_patch_index; - - - - /** - * Add edge e to complex, with Curve_index index - */ - void add_to_complex(const Edge& e, - const Curve_index& index) - { - add_to_complex(e.first->vertex(e.second), - e.first->vertex(e.third), - index); - } - - /** - * Add edge (v1,v2) to complex, with Curve_index index - */ - void add_to_complex(const Vertex_handle& v1, - const Vertex_handle& v2, - const Curve_index& index) - { - add_to_complex(make_internal_edge(v1,v2), index); - } - - /** - * Mark vertex \c v as a corner of the complex - */ - void add_to_complex(const Vertex_handle& v, const Corner_index& index) - { - v->set_dimension(0); - corners_.insert(std::make_pair(v,index)); - } - - /** - * Remove edge \c e from complex - */ - void remove_from_complex(const Edge& e) - { - remove_from_complex(e.first->vertex(e.second), e.first->vertex(e.third)); - } - - /** - * Remove edge (v1,v2) from complex - */ - void remove_from_complex(const Vertex_handle& v1, const Vertex_handle& v2) - { - remove_from_complex(make_internal_edge(v1,v2)); - } - - /** - * Remove vertex \c v from complex - */ - void remove_from_complex(const Vertex_handle& v) - { - corners_.erase(v); - v->set_dimension(-1); - } - - std::size_t number_of_far_points() const - { - return far_vertices_.size(); - } - - void add_far_point(const Point &p) - { - far_vertices_.push_back(triangulation().insert(p)); - } - - void add_far_point(Vertex_handle vh) - { - far_vertices_.push_back(vh); - } - - void remove_far_points() - { - Triangulation &tr = triangulation(); - //triangulation().remove(far_vertices_.begin(), far_vertices_.end()); - typename Far_vertices_vec::const_iterator it = far_vertices_.begin(); - typename Far_vertices_vec::const_iterator it_end = far_vertices_.end(); - for ( ; it != it_end ; ++it) - { - std::vector new_cells; - new_cells.reserve(32); - tr.remove_and_give_new_cells(*it, std::back_inserter(new_cells)); - - typename std::vector::iterator nc_it = new_cells.begin(); - typename std::vector::iterator nc_it_end = new_cells.end(); - for ( ; nc_it != nc_it_end ; ++nc_it) - { - Cell_handle c = *nc_it; - for (int i = 0 ; i < 4 ; ++i) - { - Facet mirror_facet = tr.mirror_facet(std::make_pair(c, i)); - if (is_in_complex(mirror_facet)) - { - set_surface_patch_index(c, i, - surface_patch_index(mirror_facet)); - c->set_facet_surface_center(i, - mirror_facet.first->get_facet_surface_center(mirror_facet.second)); - } - } - /*int i_inf; - if (c->has_vertex(tr.infinite_vertex(), i_inf)) - { - Facet mirror_facet = tr.mirror_facet(std::make_pair(c, i_inf)); - if (is_in_complex(mirror_facet)) - { - set_surface_patch_index(c, i_inf, - surface_patch_index(mirror_facet)); - } - }*/ - } - } - far_vertices_.clear(); - } - - /** - * Returns the number of edges of c3t3 - */ - size_type number_of_edges_in_complex() const - { - return edges_.size(); - } - size_type number_of_edges() const - { - return edges_.size(); - } - - /** - * Returns the number of corners of c3t3 - */ - size_type number_of_vertices_in_complex() const - { - return corners_.size(); - } - size_type number_of_corners() const - { - return corners_.size(); - } - - void rescan_after_load_of_triangulation(); - - /** - * Returns true if edge \c e is in complex - */ - bool is_in_complex(const Edge& e) const - { - return is_in_complex(e.first->vertex(e.second), e.first->vertex(e.third)); - } - - /** - * Returns true if edge (v1,v2) is in C3T3 - */ - bool is_in_complex(const Vertex_handle& v1, const Vertex_handle& v2) const - { - return is_in_complex(make_internal_edge(v1,v2)); - } - - /** - * Returns true if \c v is a 0-dimensionnal feature in the c3t3 - */ - bool is_in_complex(const Vertex_handle& v) const - { - return (corners_.find(v) != corners_.end()); - } - - /** - * Returns Curve_index of edge \c e - */ - Curve_index curve_index(const Edge& e) const - { - return curve_index(e.first->vertex(e.second), - e.first->vertex(e.third)); - } - - Curve_index curve_index(const Vertex_handle& v1, - const Vertex_handle& v2) const - { - return curve_index(make_internal_edge(v1,v2)); - } - -#ifndef CGAL_NO_DEPRECATED_CODE - CGAL_DEPRECATED - Curve_index curve_segment_index(const Edge& e) const - { - return curve_index(e); - } - - CGAL_DEPRECATED - Curve_index curve_segment_index(const Vertex_handle& v1, - const Vertex_handle& v2) const - { - return curve_index(v1, v2); - } -#endif // CGAL_NO_DEPRECATED_CODE - - /** - * Returns Corner_index of vertex \c v - */ - Corner_index corner_index(const Vertex_handle& v) const - { - typename Corner_map::const_iterator it = corners_.find(v); - if ( corners_.end() != it ) { return it->second; } - return Corner_index(); - } - - /** - * Outputs the outer boundary of the entire domain with facets oriented outward. - */ - std::ostream& output_boundary_to_off(std::ostream& out) const - { - internal::output_boundary_of_c3t3_to_off(*this, 0, out, false); - return out; - } - - /** - * Outputs the outer boundary of the selected subdomain with facets oriented outward. - */ - std::ostream& output_boundary_to_off(std::ostream& out, Subdomain_index subdomain) const - { - output_boundary_of_c3t3_to_off(*this, subdomain, out); - return out; - } - - /** - * Outputs the surface facets with a consistent orientation at the interface of two subdomains. - */ - std::ostream& output_facets_in_complex_to_off(std::ostream& out) const - { - internal::output_facets_in_complex_to_off(*this, out); - return out; - } - - /** - * Fills \c out with incident edges (1-dimensional features of \c v. - * OutputIterator value type is std::pair - * \pre v->in_dimension() < 2 - */ - template - OutputIterator - adjacent_vertices_in_complex(const Vertex_handle& v, OutputIterator out) const; - - // ----------------------------------- - // Undocumented - // ----------------------------------- - - /** - * Returns true if c3t3 is valid - */ - bool is_valid(bool verbose = false) const; - - // ----------------------------------- - // Complex traversal - // ----------------------------------- -private: - class Edge_iterator_not_in_complex - { - const Self& c3t3_; - const Curve_index index_; - public: - Edge_iterator_not_in_complex(const Self& c3t3, - const Curve_index& index = Curve_index()) - : c3t3_(c3t3) - , index_(index) { } - - template - bool operator()(Iterator it) const - { - if ( index_ == Curve_index() ) { return ! c3t3_.is_in_complex(*it); } - else { return c3t3_.curve_index(*it) != index_; } - } - }; - - class Vertex_iterator_not_in_complex - { - const Self& c3t3_; - const Corner_index index_; - public: - Vertex_iterator_not_in_complex(const Self& c3t3, - const Corner_index& index = Corner_index()) - : c3t3_(c3t3) - , index_(index) { } - - template - bool operator()(const ItMap it) const - { - if ( index_ == Corner_index() ) { return false; } - else { return it->second != index_; } - } - }; - - // Filtered iterator - typedef Filter_iterator< - typename Corner_map::const_iterator, - Vertex_iterator_not_in_complex > Vertex_map_filter_iterator; - - // Iterator type to get the first element of pair - typedef boost::transform_iterator < - Mesh_3::internal::First_of, - Vertex_map_filter_iterator > Vertex_map_iterator_first; - - // Iterator type to remove a level of referencing - class Vertex_map_iterator_first_dereference - : public boost::iterator_adaptor < - Vertex_map_iterator_first_dereference, - Vertex_map_iterator_first, - typename Vertex_map_iterator_first::value_type::value_type, - boost::use_default, - typename Vertex_map_iterator_first::value_type::reference > - { - typedef Vertex_map_iterator_first_dereference Self; - typedef boost::iterator_adaptor < - Vertex_map_iterator_first_dereference, - Vertex_map_iterator_first, - typename Vertex_map_iterator_first::value_type::value_type, - boost::use_default, - typename Vertex_map_iterator_first::value_type::reference > iterator_adaptor_; - public: - typedef typename Vertex_map_iterator_first::reference pointer; - typedef typename iterator_adaptor_::reference reference; - - Vertex_map_iterator_first_dereference() : Self::iterator_adaptor_() { } - - template < typename Iterator > - Vertex_map_iterator_first_dereference(Iterator i) - : Self::iterator_adaptor_(typename Self::iterator_adaptor_::base_type(i)) - { } - - pointer operator->() const { return *(this->base()); } - reference operator*() const { return **(this->base()); } - - operator Vertex_handle() { return Vertex_handle(*(this->base())); } - }; - -public: - /// Iterator type to visit the edges of the 1D complex. - typedef Filter_iterator< - typename Triangulation::Finite_edges_iterator, - Edge_iterator_not_in_complex > Edges_in_complex_iterator; - - /// Returns a Facets_in_complex_iterator to the first facet of the 1D complex - Edges_in_complex_iterator edges_in_complex_begin() const - { - return CGAL::filter_iterator(this->triangulation().finite_edges_end(), - Edge_iterator_not_in_complex(*this), - this->triangulation().finite_edges_begin()); - } - - /// Returns a Facets_in_complex_iterator to the first facet of the 1D complex - Edges_in_complex_iterator - edges_in_complex_begin(const Curve_index& index) const - { - return CGAL::filter_iterator(this->triangulation().finite_edges_end(), - Edge_iterator_not_in_complex(*this,index), - this->triangulation().finite_edges_begin()); - } - - /// Returns past-the-end iterator on facet of the 1D complex - Edges_in_complex_iterator edges_in_complex_end(const Curve_index& = Curve_index()) const - { - return CGAL::filter_iterator(this->triangulation().finite_edges_end(), - Edge_iterator_not_in_complex(*this)); - } - - /// Iterator type to visit the edges of the 0D complex. - typedef Vertex_map_iterator_first_dereference Vertices_in_complex_iterator; - - /// Returns a Vertices_in_complex_iterator to the first vertex of the 0D complex - Vertices_in_complex_iterator vertices_in_complex_begin() const - { - return CGAL::filter_iterator(corners_.end(), - Vertex_iterator_not_in_complex(*this), - corners_.begin()); - } - - /// Returns a Vertices_in_complex_iterator to the first vertex of the 0D complex - Vertices_in_complex_iterator - vertices_in_complex_begin(const Corner_index& index) const - { - return CGAL::filter_iterator(corners_.end(), - Vertex_iterator_not_in_complex(*this,index), - corners_.begin()); - } - - /// Returns past-the-end iterator on facet of the 0D complex - Vertices_in_complex_iterator vertices_in_complex_end() const - { - return CGAL::filter_iterator(corners_.end(), - Vertex_iterator_not_in_complex(*this)); - } - - -private: - /** - * Creates an Internal_edge object (i.e a pair of ordered Vertex_handle) - */ - Internal_edge make_internal_edge(const Vertex_handle& v1, - const Vertex_handle& v2) const - { - if ( v1 < v2 ) { return Internal_edge(v1,v2); } - else { return Internal_edge(v2,v1); } - } - - /** - * Returns true if \c edge is in C3T3 - */ - bool is_in_complex(const Internal_edge& edge) const - { - return (curve_index(edge) != Curve_index() ); - } - - /** - * Add edge \c edge to complex, with Curve_index index - */ - void add_to_complex(const Internal_edge& edge, const Curve_index& index) - { - CGAL_precondition(!is_in_complex(edge)); -#if CGAL_MESH_3_PROTECTION_DEBUG & 1 - std::cerr << "Add edge ( " << disp_vert(edge.left) - << " , " << disp_vert(edge.right) << " ), curve_index=" << index - << " to c3t3.\n"; -#endif // CGAL_MESH_3_PROTECTION_DEBUG - std::pair it = edges_.insert(edge); - it.first->info = index; - } - - /** - * Remove edge \c edge from complex - */ - void remove_from_complex(const Internal_edge& edge) - { - edges_.erase(edge); - } - - /** - * Returns Curve_index of edge \c edge - */ - Curve_index curve_index(const Internal_edge& edge) const - { - typename Edge_map::const_iterator it = edges_.find(edge); - if ( edges_.end() != it ) { return it->info; } - return Curve_index(); - } - -private: - Edge_map edges_; - Corner_map corners_; - Far_vertices_vec far_vertices_; -}; - - -template -Mesh_complex_3_in_triangulation_3:: -Mesh_complex_3_in_triangulation_3(const Self& rhs) - : Base(rhs) - , edges_() - , corners_() -{ - // Copy edges - for ( typename Edge_map::const_iterator it = rhs.edges_.begin(), - end = rhs.edges_.end() ; it != end ; ++it ) - { - const Vertex_handle& va = it->right; - const Vertex_handle& vb = it->left; - - Vertex_handle new_va; - this->triangulation().is_vertex(rhs.triangulation().point(va), new_va); - - Vertex_handle new_vb; - this->triangulation().is_vertex(rhs.triangulation().point(vb), new_vb); - - this->add_to_complex(make_internal_edge(new_va,new_vb), it->info); - } - - // Copy corners - for ( typename Corner_map::const_iterator it = rhs.corners_.begin(), - end = rhs.corners_.end() ; it != end ; ++it ) - { - Vertex_handle new_v; - this->triangulation().is_vertex(rhs.triangulation().point(it->first), new_v); - this->add_to_complex(new_v, it->second); - } - - // Parse vertices to identify far vertices - if (rhs.far_vertices_.size() > 0) - { - Triangulation &tr = triangulation(); - typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(); - for(typename Tr::Finite_vertices_iterator end = tr.finite_vertices_end(); - vit != end ; ++vit) - { - if (vit->in_dimension() == -1) - far_vertices_.push_back(vit); - } - CGAL_assertion(far_vertices_.size() == rhs.far_vertices_.size()); - } -} - - -template -template -OutputIterator -Mesh_complex_3_in_triangulation_3:: -adjacent_vertices_in_complex(const Vertex_handle& v, OutputIterator out) const -{ - CGAL_precondition(v->in_dimension() < 2); - - typedef typename Edge_map::right_const_iterator Rcit; - typedef typename Edge_map::left_const_iterator Lcit; - - // Add edges containing v is on the left - std::pair range_right = edges_.right.equal_range(v); - for ( Rcit rit = range_right.first ; rit != range_right.second ; ++rit ) - { - *out++ = std::make_pair(rit->second, rit->info); - } - - // Add edges containing v on the right - std::pair range_left = edges_.left.equal_range(v); - for ( Lcit lit = range_left.first ; lit != range_left.second ; ++lit ) - { - *out++ = std::make_pair(lit->second, lit->info); - } - - return out; -} - - -template -bool -Mesh_complex_3_in_triangulation_3:: -is_valid(bool verbose) const -{ - typedef typename Tr::Weighted_point Weighted_point; - typedef boost::unordered_map Vertex_map; - - Vertex_map vertex_map; - - // Fill map counting neighbor number for each vertex of an edge - for ( typename Edge_map::const_iterator it = edges_.begin(), - end = edges_.end() ; it != end ; ++it ) - { - const Vertex_handle& v1 = it->right; - if ( vertex_map.find(v1) == vertex_map.end() ) { vertex_map[v1] = 1; } - else { vertex_map[v1] += 1; } - - const Vertex_handle& v2 = it->left; - if ( vertex_map.find(v2) == vertex_map.end() ) { vertex_map[v2] = 1; } - else { vertex_map[v2] += 1; } - } - - // Verify that each vertex has 2 neighbors if it's not a corner - for ( typename Vertex_map::iterator vit = vertex_map.begin(), - vend = vertex_map.end() ; vit != vend ; ++vit ) - { - if ( vit->first->in_dimension() != 0 && vit->second != 2 ) - { - if(verbose) - std::cerr << "Validity error: vertex " << (void*)(&*vit->first) - << " (" << this->triangulation().point(vit->first) << ") " - << "is not a corner (dimension " << vit->first->in_dimension() - << ") but has " << vit->second << " neighbor(s)!\n"; - return false; - } - } - - // Verify that balls of each edge intersect - for ( typename Edge_map::const_iterator it = edges_.begin(), - end = edges_.end() ; it != end ; ++it ) - { - typename Tr::Geom_traits::Compute_weight_3 cw = - this->triangulation().geom_traits().compute_weight_3_object(); - typename Tr::Geom_traits::Construct_point_3 cp = - this->triangulation().geom_traits().construct_point_3_object(); - typename Tr::Geom_traits::Construct_sphere_3 sphere = - this->triangulation().geom_traits().construct_sphere_3_object(); - typename Tr::Geom_traits::Do_intersect_3 do_intersect = - this->triangulation().geom_traits().do_intersect_3_object(); - - const Weighted_point& itrwp = this->triangulation().point(it->right); - const Weighted_point& itlwp = this->triangulation().point(it->left); - - if ( ! do_intersect(sphere(cp(itrwp), cw(itrwp)), sphere(cp(itlwp), cw(itlwp))) ) - { - std::cerr << "Points p[" << disp_vert(it->right) << "], dim=" << it->right->in_dimension() - << " and q[" << disp_vert(it->left) << "], dim=" << it->left->in_dimension() - << " form an edge but do not intersect !\n"; - return false; - } - } - - return true; -} - -template -void -Mesh_complex_3_in_triangulation_3:: -rescan_after_load_of_triangulation() { - corners_.clear(); - for(typename Tr::Finite_vertices_iterator - vit = this->triangulation().finite_vertices_begin(), - end = this->triangulation().finite_vertices_end(); - vit != end; ++vit) - { - if ( vit->in_dimension() == 0 ) { - add_to_complex(vit, Corner_index(1)); - } - } - Base::rescan_after_load_of_triangulation(); -} - -template -std::ostream & -operator<< (std::ostream& os, - const Mesh_complex_3_in_triangulation_3 &c3t3) -{ - // TODO: implement edge saving - typedef typename Mesh_complex_3_in_triangulation_3::Concurrency_tag Concurrency_tag; - return os << static_cast< - const Mesh_3::Mesh_complex_3_in_triangulation_3_base&>(c3t3); -} - - -template -std::istream & -operator>> (std::istream& is, - Mesh_complex_3_in_triangulation_3 &c3t3) -{ - // TODO: implement edge loading - typedef typename Mesh_complex_3_in_triangulation_3::Concurrency_tag Concurrency_tag; - is >> static_cast< - Mesh_3::Mesh_complex_3_in_triangulation_3_base&>(c3t3); - c3t3.rescan_after_load_of_triangulation(); - return is; -} - -} //namespace CGAL - -#include - -#endif // CGAL_MESH_COMPLEX_3_IN_TRIANGULATION_3_H diff --git a/Mesh_3/include/CGAL/Mesh_triangulation_3.h b/Mesh_3/include/CGAL/Mesh_triangulation_3.h index 8d97e0696fe..5d4225225d3 100644 --- a/Mesh_3/include/CGAL/Mesh_triangulation_3.h +++ b/Mesh_3/include/CGAL/Mesh_triangulation_3.h @@ -28,7 +28,7 @@ #include #include -#include +#include namespace CGAL { diff --git a/Mesh_3/include/CGAL/Mesh_vertex_base_3.h b/Mesh_3/include/CGAL/Mesh_vertex_base_3.h index 91f0ab6f07e..6694284ccfc 100644 --- a/Mesh_3/include/CGAL/Mesh_vertex_base_3.h +++ b/Mesh_3/include/CGAL/Mesh_vertex_base_3.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include #include diff --git a/Mesh_3/include/CGAL/Polyhedral_mesh_domain_3.h b/Mesh_3/include/CGAL/Polyhedral_mesh_domain_3.h index ce7d0088fe3..256e92aadf8 100644 --- a/Mesh_3/include/CGAL/Polyhedral_mesh_domain_3.h +++ b/Mesh_3/include/CGAL/Polyhedral_mesh_domain_3.h @@ -59,7 +59,7 @@ // To handle I/O for Surface_patch_index if that is a pair of `int` (the // default) -#include +#include #include diff --git a/Mesh_3/include/CGAL/facets_in_complex_3_to_triangle_mesh.h b/Mesh_3/include/CGAL/facets_in_complex_3_to_triangle_mesh.h deleted file mode 100644 index d69f445716f..00000000000 --- a/Mesh_3/include/CGAL/facets_in_complex_3_to_triangle_mesh.h +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright (c) 2009-2017 GeometryFactory (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Maxime Gimeno, -// Mael Rouxel-Labbé - -#ifndef CGAL_FACETS_IN_COMPLEX_3_TO_TRIANGLE_MESH_H -#define CGAL_FACETS_IN_COMPLEX_3_TO_TRIANGLE_MESH_H - -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -namespace CGAL { - -namespace Mesh_3 { - -namespace internal { - -template -void resize(Polygon& p, std::size_t size) -{ - p.resize(size); -} - -template -void resize(std::array&, std::size_t CGAL_assertion_code(size)) -{ - CGAL_assertion(size == N); -} - -template -void facets_in_complex_3_to_triangle_soup(const C3T3& c3t3, - const typename C3T3::Subdomain_index sd_index, - PointContainer& points, - FaceContainer& faces, - const bool normals_point_outside_of_the_subdomain = true, - const bool export_all_facets = false) -{ - typedef typename PointContainer::value_type Point_3; - typedef typename FaceContainer::value_type Face; - - typedef typename C3T3::Triangulation Tr; - - typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Cell_handle Cell_handle; - typedef typename Tr::Weighted_point Weighted_point; - - typedef typename C3T3::Facets_in_complex_iterator Ficit; - - typedef CGAL::Hash_handles_with_or_without_timestamps Hash_fct; - typedef boost::unordered_map VHmap; - - typedef typename C3T3::size_type size_type; - - size_type nf = c3t3.number_of_facets_in_complex(); - faces.reserve(faces.size() + nf); - points.reserve(points.size() + nf/2); // approximating Euler - - VHmap vh_to_ids; - std::size_t inum = 0; - - for(Ficit fit = c3t3.facets_in_complex_begin(), - end = c3t3.facets_in_complex_end(); fit != end; ++fit) - { - Cell_handle c = fit->first; - int s = fit->second; - Face f; - resize(f, 3); - - typename C3T3::Subdomain_index cell_sdi = c3t3.subdomain_index(c); - typename C3T3::Subdomain_index opp_sdi = c3t3.subdomain_index(c->neighbor(s)); - - if(!export_all_facets && cell_sdi != sd_index && opp_sdi != sd_index) - continue; - - for(std::size_t i=1; i<4; ++i) - { - typename VHmap::iterator map_entry; - bool is_new; - Vertex_handle v = c->vertex((s+i)&3); - CGAL_assertion(v != Vertex_handle() && !c3t3.triangulation().is_infinite(v)); - - boost::tie(map_entry, is_new) = vh_to_ids.insert(std::make_pair(v, inum)); - if(is_new) - { - const Weighted_point& p = c3t3.triangulation().point(c, (s+i)&3); - const Point_3 bp = Point_3(CGAL::to_double(p.x()), - CGAL::to_double(p.y()), - CGAL::to_double(p.z())); - points.push_back(bp); - ++inum; - } - - f[i-1] = map_entry->second; - } - - if(export_all_facets) - { - if((cell_sdi > opp_sdi) == (s%2 == 1)) - std::swap(f[0], f[1]); - } - else - { - if(((cell_sdi == sd_index) == (s%2 == 1)) == normals_point_outside_of_the_subdomain) - std::swap(f[0], f[1]); - } - - faces.push_back(f); - } -} - -template -void facets_in_complex_3_to_triangle_soup(const C3T3& c3t3, - PointContainer& points, - FaceContainer& faces) -{ - typedef typename C3T3::Subdomain_index Subdomain_index; - Subdomain_index useless = Subdomain_index(); - facets_in_complex_3_to_triangle_soup(c3t3, useless, points, faces, - true/*point outward*/, true /*extract all facets*/); -} - -} // end namespace internal - -} // end namespace Mesh_3 - -//! \ingroup PkgMesh3Functions -//! -//! \brief builds a `TriangleMesh` from the surface facets, with a consistent orientation -//! at the interface of two subdomains. -//! -//! This function exports the surface as a `TriangleMesh` and appends it to `graph`, using -//! `orient_polygon_soup()`. -//! -//! @tparam C3T3 a model of `MeshComplexWithFeatures_3InTriangulation_3`. -//! @tparam TriangleMesh a model of `MutableFaceGraph` with an internal point property map. -//! The point type should be compatible with the one used in `C3T3`. -//! -//! @param c3t3 an instance of `C3T3`. -//! @param graph an instance of `TriangleMesh`. -template -void facets_in_complex_3_to_triangle_mesh(const C3T3& c3t3, TriangleMesh& graph) -{ - namespace PMP = CGAL::Polygon_mesh_processing; - - typedef typename boost::property_map::type VertexPointMap; - typedef typename boost::property_traits::value_type Point_3; - - typedef std::array Face; - - std::vector faces; - std::vector points; - - Mesh_3::internal::facets_in_complex_3_to_triangle_soup(c3t3, points, faces); - - if(!PMP::is_polygon_soup_a_polygon_mesh(faces)) - PMP::orient_polygon_soup(points, faces); - CGAL_postcondition(PMP::is_polygon_soup_a_polygon_mesh(faces)); - - PMP::polygon_soup_to_polygon_mesh(points, faces, graph); -} - -} // namespace CGAL - -#endif // CGAL_FACETS_IN_COMPLEX_3_TO_TRIANGLE_MESH_H diff --git a/Mesh_3/include/CGAL/refine_mesh_3.h b/Mesh_3/include/CGAL/refine_mesh_3.h index acbf847b26b..19f94e8787d 100644 --- a/Mesh_3/include/CGAL/refine_mesh_3.h +++ b/Mesh_3/include/CGAL/refine_mesh_3.h @@ -24,10 +24,10 @@ #include #include #include -#include #include #include #include +#include #include diff --git a/Mesh_3/package_info/Mesh_3/dependencies b/Mesh_3/package_info/Mesh_3/dependencies index 2bfb2043f8b..ef353eab235 100644 --- a/Mesh_3/package_info/Mesh_3/dependencies +++ b/Mesh_3/package_info/Mesh_3/dependencies @@ -19,6 +19,7 @@ Intersections_3 Interval_support Kernel_23 Kernel_d +MDS_3 Mesh_3 Mesher_level Modifier diff --git a/Mesh_3/test/Mesh_3/CMakeLists.txt b/Mesh_3/test/Mesh_3/CMakeLists.txt index f30b1c82b46..376aea84c2f 100644 --- a/Mesh_3/test/Mesh_3/CMakeLists.txt +++ b/Mesh_3/test/Mesh_3/CMakeLists.txt @@ -29,16 +29,12 @@ if ( CGAL_FOUND ) endif() create_single_source_cgal_program( "test_boost_has_xxx.cpp" ) - create_single_source_cgal_program( "test_c3t3.cpp" ) create_single_source_cgal_program( "test_mesh_capsule_var_distance_bound.cpp" ) create_single_source_cgal_program( "test_implicit_multi_domain_to_labeling_function_wrapper.cpp" ) - create_single_source_cgal_program( "test_c3t3_io.cpp" ) - create_single_source_cgal_program( "test_c3t3_with_features.cpp" ) create_single_source_cgal_program( "test_criteria.cpp" ) create_single_source_cgal_program( "test_domain_with_polyline_features.cpp" ) create_single_source_cgal_program( "test_labeled_mesh_domain_3.cpp" ) create_single_source_cgal_program( "test_mesh_criteria_creation.cpp" ) - create_single_source_cgal_program( "test_c3t3_into_facegraph.cpp" ) create_single_source_cgal_program( "test_without_detect_features.cpp" ) if(CGAL_ImageIO_USE_ZLIB) create_single_source_cgal_program( "test_meshing_3D_image.cpp" ) @@ -58,7 +54,6 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "test_meshing_unit_tetrahedron.cpp" ) create_single_source_cgal_program( "test_meshing_with_default_edge_size.cpp" ) create_single_source_cgal_program( "test_meshing_determinism.cpp" ) - create_single_source_cgal_program( "test_c3t3_extract_subdomains_boundaries.cpp" ) create_single_source_cgal_program( "test_mesh_3_issue_1554.cpp" ) create_single_source_cgal_program( "test_mesh_polyhedral_domain_with_features_deprecated.cpp" ) create_single_source_cgal_program( "test_meshing_with_one_step.cpp" ) @@ -66,16 +61,12 @@ if ( CGAL_FOUND ) foreach(target test_boost_has_xxx - test_c3t3 test_mesh_capsule_var_distance_bound test_implicit_multi_domain_to_labeling_function_wrapper - test_c3t3_io - test_c3t3_with_features test_criteria test_domain_with_polyline_features test_labeled_mesh_domain_3 test_mesh_criteria_creation - test_c3t3_into_facegraph test_without_detect_features test_meshing_3D_image test_meshing_3D_image_deprecated @@ -91,7 +82,6 @@ if ( CGAL_FOUND ) test_meshing_unit_tetrahedron test_meshing_with_default_edge_size test_meshing_determinism - test_c3t3_extract_subdomains_boundaries test_mesh_3_issue_1554 test_mesh_polyhedral_domain_with_features_deprecated test_mesh_cell_base_3 diff --git a/Mesh_3/test/Mesh_3/test_mesh_cell_base_3.cpp b/Mesh_3/test/Mesh_3/test_mesh_cell_base_3.cpp index 2a4bc5a5748..82130f77c59 100644 --- a/Mesh_3/test/Mesh_3/test_mesh_cell_base_3.cpp +++ b/Mesh_3/test/Mesh_3/test_mesh_cell_base_3.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include #include diff --git a/Mesh_3/test/Mesh_3/test_meshing_polyhedron.cpp b/Mesh_3/test/Mesh_3/test_meshing_polyhedron.cpp index b758086448e..6acba7b342b 100644 --- a/Mesh_3/test/Mesh_3/test_meshing_polyhedron.cpp +++ b/Mesh_3/test/Mesh_3/test_meshing_polyhedron.cpp @@ -15,14 +15,14 @@ // File Description : //****************************************************************************** -#include +#include #include "test_meshing_utilities.h" #include #include #include -#include +#include #include diff --git a/Mesh_3/test/Mesh_3/test_meshing_unit_tetrahedron.cpp b/Mesh_3/test/Mesh_3/test_meshing_unit_tetrahedron.cpp index 85989f0e485..8dd5fa81d70 100644 --- a/Mesh_3/test/Mesh_3/test_meshing_unit_tetrahedron.cpp +++ b/Mesh_3/test/Mesh_3/test_meshing_unit_tetrahedron.cpp @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include diff --git a/Periodic_3_mesh_3/include/CGAL/Periodic_3_mesh_3/IO/File_medit.h b/Periodic_3_mesh_3/include/CGAL/Periodic_3_mesh_3/IO/File_medit.h index dda69561ff2..84cc5434be6 100644 --- a/Periodic_3_mesh_3/include/CGAL/Periodic_3_mesh_3/IO/File_medit.h +++ b/Periodic_3_mesh_3/include/CGAL/Periodic_3_mesh_3/IO/File_medit.h @@ -308,7 +308,7 @@ void output_to_medit(std::ostream& os, #endif CGAL_precondition(c3t3.triangulation().is_1_cover()); - typedef CGAL::Mesh_3::Medit_pmap_generator Generator; + typedef CGAL::MDS_3::Medit_pmap_generator Generator; typedef typename Generator::Cell_pmap Cell_pmap; typedef typename Generator::Facet_pmap Facet_pmap; typedef typename Generator::Facet_pmap_twice Facet_pmap_twice; diff --git a/Periodic_3_mesh_3/include/CGAL/Periodic_3_mesh_3/Protect_edges_sizing_field.h b/Periodic_3_mesh_3/include/CGAL/Periodic_3_mesh_3/Protect_edges_sizing_field.h index 842abf61081..c394b70b9fc 100644 --- a/Periodic_3_mesh_3/include/CGAL/Periodic_3_mesh_3/Protect_edges_sizing_field.h +++ b/Periodic_3_mesh_3/include/CGAL/Periodic_3_mesh_3/Protect_edges_sizing_field.h @@ -31,12 +31,12 @@ #include -#include +#include #ifdef CGAL_MESH_3_DUMP_FEATURES_PROTECTION_ITERATIONS #include #endif #include -#include +#include #include #include @@ -75,7 +75,7 @@ namespace Periodic_3_mesh_3 { template class Protect_edges_sizing_field - : public CGAL::Mesh_3::internal::Debug_messages_tools + : public CGAL::MDS_3::internal::Debug_messages_tools { typedef Protect_edges_sizing_field Self; diff --git a/Periodic_3_mesh_3/include/CGAL/Periodic_3_mesh_triangulation_3.h b/Periodic_3_mesh_3/include/CGAL/Periodic_3_mesh_triangulation_3.h index 72f731760ec..7abce20f71f 100644 --- a/Periodic_3_mesh_3/include/CGAL/Periodic_3_mesh_triangulation_3.h +++ b/Periodic_3_mesh_3/include/CGAL/Periodic_3_mesh_triangulation_3.h @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include diff --git a/Periodic_3_mesh_3/include/CGAL/refine_periodic_3_mesh_3.h b/Periodic_3_mesh_3/include/CGAL/refine_periodic_3_mesh_3.h index acb3b35decd..b3a8c8f465f 100644 --- a/Periodic_3_mesh_3/include/CGAL/refine_periodic_3_mesh_3.h +++ b/Periodic_3_mesh_3/include/CGAL/refine_periodic_3_mesh_3.h @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include #include diff --git a/Periodic_3_mesh_3/package_info/Periodic_3_mesh_3/dependencies b/Periodic_3_mesh_3/package_info/Periodic_3_mesh_3/dependencies index c07e2af9cd5..9046a3843f9 100644 --- a/Periodic_3_mesh_3/package_info/Periodic_3_mesh_3/dependencies +++ b/Periodic_3_mesh_3/package_info/Periodic_3_mesh_3/dependencies @@ -16,6 +16,7 @@ Intersections_3 Interval_support Kernel_23 Kernel_d +MDS_3 Mesh_3 Mesher_level Modular_arithmetic @@ -34,4 +35,3 @@ Spatial_sorting Stream_support TDS_3 Triangulation_3 -Union_find diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h index 9e704870c18..e904ed5a2cc 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -74,9 +75,13 @@ public: m_pm(pm) { } - template + template //polygonindex-2-face void operator()(PolygonMesh& pmesh, VertexPointMap vpm, + V2V i2v, + F2F i2f, const bool insert_isolated_vertices = true) { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; @@ -109,6 +114,7 @@ public: vertices[i] = add_vertex(pmesh); PM_Point pi = convert_to_pm_point(get(m_pm, m_points[i])); put(vpm, vertices[i], pi); + *i2v++ = std::make_pair(i, vertices[i]); } for(std::size_t i = 0, end = m_polygons.size(); i < end; ++i) @@ -121,9 +127,10 @@ public: for(std::size_t j = 0; j < size; ++j) vr[j] = vertices[polygon[j] ]; - CGAL_assertion_code(typename boost::graph_traits::face_descriptor fd =) + typename boost::graph_traits::face_descriptor fd = CGAL::Euler::add_face(vr, pmesh); CGAL_assertion(fd != boost::graph_traits::null_face()); + *i2f++ = std::make_pair(i, fd); } } @@ -131,7 +138,11 @@ public: void operator()(PolygonMesh& pmesh, const bool insert_isolated_vertices = true) { - return operator()(pmesh, get(CGAL::vertex_point, pmesh), insert_isolated_vertices); + return operator()(pmesh, + get(CGAL::vertex_point, pmesh), + CGAL::Emptyset_iterator(), + CGAL::Emptyset_iterator(), + insert_isolated_vertices); } private: @@ -248,6 +259,23 @@ bool is_polygon_soup_a_polygon_mesh(const PolygonRange& polygons) * of the vertex point map associated to the polygon mesh} * \cgalParamDefault{`CGAL::Identity_property_map`} * \cgalParamNEnd +* +* \cgalParamNBegin{point_to_vertex_output_iterator} +* \cgalParamDescription{an `OutputIterator` containing the pairs source-vertex-index +* from `points`, target-vertex.} +* \cgalParamType{a class model of `OutputIterator` accepting +* `std::pair<`int`, `boost::graph_traits::%vertex_descriptor>`} +* \cgalParamDefault{`Emptyset_iterator`} +* \cgalParamNEnd +* +* \cgalParamNBegin{polygon_to_face_output_iterator} +* \cgalParamDescription{an `OutputIterator` containing the pairs polygon-index +* from `polygons`, target-face.} +* \cgalParamType{a class model of `OutputIterator` accepting +* `std::pair<`int`, `boost::graph_traits::%face_descriptor>`} +* \cgalParamDefault{`Emptyset_iterator`} +* \cgalParamNEnd +* * \cgalNamedParamsEnd * * @param np_pm an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below @@ -290,7 +318,11 @@ void polygon_soup_to_polygon_mesh(const PointRange& points, get_property_map(CGAL::vertex_point, out)); internal::PS_to_PM_converter converter(points, polygons, pm); - converter(out, vpm); + converter(out, vpm, + choose_parameter(get_parameter(np_ps, internal_np::point_to_vertex_output_iterator), + impl::make_functor(get_parameter(np_ps, internal_np::vertex_to_vertex_map))), + choose_parameter(get_parameter(np_ps, internal_np::polygon_to_face_output_iterator), + impl::make_functor(get_parameter(np_ps, internal_np::face_to_face_map)))); } /// \cond SKIP_IN_MANUAL diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index 12616332198..cb4fa8cbfe9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -10,7 +10,7 @@ // Jane Tournois // -#include +#include #include #include "Scene_surface_mesh_item.h" @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include @@ -420,9 +420,9 @@ public: std::swap(finite_cells[i][1], finite_cells[i][3]); } } - std::vector new_vertices; - CGAL::build_triangulation(c3t3_item->c3t3().triangulation(), - points, finite_cells, border_facets, new_vertices); + + CGAL::MDS_3::build_triangulation(c3t3_item->c3t3().triangulation(), + points, finite_cells, border_facets); for( C3t3::Triangulation::Finite_cells_iterator cit = c3t3_item->c3t3().triangulation().finite_cells_begin(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp index e2e77c8faff..d51fcdca8b4 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp @@ -1,6 +1,6 @@ -#include +#include #include "Scene_c3t3_item.h" -#include +#include #include #include #include @@ -127,7 +127,7 @@ Polyhedron_demo_c3t3_binary_io_plugin::load( item->setName(fileinfo.baseName()); item->set_valid(false); - if(CGAL::build_triangulation_from_file(in, item->c3t3().triangulation(), true)) + if(CGAL::MDS_3::build_triangulation_from_file(in, item->c3t3().triangulation(), true)) { item->c3t3().rescan_after_load_of_triangulation(); for( C3t3::Triangulation::Finite_cells_iterator diff --git a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp index 3b604818e77..8dda4174ed8 100644 --- a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp @@ -1168,9 +1168,20 @@ double Scene_c3t3_item_priv::complex_diag() const { void Scene_c3t3_item::export_facets_in_complex() { SMesh outmesh; - CGAL::facets_in_complex_3_to_triangle_mesh(c3t3(), outmesh); - Scene_surface_mesh_item* item = new Scene_surface_mesh_item(std::move(outmesh)); + Scene_surface_mesh_item* item = new Scene_surface_mesh_item(outmesh); + item->setItemIsMulticolor(true); + + boost::property_map >::type + fpmap = get(CGAL::face_patch_id_t(), *item->face_graph()); + + CGAL::facets_in_complex_3_to_triangle_mesh(c3t3(), + *item->face_graph(), + CGAL::parameters::face_patch_map(fpmap)); + + item->computeItemColorVectorAutomatically(true); + item->invalidateOpenGLBuffers(); item->setName(QString("%1_%2").arg(this->name()).arg("facets")); + scene->addItem(item); this->setVisible(false); } diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies index 30913764fab..14160e269fd 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies @@ -8,3 +8,4 @@ Triangulation_3 BGL Mesh_3 TDS_3 +MDS_3 diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 4ce1fe25af0..5d2275eb335 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -28,7 +28,7 @@ #include #include -#include +#include #include #include @@ -109,9 +109,9 @@ public: // finished std::vector new_vertices; std::map border_facets; - if (CGAL::build_triangulation(triangulation, - points, finite_cells, border_facets, - new_vertices, false/*verbose*/)) + if (CGAL::MDS_3::build_triangulation(triangulation, + points, finite_cells, border_facets, + new_vertices /*, verbose*/)) { CGAL_assertion(triangulation.tds().is_valid()); CGAL_assertion(triangulation.infinite_vertex() == new_vertices[0]); diff --git a/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies index 2311653695c..b90ad8d775b 100644 --- a/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies +++ b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies @@ -14,6 +14,7 @@ Intersections_3 Interval_support Kernel_23 Kernel_d +MDS_3 Mesh_3 Modular_arithmetic Number_types diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_from_mesh_file.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_from_mesh_file.cpp index cb748e0e92b..a00b07d21cf 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_from_mesh_file.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_from_mesh_file.cpp @@ -10,7 +10,7 @@ #include #include -#include +#include typedef CGAL::Exact_predicates_inexact_constructions_kernel K;