From 54412d7b5887a0c812642fc8770165b988ed3798 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 27 Aug 2026 12:44:03 +0100 Subject: [PATCH 01/72] Stream_support: Add write_MEDIT() for a tetrahedron soup --- .../File_formats/Supported_file_formats.txt | 3 +- .../doc/Stream_support/IOstream.txt | 2 +- Stream_support/include/CGAL/IO/MEDIT.h | 51 +++++++++++++++++++ .../include/CGAL/IO/polygon_soup_io.h | 2 +- .../test/Stream_support/test_MEDIT.cpp | 14 +++++ 5 files changed, 69 insertions(+), 3 deletions(-) diff --git a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt index 077204618144..e3070028e1e2 100644 --- a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt +++ b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt @@ -556,8 +556,9 @@ The following \cgal data structures can be exported into the `.mesh` file format - `CGAL::Conforming_constrained_Delaunay_triangulation_3`, using the function \link CGAL::IO::write_MEDIT(std::ostream &os, const CGAL::Conforming_constrained_Delaunay_triangulation_3< Traits, Tr > &ccdt, const NamedParameters& np) `CGAL::IO::write_MEDIT()` \endlink. -The following function enables to read into a tetrahedron soup +The following function enables to read and write a tetrahedron soup - \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, CellRange&, std::vector&,bool) `CGAL::IO::read_MEDIT()` \endlink +- \link CGAL::IO::write_MEDIT(std::ostream&, PointRange&, CellRange&, std::vector&,bool) `CGAL::IO::writeMEDIT()` \endlink \section IOStreamTetgen Tetgen File Format diff --git a/Stream_support/doc/Stream_support/IOstream.txt b/Stream_support/doc/Stream_support/IOstream.txt index fbfb08677868..770369c4a8bf 100644 --- a/Stream_support/doc/Stream_support/IOstream.txt +++ b/Stream_support/doc/Stream_support/IOstream.txt @@ -506,7 +506,7 @@ which can perform some combinatorial repairing to ensure the input data is a 2-m \ref IOStreamMedit "MEDIT" \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, CellRange&, std::vector&,bool) `CGAL::IO::read_MEDIT()` \endlink -
-
+ \link CGAL::IO::write_MEDIT(std::ostream&, PointRange&, CellRange&, std::vector&,bool) `CGAL::IO::write_MEDIT()` \endlink diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 8e3d1fab4083..3a9f411d3f56 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -281,6 +281,57 @@ bool read_MEDIT(std::istream& is, read_border_facets, verbose, is_CGAL_mesh); } + +/*! + * \ingroup PkgStreamSupportIoFuncsMEDIT + * + * \brief writes the `points` and `finite_cells`. + * + * See \cgalCite{frey:inria-00069921} for a comprehensive description of the medit (`.mesh`) file format. + * + * + * \tparam PointRange a model of the concept `RandomAccessContainer` whose value type is the point type + * \tparam CellRange a model of the concept `RandomAccessContainer` + * whose `value_type` is a model of the concept `RandomAccessContainer` + * whose `value_type` is `std::size_t`. + * + * \param os the output stream + * \param points points of the soup of cells + * \param finite_cells each element in it describes a cell + * using the indices of the points in `points` + * \param subdomains each element in it describes the subdomain index of the corresponding cell in `finite_cells` + * + * \returns `true` if the writing was successful, `false` otherwise. + * + * \see \ref IOStreamMedit + */ + +template +bool write_MEDIT(std::ostream& os, + const PointRange& points, + const CellRange& finite_cells, + const std::vector& subdomains) + +{ + using Point_3 = typename PointRange::value_type; + + if(!os) + return false; + os << "MeshVersionFormatted 1\nDimension 3\nVertices\n"; + os << points.size() << "\n"; + for (const Point_3& p : points) + os << p << " 0\n"; + os << "Triangles\n0\nTetrahedra\n"; + os << finite_cells.size() << "\n"; + for (std::size_t k=0; k #include #include +#include #include typedef CGAL::Simple_cartesian Kernel; @@ -16,5 +17,18 @@ int main() { bool verbose = false; bool success = CGAL::IO::read_MEDIT(input, points, cells, subdomains, verbose); assert(success); + + std::ostringstream output; + output.precision(17); + CGAL::IO::write_MEDIT(output, points, cells, subdomains); + std::istringstream input2(output.str()); + std::vector points2; + std::vector> cells2; + std::vector subdomains2; + success = CGAL::IO::read_MEDIT(input2, points2, cells2, subdomains2, verbose); + assert(points == points2); + assert(cells == cells2); + assert(subdomains == subdomains2); + assert(success); return 0; } From 1013a9abd541a2cfb32538d7e8ce0c5d2caf41fe Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 27 Aug 2026 12:57:10 +0100 Subject: [PATCH 02/72] Fix signature in link --- .../Stream_support/File_formats/Supported_file_formats.txt | 2 +- Stream_support/doc/Stream_support/IOstream.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt index e3070028e1e2..80fdd2c1ceb4 100644 --- a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt +++ b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt @@ -558,7 +558,7 @@ The following \cgal data structures can be exported into the `.mesh` file format The following function enables to read and write a tetrahedron soup - \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, CellRange&, std::vector&,bool) `CGAL::IO::read_MEDIT()` \endlink -- \link CGAL::IO::write_MEDIT(std::ostream&, PointRange&, CellRange&, std::vector&,bool) `CGAL::IO::writeMEDIT()` \endlink +- \link CGAL::IO::write_MEDIT(std::ostream&, PointRange&, CellRange&, std::vector&) `CGAL::IO::writeMEDIT()` \endlink \section IOStreamTetgen Tetgen File Format diff --git a/Stream_support/doc/Stream_support/IOstream.txt b/Stream_support/doc/Stream_support/IOstream.txt index 770369c4a8bf..79500b0f2fb2 100644 --- a/Stream_support/doc/Stream_support/IOstream.txt +++ b/Stream_support/doc/Stream_support/IOstream.txt @@ -505,8 +505,8 @@ which can perform some combinatorial repairing to ensure the input data is a 2-m \ref IOStreamMedit "MEDIT" - \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, CellRange&, std::vector&,bool) `CGAL::IO::read_MEDIT()` \endlink - \link CGAL::IO::write_MEDIT(std::ostream&, PointRange&, CellRange&, std::vector&,bool) `CGAL::IO::write_MEDIT()` \endlink + \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, CellRange&, std::vector&, bool) `CGAL::IO::read_MEDIT()` \endlink + \link CGAL::IO::write_MEDIT(std::ostream&, PointRange&, CellRange&, std::vector&) `CGAL::IO::write_MEDIT()` \endlink From 4b16c9c15d9a4e9063b30365e0ebe5bdf61c3a75 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 27 Aug 2026 13:18:46 +0100 Subject: [PATCH 03/72] Fix signature in link --- .../doc/Stream_support/File_formats/Supported_file_formats.txt | 2 +- Stream_support/doc/Stream_support/IOstream.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt index 80fdd2c1ceb4..9545e48d738e 100644 --- a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt +++ b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt @@ -558,7 +558,7 @@ The following \cgal data structures can be exported into the `.mesh` file format The following function enables to read and write a tetrahedron soup - \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, CellRange&, std::vector&,bool) `CGAL::IO::read_MEDIT()` \endlink -- \link CGAL::IO::write_MEDIT(std::ostream&, PointRange&, CellRange&, std::vector&) `CGAL::IO::writeMEDIT()` \endlink +- \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const CellRange&, const std::vector&) `CGAL::IO::writeMEDIT()` \endlink \section IOStreamTetgen Tetgen File Format diff --git a/Stream_support/doc/Stream_support/IOstream.txt b/Stream_support/doc/Stream_support/IOstream.txt index 79500b0f2fb2..a48d9f84e351 100644 --- a/Stream_support/doc/Stream_support/IOstream.txt +++ b/Stream_support/doc/Stream_support/IOstream.txt @@ -506,7 +506,7 @@ which can perform some combinatorial repairing to ensure the input data is a 2-m \ref IOStreamMedit "MEDIT" \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, CellRange&, std::vector&, bool) `CGAL::IO::read_MEDIT()` \endlink - \link CGAL::IO::write_MEDIT(std::ostream&, PointRange&, CellRange&, std::vector&) `CGAL::IO::write_MEDIT()` \endlink + \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const CellRange&, const std::vector&) `CGAL::IO::write_MEDIT()` \endlink From d1c6d22d9477da9690d08d05a86588035ca69ea3 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 28 Aug 2026 10:35:42 +0100 Subject: [PATCH 04/72] rename tparams and params --- Stream_support/include/CGAL/IO/MEDIT.h | 54 +++++++++++++------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 3a9f411d3f56..2cec7ea23c57 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -32,10 +32,10 @@ namespace CGAL { namespace IO { namespace internal { -template +template bool read_MEDIT(std::istream& is, PointRange& points, - CellRange& finite_cells, + TetrahedronRange& tetrahedra, std::vector& subdomains, boost::unordered_map,SurfacePatchIndex_ >& border_facets, bool read_border_facets, @@ -217,7 +217,7 @@ bool read_MEDIT(std::istream& is, t[2] = offset + n[2] - 1; t[3] = offset + n[3] - 1; - finite_cells.push_back(t); + tetrahedra.push_back(t); subdomains.push_back(reference); } } @@ -227,13 +227,13 @@ bool read_MEDIT(std::istream& is, { std::cout << points.size() - std::size_t(offset) << " points" << std::endl; std::cout << border_facets.size() << " border facets" << std::endl; - std::cout << finite_cells.size() << " cells" << std::endl; + std::cout << tetrahedra.size() << " cells" << std::endl; } - if(finite_cells.empty()) + if(tetrahedra.empty()) return false; - CGAL_assertion(finite_cells.size() == subdomains.size()); + CGAL_assertion(tetrahedra.size() == subdomains.size()); return true; } @@ -245,20 +245,20 @@ bool read_MEDIT(std::istream& is, /*! * \ingroup PkgStreamSupportIoFuncsMEDIT * - * \brief reads the content of `is` into `points` and `finite_cells`. + * \brief reads the content of `is` into `points` and `tetrahedra`. * * See \cgalCite{frey:inria-00069921} for a comprehensive description of the medit (`.mesh`) file format. * - * \attention The cell soup is not cleared, and the data from the stream are appended. + * \attention The tetrahedron soup is not cleared, and the data from the stream are appended. * * \tparam PointRange a model of the concept `BackInsertionSequence` whose value type is the point type - * \tparam CellRange a model of the concept `BackInsertionSequence` whose `value_type` is `std::array` + * \tparam TetrahedronRange a model of the concept `BackInsertionSequence` whose `value_type` is `std::array` * * \param is the input stream * \param points points of the soup of cells - * \param finite_cells each element in it describes a cell + * \param tetrahedra each element in it describes a tetrahedron * using the indices of the points in `points` - * \param subdomains each element in it describes the subdomain index of the corresponding cell in `finite_cells` + * \param subdomains each element in it describes the subdomain index of the corresponding tetrahedron * \param verbose if `true`, prints information about the reading process * * \returns `true` if the reading was successful, `false` otherwise. @@ -266,10 +266,10 @@ bool read_MEDIT(std::istream& is, * \see \ref IOStreamMedit */ -template +template bool read_MEDIT(std::istream& is, PointRange& points, - CellRange& finite_cells, + TetrahedronRange& tetrahedra, std::vector& subdomains, bool verbose = false) @@ -277,7 +277,7 @@ bool read_MEDIT(std::istream& is, boost::unordered_map,int > border_facets; constexpr bool read_border_facets = false; bool is_CGAL_mesh; - return internal::read_MEDIT(is, points, finite_cells, subdomains, border_facets, + return internal::read_MEDIT(is, points, tetrahedra, subdomains, border_facets, read_border_facets, verbose, is_CGAL_mesh); } @@ -285,31 +285,31 @@ bool read_MEDIT(std::istream& is, /*! * \ingroup PkgStreamSupportIoFuncsMEDIT * - * \brief writes the `points` and `finite_cells`. + * \brief writes the `points` and `tetrahedra`. * * See \cgalCite{frey:inria-00069921} for a comprehensive description of the medit (`.mesh`) file format. * * - * \tparam PointRange a model of the concept `RandomAccessContainer` whose value type is the point type - * \tparam CellRange a model of the concept `RandomAccessContainer` + * \tparam PointRange a model of the concept `ConstRange` whose value type is the point type + * \tparam TetrahedronRange a model of the concept `ConstRange` * whose `value_type` is a model of the concept `RandomAccessContainer` * whose `value_type` is `std::size_t`. * * \param os the output stream * \param points points of the soup of cells - * \param finite_cells each element in it describes a cell + * \param tetrahedra each element in it describes a cell * using the indices of the points in `points` - * \param subdomains each element in it describes the subdomain index of the corresponding cell in `finite_cells` + * \param subdomains each element in it describes the subdomain index of the corresponding tetrahedron * * \returns `true` if the writing was successful, `false` otherwise. * * \see \ref IOStreamMedit */ -template +template bool write_MEDIT(std::ostream& os, const PointRange& points, - const CellRange& finite_cells, + const TetrahedronRange& tetrahedra, const std::vector& subdomains) { @@ -322,12 +322,12 @@ bool write_MEDIT(std::ostream& os, for (const Point_3& p : points) os << p << " 0\n"; os << "Triangles\n0\nTetrahedra\n"; - os << finite_cells.size() << "\n"; - for (std::size_t k=0; k Date: Fri, 28 Aug 2026 11:09:48 +0100 Subject: [PATCH 05/72] Fix links --- .../Stream_support/File_formats/Supported_file_formats.txt | 4 ++-- Stream_support/doc/Stream_support/IOstream.txt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt index 9545e48d738e..ffacbc21f36a 100644 --- a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt +++ b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt @@ -557,8 +557,8 @@ The following \cgal data structures can be exported into the `.mesh` file format \link CGAL::IO::write_MEDIT(std::ostream &os, const CGAL::Conforming_constrained_Delaunay_triangulation_3< Traits, Tr > &ccdt, const NamedParameters& np) `CGAL::IO::write_MEDIT()` \endlink. The following function enables to read and write a tetrahedron soup -- \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, CellRange&, std::vector&,bool) `CGAL::IO::read_MEDIT()` \endlink -- \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const CellRange&, const std::vector&) `CGAL::IO::writeMEDIT()` \endlink +- \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, TetrahedronRange&, std::vector&,bool) `CGAL::IO::read_MEDIT()` \endlink +- \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const TetrahedronRange&, const std::vector&) `CGAL::IO::writeMEDIT()` \endlink \section IOStreamTetgen Tetgen File Format diff --git a/Stream_support/doc/Stream_support/IOstream.txt b/Stream_support/doc/Stream_support/IOstream.txt index a48d9f84e351..716e0aace41c 100644 --- a/Stream_support/doc/Stream_support/IOstream.txt +++ b/Stream_support/doc/Stream_support/IOstream.txt @@ -505,8 +505,8 @@ which can perform some combinatorial repairing to ensure the input data is a 2-m \ref IOStreamMedit "MEDIT" - \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, CellRange&, std::vector&, bool) `CGAL::IO::read_MEDIT()` \endlink - \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const CellRange&, const std::vector&) `CGAL::IO::write_MEDIT()` \endlink + \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, TetrahedronRange&, std::vector&, bool) `CGAL::IO::read_MEDIT()` \endlink + \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const TetrahedronRange&, const std::vector&) `CGAL::IO::write_MEDIT()` \endlink From 891527f440d27c67f95f29c1a0fad6d2da195be7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 31 Aug 2026 18:36:54 +0200 Subject: [PATCH 06/72] compatibility with other PR --- Stream_support/include/CGAL/IO/MEDIT.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 0640f5cb3a00..f6c2ff4b343d 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -46,7 +46,7 @@ bool read_MEDIT(std::istream& is, using FT = typename Kernel_traits::Kernel::FT; using Surface_patch_index = SurfacePatchIndex_; using Facet = std::array; - using Tet_with_ref = typename std::iterator_traits::value_type; + using Tet_with_ref = typename std::iterator_traits::value_type; if(!is) return false; From 7075ea514ec57a87748887bf150c102c956bb130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 15 Sep 2026 23:09:27 +0200 Subject: [PATCH 07/72] API proposal for read/write_MEDIT --- .../Linear_cell_complex/tetsoup_to_lcc.cpp | 2 +- .../internal/parameters_interface.h | 4 +- Stream_support/include/CGAL/IO/MEDIT.h | 80 +++++++++++++++---- .../test/Stream_support/test_MEDIT.cpp | 6 +- 4 files changed, 72 insertions(+), 20 deletions(-) diff --git a/Linear_cell_complex/examples/Linear_cell_complex/tetsoup_to_lcc.cpp b/Linear_cell_complex/examples/Linear_cell_complex/tetsoup_to_lcc.cpp index a57e78dd4a54..4aa49392d7f8 100644 --- a/Linear_cell_complex/examples/Linear_cell_complex/tetsoup_to_lcc.cpp +++ b/Linear_cell_complex/examples/Linear_cell_complex/tetsoup_to_lcc.cpp @@ -23,7 +23,7 @@ int main(int argc, char** argv) return 1; } - CGAL::IO::read_MEDIT(in, points, tetras, subdomains); + CGAL::IO::read_MEDIT(in, points, tetras, CGAL::parameters::subdomains(std::ref(subdomains))); //filter out subdomain 0 std::vector> filtered_tetras; diff --git a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h index fef884f49917..ada53548adb8 100644 --- a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h +++ b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h @@ -68,6 +68,8 @@ CGAL_add_named_parameter(output_color_t, output_color, output_color) CGAL_add_named_parameter(stream_precision_t, stream_precision, stream_precision) CGAL_add_named_parameter(read_only_one_object_t, read_only_one_object, read_only_one_object) +CGAL_add_named_parameter(subdomains_t, subdomains, subdomains) + // List of named parameters that we use in the package 'Mesh_3' CGAL_add_named_parameter(vertex_feature_degree_t, vertex_feature_degree, vertex_feature_degree_map) @@ -434,7 +436,7 @@ CGAL_add_named_parameter_with_compatibility(cell_min_size_param_t, cell_min_size CGAL_add_named_parameter_with_compatibility(function_param_t, function_param, function) CGAL_add_named_parameter_with_compatibility(bounding_object_param_t, bounding_object_param, bounding_object) -// List of named parameters used in the package ' 3D Surface Subdivision Methods' +// List of named parameters used in the package '3D Surface Subdivision Methods' CGAL_add_named_parameter(do_not_modify_geometry_t, do_not_modify_geometry, do_not_modify_geometry) //List of named parameters used in Straight_skeleton_2 diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index bb6c91ae4315..f3aa39d78c6b 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -49,16 +50,16 @@ struct Corner_with_index template + class Edge_with_index_, // either Edge_with_index or a tuple + class Corner_with_index_> // either Corner_with_index or a tuple/pair bool read_MEDIT(std::istream& is, PointRange& points, TetrahedronRange& tetrahedra, std::vector& subdomains, boost::unordered_map,SurfacePatchIndex_ >& border_facets, bool read_border_facets, - std::vector>& edge_indices, - std::vector>& corner_indices, + std::vector& edge_indices, + std::vector& corner_indices, bool verbose, bool& is_CGAL_mesh) { @@ -67,7 +68,6 @@ bool read_MEDIT(std::istream& is, using Surface_patch_index = SurfacePatchIndex_; using Facet = std::array; using Tet_with_ref = typename std::iterator_traits::value_type; - using Corner_index = CornerIndex_; if(!is) return false; @@ -243,7 +243,7 @@ bool read_MEDIT(std::istream& is, } } - Corner_index corner_index = 0; + int corner_index = 0; if(line.find("Corners") != std::string::npos) { is >> ncorners; @@ -323,21 +323,48 @@ bool read_MEDIT(std::istream& is, * \param tetrahedra each element in it describes a tetrahedron * using the indices of the points in `points` * \param subdomains each element in it describes the subdomain index of the corresponding tetrahedron - * \param verbose if `true`, prints information about the reading process + * + * \param np optional \ref bgl_namedparameters "Named Parameters" described below + * + * \cgalNamedParamsBegin + * + * \cgalParamNBegin{subdomains} + * \cgalParamDescription{a non-const reference wrapper to a container of integer that will be filled by this function. + * Each element in the container indicates the subdomain index of the corresponding tetrahedron at the same position.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` able to store `int`.} + * \cgalParamDefault{subdomains are ignored} + * \cgalParamNEnd + * + * \cgalParamNBegin{verbose} + * \cgalParamDescription{if true, prints information about the reading process.} + * \cgalParamType{Boolean} + * \cgalParamDefault{`false`} + * \cgalParamNEnd + * + * \cgalNamedParamsEnd * * \returns `true` if the reading was successful, `false` otherwise. * * \see \ref IOStreamMedit */ -template +template bool read_MEDIT(std::istream& is, PointRange& points, TetrahedronRange& tetrahedra, - std::vector& subdomains, - bool verbose = false) - + const CGAL_NP_CLASS& np = parameters::default_values()) { + using parameters::choose_parameter; + using parameters::get_parameter; + using parameters::get_parameter_reference; + + const bool verbose = choose_parameter(get_parameter(np, internal_np::verbose), false); + + // subdomains + std::vector default_subdomains; + using Subdomains = typename internal_np::Lookup_named_param_def>::reference; + Subdomains subdomains = choose_parameter(get_parameter_reference(np, internal_np::subdomains), default_subdomains); + boost::unordered_map,int > border_facets; constexpr bool read_border_facets = false; std::vector> edge_indices; @@ -368,24 +395,47 @@ bool read_MEDIT(std::istream& is, * \param points points of the soup of cells * \param tetrahedra each element in it describes a cell * using the indices of the points in `points` - * \param subdomains each element in it describes the subdomain index of the corresponding tetrahedron + * + * \param np optional \ref bgl_namedparameters "Named Parameters" described below + * + * \cgalNamedParamsBegin + * \cgalParamNBegin{subdomains} + * \cgalParamDescription{a reference wrapper to a container of integer of the same size as `tetrahedra`. + * Each element in the container indicates the subdomain index of the corresponding tetrahedron at the same position.} + * \cgalParamType{a `std::reference_wrapper` to a model of the concept `RandomAccessContainer` of integer.} + * \cgalParamDefault{all tetrahedra will have the subdomain id `1`.} + * \cgalParamNEnd + * \cgalNamedParamsEnd * * \returns `true` if the writing was successful, `false` otherwise. * * \see \ref IOStreamMedit */ - -template +template bool write_MEDIT(std::ostream& os, const PointRange& points, const TetrahedronRange& tetrahedra, - const std::vector& subdomains) + const CGAL_NP_CLASS& np = parameters::default_values()) { + using parameters::choose_parameter; + using parameters::get_parameter; + using parameters::get_parameter_reference; + using parameters::is_default_parameter; + using Point_3 = typename PointRange::value_type; if(!os) return false; + + // subdomains + std::vector default_subdomains; + using Subdomains = typename internal_np::Lookup_named_param_def>::reference; + Subdomains subdomains = choose_parameter(get_parameter_reference(np, internal_np::subdomains), default_subdomains); + + if constexpr (is_default_parameter::value) + default_subdomains.resize(tetrahedra.size(), 1); + os << "MeshVersionFormatted 1\nDimension 3\nVertices\n"; os << points.size() << "\n"; for (const Point_3& p : points) diff --git a/Stream_support/test/Stream_support/test_MEDIT.cpp b/Stream_support/test/Stream_support/test_MEDIT.cpp index fc4fa4db4bbc..aebdc7763e23 100644 --- a/Stream_support/test/Stream_support/test_MEDIT.cpp +++ b/Stream_support/test/Stream_support/test_MEDIT.cpp @@ -15,17 +15,17 @@ int main() { std::vector subdomains; std::vector> cells; bool verbose = false; - bool success = CGAL::IO::read_MEDIT(input, points, cells, subdomains, verbose); + bool success = CGAL::IO::read_MEDIT(input, points, cells, CGAL::parameters::subdomains(std::ref(subdomains)).verbose(verbose)); assert(success); std::ostringstream output; output.precision(17); - CGAL::IO::write_MEDIT(output, points, cells, subdomains); + CGAL::IO::write_MEDIT(output, points, cells, CGAL::parameters::subdomains(std::cref(subdomains))); std::istringstream input2(output.str()); std::vector points2; std::vector> cells2; std::vector subdomains2; - success = CGAL::IO::read_MEDIT(input2, points2, cells2, subdomains2, verbose); + success = CGAL::IO::read_MEDIT(input2, points2, cells2, CGAL::parameters::subdomains(std::ref(subdomains2)).verbose(verbose)); assert(points == points2); assert(cells == cells2); assert(subdomains == subdomains2); From b39e47160e6387e213f785861e41021f93c5b503 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 16 Sep 2026 11:42:28 +0100 Subject: [PATCH 08/72] make the trivial fixes --- .../File_formats/Supported_file_formats.txt | 2 +- Stream_support/include/CGAL/IO/MEDIT.h | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt index ffacbc21f36a..9b0071230ce4 100644 --- a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt +++ b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt @@ -557,7 +557,7 @@ The following \cgal data structures can be exported into the `.mesh` file format \link CGAL::IO::write_MEDIT(std::ostream &os, const CGAL::Conforming_constrained_Delaunay_triangulation_3< Traits, Tr > &ccdt, const NamedParameters& np) `CGAL::IO::write_MEDIT()` \endlink. The following function enables to read and write a tetrahedron soup -- \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, TetrahedronRange&, std::vector&,bool) `CGAL::IO::read_MEDIT()` \endlink +- \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, TetrahedronRange&, const NamedParameters&) `CGAL::IO::read_MEDIT()` \endlink - \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const TetrahedronRange&, const std::vector&) `CGAL::IO::writeMEDIT()` \endlink \section IOStreamTetgen Tetgen File Format diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index f3aa39d78c6b..20f0203abd1e 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -50,16 +50,16 @@ struct Corner_with_index template // either Corner_with_index or a tuple/pair + class EdgeWithIndex_, // either Edge_with_index or a tuple + class CornerWithIndex_> // either Corner_with_index or a tuple/pair bool read_MEDIT(std::istream& is, PointRange& points, TetrahedronRange& tetrahedra, std::vector& subdomains, boost::unordered_map,SurfacePatchIndex_ >& border_facets, bool read_border_facets, - std::vector& edge_indices, - std::vector& corner_indices, + std::vector& edge_indices, + std::vector& corner_indices, bool verbose, bool& is_CGAL_mesh) { @@ -329,14 +329,14 @@ bool read_MEDIT(std::istream& is, * \cgalNamedParamsBegin * * \cgalParamNBegin{subdomains} - * \cgalParamDescription{a non-const reference wrapper to a container of integer that will be filled by this function. + * \cgalParamDescription{a non-const reference wrapper to a container of integers that will be filled by this function. * Each element in the container indicates the subdomain index of the corresponding tetrahedron at the same position.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` able to store `int`.} * \cgalParamDefault{subdomains are ignored} * \cgalParamNEnd * * \cgalParamNBegin{verbose} - * \cgalParamDescription{if true, prints information about the reading process.} + * \cgalParamDescription{if `true`, prints information about the reading process.} * \cgalParamType{Boolean} * \cgalParamDefault{`false`} * \cgalParamNEnd @@ -400,7 +400,7 @@ bool read_MEDIT(std::istream& is, * * \cgalNamedParamsBegin * \cgalParamNBegin{subdomains} - * \cgalParamDescription{a reference wrapper to a container of integer of the same size as `tetrahedra`. + * \cgalParamDescription{a reference wrapper to a container of integers of the same size as `tetrahedra`. * Each element in the container indicates the subdomain index of the corresponding tetrahedron at the same position.} * \cgalParamType{a `std::reference_wrapper` to a model of the concept `RandomAccessContainer` of integer.} * \cgalParamDefault{all tetrahedra will have the subdomain id `1`.} From bc0a5bf6a8e0a4165acb09f133576cabc0c2e23c Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 16 Sep 2026 11:43:24 +0100 Subject: [PATCH 09/72] make the trivial fixes --- .../doc/Stream_support/File_formats/Supported_file_formats.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt index 9b0071230ce4..aa942e9a7946 100644 --- a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt +++ b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt @@ -558,7 +558,7 @@ The following \cgal data structures can be exported into the `.mesh` file format The following function enables to read and write a tetrahedron soup - \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, TetrahedronRange&, const NamedParameters&) `CGAL::IO::read_MEDIT()` \endlink -- \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const TetrahedronRange&, const std::vector&) `CGAL::IO::writeMEDIT()` \endlink +- \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const TetrahedronRange&, const NamedParameters&) `CGAL::IO::writeMEDIT()` \endlink \section IOStreamTetgen Tetgen File Format From 4518ad340129045e4adad0f449180bf536f6e690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 16 Sep 2026 22:17:45 +0200 Subject: [PATCH 10/72] uniformize facets/edges/corners --- SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h | 32 ++++++- Stream_support/include/CGAL/IO/MEDIT.h | 89 ++++++++----------- 2 files changed, 69 insertions(+), 52 deletions(-) diff --git a/SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h b/SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h index 68eccae85985..2044704fefe5 100644 --- a/SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h +++ b/SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h @@ -698,13 +698,16 @@ bool build_triangulation_from_file(std::istream& is, using Facet = std::array; // 3 = id using Tet_with_ref = std::array; // 4 = id + using Facet_with_index = CGAL::IO::internal::Facet_with_index; using Edge_with_index = CGAL::IO::internal::Edge_with_index; using Corner_with_index = CGAL::IO::internal::Corner_with_index; std::vector finite_cells; std::vector subdomains; std::vector points; - boost::unordered_map border_facets; + + + std::vector facet_indices; std::vector edge_indices; std::vector corner_indices; @@ -718,16 +721,41 @@ bool build_triangulation_from_file(std::istream& is, } bool ok = CGAL::IO::internal::read_MEDIT(is, points, finite_cells, subdomains, - border_facets, true, + facet_indices, true, edge_indices, corner_indices, verbose, is_CGAL_mesh); + if(!ok){ return false; } + boost::unordered_map border_facets; + border_facets.reserve(facet_indices.size()); + + bool has_negative_surface_patch_ids = false; + Surface_patch_index max_surface_patch_id{0}; + + for (const Facet_with_index& fi : facet_indices) + { + if (fi.surface_patch_index<0) + has_negative_surface_patch_ids=true; + max_surface_patch_id=(std::max)(max_surface_patch_id, fi.surface_patch_index); + border_facets.emplace(CGAL::make_array(fi.v0, fi.v1, fi.v2), fi.surface_patch_index); + } + + if(has_negative_surface_patch_ids) + { + if(verbose) + std::cerr << "Warning: negative surface patch ids" << std::endl; + for(auto& facet_and_patch_id : border_facets) { + if(facet_and_patch_id.second < 0) + facet_and_patch_id.second = max_surface_patch_id - facet_and_patch_id.second; + } + } + if(!is_CGAL_mesh) tr.may_have_badly_oriented_cells(true); diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 20f0203abd1e..fbee3c0c99ab 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -33,6 +33,13 @@ namespace CGAL { namespace IO { namespace internal { +template +struct Facet_with_index +{ + int v0, v1, v2; + SurfacePatchIndex surface_patch_index; +}; + template struct Edge_with_index { @@ -47,25 +54,25 @@ struct Corner_with_index CornerIndex corner_index; }; + template // either Corner_with_index or a tuple/pair + class FacetWithIndex, // either Facet_with_index or a tuple/array + class EdgeWithIndex, // either Edge_with_index or a tuple/array + class CornerWithIndex> // either Corner_with_index or a tuple/pair/array bool read_MEDIT(std::istream& is, PointRange& points, TetrahedronRange& tetrahedra, std::vector& subdomains, - boost::unordered_map,SurfacePatchIndex_ >& border_facets, - bool read_border_facets, - std::vector& edge_indices, - std::vector& corner_indices, + std::vector& facets_and_indices, + bool read_facets_and_indices, + std::vector& edges_and_indices, + std::vector& corners_and_indices, bool verbose, bool& is_CGAL_mesh) { using Point_3 = typename PointRange::value_type; using FT = typename Kernel_traits::Kernel::FT; - using Surface_patch_index = SurfacePatchIndex_; using Facet = std::array; using Tet_with_ref = typename std::iterator_traits::value_type; @@ -134,10 +141,9 @@ bool read_MEDIT(std::istream& is, if(line.find("Triangles") != std::string::npos) { - if(read_border_facets){ - bool has_negative_surface_patch_ids = false; - Surface_patch_index max_surface_patch_id{0}; + if(read_facets_and_indices){ is >> nf; + facets_and_indices.reserve(nf); if(verbose) std::cerr << "Reading "<< nf << " triangles" << std::endl; @@ -145,15 +151,13 @@ bool read_MEDIT(std::istream& is, for(int i=0; i> n[0] >> n[1] >> n[2] >> surface_patch_id)) { if(verbose) std::cerr << "Issue while reading triangles" << std::endl; return false; } - has_negative_surface_patch_ids |= (surface_patch_id < 0); - max_surface_patch_id = (std::max)(max_surface_patch_id, surface_patch_id); Facet facet; facet[0] = offset + n[0] - 1; facet[1] = offset + n[1] - 1; @@ -171,36 +175,17 @@ bool read_MEDIT(std::istream& is, // find the circular permutation that puts the smallest index in the first place. int n0 = (std::min)({facet[0],facet[1], facet[2]}); - do + while(facet[0] != n0) { std::rotate(std::begin(facet), std::next(std::begin(facet)), std::end(facet)); } - while(facet[0] != n0); - - border_facets.emplace(facet, surface_patch_id); - } - if(has_negative_surface_patch_ids) - { - if(verbose) - std::cerr << "Warning: negative surface patch ids" << std::endl; - for(auto& facet_and_patch_id : border_facets) { - if(facet_and_patch_id.second < 0) - facet_and_patch_id.second = max_surface_patch_id - facet_and_patch_id.second; - } + facets_and_indices.push_back({facet[0], facet[1], facet[2], surface_patch_id}); } }else{ is >> nf; + std::string buffer; for(int i=0; i> n[0] >> n[1] >> n[2] >> surface_patch_id)) - { - if(verbose) - std::cerr << "Issue while reading triangles" << std::endl; - return false; - } - } + std::getline(is, buffer); } } if(line.find("Tetrahedra") != std::string::npos) @@ -259,7 +244,7 @@ bool read_MEDIT(std::istream& is, std::cerr << "Issue while reading corners" << std::endl; return false; } - corner_indices.push_back({offset + n - 1, ++corner_index}); + corners_and_indices.push_back({offset + n - 1, ++corner_index}); } } @@ -278,8 +263,8 @@ bool read_MEDIT(std::istream& is, std::cerr << "Issue while reading edges" << std::endl; return false; } - edge_indices.push_back({offset + n[0] - 1, offset + n[1] - 1, curve_index}); - CGAL_assertion(edge_indices.size() == static_cast(i + 1)); + edges_and_indices.push_back({offset + n[0] - 1, offset + n[1] - 1, curve_index}); + CGAL_assertion(edges_and_indices.size() == static_cast(i + 1)); } } @@ -289,9 +274,9 @@ bool read_MEDIT(std::istream& is, { std::cout << points.size() - std::size_t(offset) << " points" << std::endl; std::cout << tetrahedra.size() << " cells" << std::endl; - std::cout << border_facets.size() << " border facets" << std::endl; - std::cout << edge_indices.size() << " edges" << std::endl; - std::cout << corner_indices.size() << " corners" << std::endl; + std::cout << facets_and_indices.size() << " border facets" << std::endl; + std::cout << edges_and_indices.size() << " edges" << std::endl; + std::cout << corners_and_indices.size() << " corners" << std::endl; } if(tetrahedra.empty()) @@ -365,15 +350,15 @@ bool read_MEDIT(std::istream& is, using Subdomains = typename internal_np::Lookup_named_param_def>::reference; Subdomains subdomains = choose_parameter(get_parameter_reference(np, internal_np::subdomains), default_subdomains); - boost::unordered_map,int > border_facets; - constexpr bool read_border_facets = false; - std::vector> edge_indices; - std::vector> corner_indices; + constexpr bool read_facets_and_indices = false; + std::vector> facets_and_indices; + std::vector> edges_and_indices; + std::vector> corners_and_indices; bool is_CGAL_mesh; return internal::read_MEDIT(is, points, tetrahedra, subdomains, - border_facets, read_border_facets, - edge_indices, corner_indices, + facets_and_indices, read_facets_and_indices, + edges_and_indices, corners_and_indices, verbose, is_CGAL_mesh); } @@ -415,7 +400,11 @@ template>* = nullptr +#endif + ) { using parameters::choose_parameter; From 959f8586891b4c29560702b5eb85f5e232317399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 16 Sep 2026 22:33:58 +0200 Subject: [PATCH 11/72] add facets, edges and corners as np --- .../internal/parameters_interface.h | 4 + .../doc/Stream_support/IOstream.txt | 4 +- Stream_support/include/CGAL/IO/MEDIT.h | 73 ++++++++++++++----- 3 files changed, 59 insertions(+), 22 deletions(-) diff --git a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h index ada53548adb8..6fc4a1fcefa0 100644 --- a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h +++ b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h @@ -69,6 +69,10 @@ CGAL_add_named_parameter(stream_precision_t, stream_precision, stream_precision) CGAL_add_named_parameter(read_only_one_object_t, read_only_one_object, read_only_one_object) CGAL_add_named_parameter(subdomains_t, subdomains, subdomains) +CGAL_add_named_parameter(facets_with_indices_t, facets_with_indices, facets_with_indices) +CGAL_add_named_parameter(edges_with_indices_t, edges_with_indices, edges_with_indices) +CGAL_add_named_parameter(corners_with_indices_t, corners_with_indices, corners_with_indices) + // List of named parameters that we use in the package 'Mesh_3' CGAL_add_named_parameter(vertex_feature_degree_t, vertex_feature_degree, vertex_feature_degree_map) diff --git a/Stream_support/doc/Stream_support/IOstream.txt b/Stream_support/doc/Stream_support/IOstream.txt index 716e0aace41c..139f025d616f 100644 --- a/Stream_support/doc/Stream_support/IOstream.txt +++ b/Stream_support/doc/Stream_support/IOstream.txt @@ -505,8 +505,8 @@ which can perform some combinatorial repairing to ensure the input data is a 2-m \ref IOStreamMedit "MEDIT" - \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, TetrahedronRange&, std::vector&, bool) `CGAL::IO::read_MEDIT()` \endlink - \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const TetrahedronRange&, const std::vector&) `CGAL::IO::write_MEDIT()` \endlink + \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, TetrahedronRange&, const NamedParameters&) `CGAL::IO::read_MEDIT()` \endlink + \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const TetrahedronRange&, const NamedParameters&) `CGAL::IO::write_MEDIT()` \endlink diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index fbee3c0c99ab..c43edc03bd6d 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -64,10 +64,10 @@ bool read_MEDIT(std::istream& is, PointRange& points, TetrahedronRange& tetrahedra, std::vector& subdomains, - std::vector& facets_and_indices, - bool read_facets_and_indices, - std::vector& edges_and_indices, - std::vector& corners_and_indices, + std::vector& facets_with_indices, + bool read_facets_with_indices, + std::vector& edges_with_indices, + std::vector& corners_with_indices, bool verbose, bool& is_CGAL_mesh) { @@ -141,9 +141,9 @@ bool read_MEDIT(std::istream& is, if(line.find("Triangles") != std::string::npos) { - if(read_facets_and_indices){ + if(read_facets_with_indices){ is >> nf; - facets_and_indices.reserve(nf); + facets_with_indices.reserve(nf); if(verbose) std::cerr << "Reading "<< nf << " triangles" << std::endl; @@ -179,7 +179,7 @@ bool read_MEDIT(std::istream& is, { std::rotate(std::begin(facet), std::next(std::begin(facet)), std::end(facet)); } - facets_and_indices.push_back({facet[0], facet[1], facet[2], surface_patch_id}); + facets_with_indices.push_back({facet[0], facet[1], facet[2], surface_patch_id}); } }else{ is >> nf; @@ -244,7 +244,7 @@ bool read_MEDIT(std::istream& is, std::cerr << "Issue while reading corners" << std::endl; return false; } - corners_and_indices.push_back({offset + n - 1, ++corner_index}); + corners_with_indices.push_back({offset + n - 1, ++corner_index}); } } @@ -263,8 +263,8 @@ bool read_MEDIT(std::istream& is, std::cerr << "Issue while reading edges" << std::endl; return false; } - edges_and_indices.push_back({offset + n[0] - 1, offset + n[1] - 1, curve_index}); - CGAL_assertion(edges_and_indices.size() == static_cast(i + 1)); + edges_with_indices.push_back({offset + n[0] - 1, offset + n[1] - 1, curve_index}); + CGAL_assertion(edges_with_indices.size() == static_cast(i + 1)); } } @@ -274,9 +274,9 @@ bool read_MEDIT(std::istream& is, { std::cout << points.size() - std::size_t(offset) << " points" << std::endl; std::cout << tetrahedra.size() << " cells" << std::endl; - std::cout << facets_and_indices.size() << " border facets" << std::endl; - std::cout << edges_and_indices.size() << " edges" << std::endl; - std::cout << corners_and_indices.size() << " corners" << std::endl; + std::cout << facets_with_indices.size() << " border facets" << std::endl; + std::cout << edges_with_indices.size() << " edges" << std::endl; + std::cout << corners_with_indices.size() << " corners" << std::endl; } if(tetrahedra.empty()) @@ -307,7 +307,6 @@ bool read_MEDIT(std::istream& is, * \param points points of the soup of cells * \param tetrahedra each element in it describes a tetrahedron * using the indices of the points in `points` - * \param subdomains each element in it describes the subdomain index of the corresponding tetrahedron * * \param np optional \ref bgl_namedparameters "Named Parameters" described below * @@ -320,6 +319,27 @@ bool read_MEDIT(std::istream& is, * \cgalParamDefault{subdomains are ignored} * \cgalParamNEnd * + * \cgalParamNBegin{facets_with_indices} + * \cgalParamDescription{a non-const reference wrapper to a container of quadruple of integers that will be filled by this function. + * Each element corresponds to a facet with vertex being the three first integer, the last one being the surface patch index of the facet.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` able to store quadruple of `int`.} + * \cgalParamDefault{facets are ignored} + * \cgalParamNEnd + * + * \cgalParamNBegin{edges_with_indices} + * \cgalParamDescription{a non-const reference wrapper to a container of triple of integers that will be filled by this function. + * Each element corresponds to an edge with vertex being the two first integer, the last one being the curve index of the edge.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` able to store triple of `int`.} + * \cgalParamDefault{edges are ignored} + * \cgalParamNEnd + * + * \cgalParamNBegin{corners_with_indices} + * \cgalParamDescription{a non-const reference wrapper to a container of pair of integers that will be filled by this function. + * Each element corresponds to a corner at vertex corresponding to the first integer, the last one being the corner index.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` able to store pair of `int`.} + * \cgalParamDefault{corners are ignored} + * \cgalParamNEnd + * * \cgalParamNBegin{verbose} * \cgalParamDescription{if `true`, prints information about the reading process.} * \cgalParamType{Boolean} @@ -350,15 +370,28 @@ bool read_MEDIT(std::istream& is, using Subdomains = typename internal_np::Lookup_named_param_def>::reference; Subdomains subdomains = choose_parameter(get_parameter_reference(np, internal_np::subdomains), default_subdomains); - constexpr bool read_facets_and_indices = false; - std::vector> facets_and_indices; - std::vector> edges_and_indices; - std::vector> corners_and_indices; + // facets + std::vector> default_facets_with_indices; + using Facets_with_indices = typename internal_np::Lookup_named_param_def>>::reference; + Facets_with_indices facets_with_indices = choose_parameter(get_parameter_reference(np, internal_np::facets_with_indices), default_facets_with_indices); + + // edges + std::vector> default_edges_with_indices; + using Edges_with_indices = typename internal_np::Lookup_named_param_def>>::reference; + Edges_with_indices edges_with_indices = choose_parameter(get_parameter_reference(np, internal_np::edges_with_indices), default_edges_with_indices); + + // corners + std::vector> default_corners_with_indices; + using Corners_with_indices = typename internal_np::Lookup_named_param_def>>::reference; + Corners_with_indices corners_with_indices = choose_parameter(get_parameter_reference(np, internal_np::corners_with_indices), default_corners_with_indices); + + constexpr bool read_facets_with_indices = false; + bool is_CGAL_mesh; return internal::read_MEDIT(is, points, tetrahedra, subdomains, - facets_and_indices, read_facets_and_indices, - edges_and_indices, corners_and_indices, + facets_with_indices, read_facets_with_indices, + edges_with_indices, corners_with_indices, verbose, is_CGAL_mesh); } From 857bd3c3b63eef4418a950786e7620b71a781716 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 17 Sep 2026 10:11:48 +0100 Subject: [PATCH 12/72] wording --- Stream_support/include/CGAL/IO/MEDIT.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index c43edc03bd6d..2e7973b63cdc 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -321,21 +321,21 @@ bool read_MEDIT(std::istream& is, * * \cgalParamNBegin{facets_with_indices} * \cgalParamDescription{a non-const reference wrapper to a container of quadruple of integers that will be filled by this function. - * Each element corresponds to a facet with vertex being the three first integer, the last one being the surface patch index of the facet.} + * Each element corresponds to a facet with vertices corresponding to the three first integers, and the last integer being the surface patch index of the facet.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` able to store quadruple of `int`.} * \cgalParamDefault{facets are ignored} * \cgalParamNEnd * * \cgalParamNBegin{edges_with_indices} * \cgalParamDescription{a non-const reference wrapper to a container of triple of integers that will be filled by this function. - * Each element corresponds to an edge with vertex being the two first integer, the last one being the curve index of the edge.} + * Each element corresponds to an edge with vertices corresponding to the two first integers, and the last integer being the curve index of the edge.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` able to store triple of `int`.} * \cgalParamDefault{edges are ignored} * \cgalParamNEnd * * \cgalParamNBegin{corners_with_indices} * \cgalParamDescription{a non-const reference wrapper to a container of pair of integers that will be filled by this function. - * Each element corresponds to a corner at vertex corresponding to the first integer, the last one being the corner index.} + * Each element corresponds to a corner at the vertex corresponding to the first integer, the last one being the corner index.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` able to store pair of `int`.} * \cgalParamDefault{corners are ignored} * \cgalParamNEnd From 01f132536ab3c737ce34cdd7508790f44f0c634b Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 17 Sep 2026 12:40:31 +0100 Subject: [PATCH 13/72] Add Corners to read/write --- Stream_support/include/CGAL/IO/MEDIT.h | 20 +- .../data/polyhedral_complex.mesh | 3038 +++++++++++++++++ .../test/Stream_support/test_MEDIT.cpp | 21 +- 3 files changed, 3071 insertions(+), 8 deletions(-) create mode 100644 Stream_support/test/Stream_support/data/polyhedral_complex.mesh diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 2e7973b63cdc..2dc71caf78c5 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -51,7 +51,11 @@ template struct Corner_with_index { int v; - CornerIndex corner_index; + + bool operator==(const Corner_with_index& rhs) const + { + return (v == rhs.v); + } }; @@ -228,7 +232,6 @@ bool read_MEDIT(std::istream& is, } } - int corner_index = 0; if(line.find("Corners") != std::string::npos) { is >> ncorners; @@ -244,7 +247,7 @@ bool read_MEDIT(std::istream& is, std::cerr << "Issue while reading corners" << std::endl; return false; } - corners_with_indices.push_back({offset + n - 1, ++corner_index}); + corners_with_indices.push_back({offset + n}); } } @@ -452,9 +455,14 @@ bool write_MEDIT(std::ostream& os, // subdomains std::vector default_subdomains; + std::vector> default_corners; + using Subdomains = typename internal_np::Lookup_named_param_def>::reference; Subdomains subdomains = choose_parameter(get_parameter_reference(np, internal_np::subdomains), default_subdomains); + using Corners_with_indices = typename internal_np::Lookup_named_param_def>>::reference; + Corners_with_indices corners = choose_parameter(get_parameter_reference(np, internal_np::corners_with_indices), default_corners); + if constexpr (is_default_parameter::value) default_subdomains.resize(tetrahedra.size(), 1); @@ -469,6 +477,12 @@ bool write_MEDIT(std::ostream& os, << tetrahedra[k][1]+1 << " " << tetrahedra[k][2]+1 << " " << tetrahedra[k][3]+1 << " " << subdomains[k] << "\n"; + + if(!corners.empty()){ + os << "Corners\n" << corners.size() << "\n"; + for(const auto& c : corners) + os << c.v << "\n"; + } os <<"End\n"; return true; } diff --git a/Stream_support/test/Stream_support/data/polyhedral_complex.mesh b/Stream_support/test/Stream_support/data/polyhedral_complex.mesh new file mode 100644 index 000000000000..0dae46b18e59 --- /dev/null +++ b/Stream_support/test/Stream_support/data/polyhedral_complex.mesh @@ -0,0 +1,3038 @@ +MeshVersionFormatted 1 +Dimension 3 +# CGAL::Mesh_complex_3_in_triangulation_3 +Vertices +357 +0 0 0 0 +0 0 50 0 +0 0 100 0 +0 50 66.659999999999997 0 +0 50 100 0 +0 100 0 0 +0 100 50 0 +0 100 100 0 +100 0 0 0 +100 0 50 0 +100 0 100 0 +100 50 66.659999999999997 0 +100 50 100 0 +100 100 0 0 +100 100 50 0 +100 100 100 0 +100 39.386215727983412 62.273568757997808 0 +100 27.515222328655064 57.986212335080076 0 +100 14.378822232785753 53.893969102838732 0 +83.333333333333329 0 50 0 +66.666666666666657 0 50 0 +49.999999999999986 0 50 0 +33.333333333333314 0 50 0 +16.666666666666647 0 50 0 +100 0 33.333333333333329 0 +100 0 16.666666666666661 0 +100 0 66.666666666666671 0 +100 0 83.333333333333343 0 +100 60.613784272016588 62.273568757997808 0 +100 72.484777671344943 57.986212335080076 0 +100 85.621177767214249 53.893969102838724 0 +88.888888888888886 50 66.659999999999997 0 +77.777777777777771 50 66.659999999999997 0 +66.666666666666657 50 66.659999999999997 0 +55.555555555555543 50 66.659999999999997 0 +44.444444444444429 50 66.659999999999997 0 +33.333333333333314 50 66.659999999999997 0 +22.2222222222222 50 66.659999999999997 0 +11.111111111111088 50 66.659999999999997 0 +100 50 77.773333333333326 0 +100 50 88.886666666666656 0 +0 39.386215727983412 62.273568757997808 0 +0 27.515222328655064 57.986212335080076 0 +0 14.378822232785753 53.893969102838732 0 +0 0 33.333333333333329 0 +0 0 16.666666666666661 0 +0 0 66.666666666666671 0 +0 0 83.333333333333343 0 +100 83.333333333333329 0 0 +100 66.666666666666657 0 0 +100 49.999999999999986 0 0 +100 33.333333333333314 0 0 +100 16.666666666666647 0 0 +83.333333333333329 100 0 0 +66.666666666666657 100 0 0 +49.999999999999986 100 0 0 +33.333333333333314 100 0 0 +16.666666666666647 100 0 0 +100 100 16.666666666666668 0 +100 100 33.333333333333329 0 +83.333333333333329 0 0 0 +66.666666666666657 0 0 0 +49.999999999999986 0 0 0 +33.333333333333314 0 0 0 +16.666666666666647 0 0 0 +0 60.613784272016588 62.273568757997808 0 +0 72.484777671344943 57.986212335080076 0 +0 85.621177767214249 53.893969102838724 0 +0 50 77.773333333333326 0 +0 50 88.886666666666656 0 +83.333333333333329 100 50 0 +66.666666666666657 100 50 0 +49.999999999999986 100 50 0 +33.333333333333314 100 50 0 +16.666666666666647 100 50 0 +100 100 66.666666666666671 0 +100 100 83.333333333333343 0 +0 100 33.333333333333329 0 +0 100 16.666666666666661 0 +0 100 66.666666666666671 0 +0 100 83.333333333333343 0 +0 83.333333333333329 0 0 +0 66.666666666666657 0 0 +0 49.999999999999986 0 0 +0 33.333333333333314 0 0 +0 16.666666666666647 0 0 +16.666666666666668 100 100 0 +33.333333333333329 100 100 0 +50 100 100 0 +66.666666666666671 100 100 0 +83.333333333333343 100 100 0 +0 64.777588784083292 100 0 +0 81.444255450749964 100 0 +100 64.777588784083292 100 0 +100 81.444255450749964 100 0 +88.888888888888886 50 100 0 +77.777777777777771 50 100 0 +66.666666666666657 50 100 0 +55.555555555555543 50 100 0 +44.444444444444429 50 100 0 +33.333333333333314 50 100 0 +22.2222222222222 50 100 0 +11.111111111111088 50 100 0 +100 35.222411215916708 100 0 +100 18.55574454925004 100 0 +0 35.222411215916708 100 0 +0 18.55574454925004 100 0 +16.666666666666668 0 100 0 +33.333333333333329 0 100 0 +50 0 100 0 +66.666666666666671 0 100 0 +83.333333333333343 0 100 0 +49.978654997889109 13.418404069439919 -0.03921569561300231 0 +61.435366853229077 0.029005240205339788 71.344750274246323 0 +42.084855094773033 58.564505634921645 63.133637732153986 0 +38.054786358999479 65.660403547545158 60.344849529066821 0 +58.205511137827457 71.110192674628934 58.425600797399497 0 +58.333333333333329 58.333333333333314 -0.01006124638752226 0 +100.00701504997905 46.411783630495279 32.401718226472752 0 +-0.036059255694100401 46.411783630495279 32.401718226472745 0 +77.828415239112118 19.722718520475645 99.996698967750717 0 +72.222222222222214 26.120550227647747 57.575923589292472 0 +61.1111111111111 74.130708032399994 99.968342034188282 0 +27.777777777777757 25.869291967599995 99.989392485068805 0 +67.089082932691014 81.54402564178298 55.099555751066546 0 +27.777777777777754 74.130708032400008 99.999274770923876 0 +99.968571595728235 73.022487598897953 30.604380032178401 0 +-0.042502813945020534 73.022487598897939 30.604380032178383 0 +32.392057237618488 41.66666666666665 0.026440513049692527 0 +99.960672341627856 29.209222149777986 80.032816191068918 0 +0.053247842553901137 29.209222149777993 80.032816191068932 0 +78.933035503980236 47.133155569619994 43.542305658750266 0 +0.0063435898991883732 70.790777850222014 80.032816191068918 0 +18.835685383938618 19.28010438931102 55.31362276422756 0 +22.958845094484637 99.986428893452 77.690038274608952 0 +81.164627392363371 80.722670078629989 55.322529009252023 0 +38.888888888888872 50 83.329999999999998 0 +61.1111111111111 50 83.329999999999998 0 +75.988811755102049 100.03388208079696 25 0 +23.022376489795914 -0.02729473271888061 76.977623510204083 0 +14.321541223572437 76.360482934977256 68.619202115964057 0 +76.977623510204083 -0.011674220018903725 23.022376489795924 0 +76.977623510204069 76.977623510204069 0.035338907166988065 0 +77.285446948418411 99.995898385447205 73.429771866388705 0 +23.022376489795917 76.977623510204069 -0.0065974382960121147 0 +76.977623510204069 23.022376489795917 -0.012066188633070851 0 +41.66666666666665 -0.017794785879232222 25 0 +41.666666666666657 99.961361438483436 25 0 +70.937629652188036 0.041111970829258659 82.376955413732958 0 +99.966338703289409 24.011188244897948 24.999999999999989 0 +84.133727696482765 50 83.329999999999984 0 +15.866272303517221 50 83.329999999999984 0 +84.9385669485211 63.773085365141171 61.04890880599082 0 +84.938566948521085 36.21326749979616 61.081930581437504 0 +15.061433051478875 63.772641761430904 61.047835424505152 0 +15.061433051478875 36.229114524483755 61.043585764864048 0 +-0.009412345531018218 49.000289088926507 47.98755982042286 0 +100.01456719743439 49.000284192491407 47.987571668256109 0 +84.938566948521085 36.053422468406154 100.04956546486082 0 +84.938566948521085 63.946577531593846 99.993567989689467 0 +15.061433051478886 63.946577531593803 99.988779200919623 0 +15.061433051478886 36.053422468406183 99.982903807788261 0 +49.999999999999986 34.992991913482157 60.624153641246281 0 +49.999999999999986 65.662917805421756 99.960907025466497 0 +49.999999999999986 34.337010957979174 100.03568358299466 0 +23.022376489795889 22.626595146375479 -0.020783118333771 0 +53.990118957818254 19.839770270451382 55.498691298934887 0 +21.224553419055773 100.04929000372059 24.999999999999993 0 +21.224491189719924 -0.0056337928435823414 24.999999999999993 0 +47.561966897401462 80.385673163724789 99.989302926147587 0 +47.562065251618364 19.614294843931994 100.00954035673945 0 +48.737283207800928 66.403236402778461 60.131548984672165 0 +81.471320398934495 21.480279283991099 75.361705466231712 0 +58.333333333333336 100.02353306297181 78.101862860840527 0 +41.66666666666665 -0.029755008492429624 71.757253789638511 0 +-0.02815620386536466 14.99538917842308 69.067871989597535 0 +100.06701916786884 14.995389178423082 69.067871989597535 0 +0.0051302574775036192 85.004610821576932 69.067871989597506 0 +99.951445755915756 85.004610821576932 69.067871989597506 0 +80.439890140773713 0.041671416426652286 73.976957746978556 0 +99.980808575263239 24.081630949080136 39.900371307636206 0 +-0.022650202605063896 24.08164340162854 39.900331334044985 0 +72.222222222222214 37.265452059839561 61.44599852803978 0 +57.41332171459382 35.269966216480299 -0.019721710177734053 0 +75.537200394677825 46.097025218651893 -0.010073131739398278 0 +21.200166666970116 58.333333333333321 -0.010398899728897959 0 +77.285446948418411 0.0092214341516410059 63.347170535620364 0 +44.690944296294731 75.255983443392353 -0.0068975227245307025 0 +42.25389767588652 81.011723920272544 55.206279454259402 0 +41.666666666666664 100.02842183787638 80.459009956888281 0 +100.01470233827189 38.271844025878352 19.438822766513326 0 +58.333333333333314 81.87646656362972 -0.022783208914916031 0 +-0.07511110121049569 41.666666666666657 18.068494234916439 0 +0.0020888899514834858 58.94881613302789 20.299021688617117 0 +0.04718140250984959 84.322770917481407 38.507091156462579 0 +-0.007138078308457807 85.319799765579461 25.050888605938923 0 +58.827653428231187 100.03822047159913 20.520307691694967 0 +-0.011409296736474062 74.332880311476544 17.114164869549015 0 +58.333333333333321 99.975464972717774 33.585020279934596 0 +59.58595258720004 -0.027906276788641549 28.721495609827329 0 +99.988433256697164 81.807780308459968 18.192219691540018 0 +38.888888888888872 26.128203331990342 57.552955088864536 0 +58.333333333333336 0.014054836010018334 83.785464457138886 0 +99.952832898508404 62.945450524598101 41.96880352179177 0 +34.486050516060587 -0.020616991589600175 82.015798750969168 0 +40.352482913724543 57.798178786304049 -0.037177915871893674 0 +77.285446948418411 -0.028710549336665281 35.486314306002775 0 +22.714553051581554 -0.024035769335964297 64.513685081670502 0 +31.44557805120748 -0.013188469786655332 17.87736959524576 0 +34.330876138525838 82.08527759087778 0.03278581307817241 0 +58.333333333333321 99.97822211489445 65.803817615388738 0 +77.828341071019196 80.277313549323026 100.01492789231884 0 +17.674943150257299 83.140014554344191 100.02918059188571 0 +17.6749415965417 16.859984050117099 99.991685215638569 0 +41.66666666666665 15.017420852129039 54.051850769492042 0 +31.445594988789548 0.015282973625289742 32.122615784885369 0 +83.342765161232563 16.94070431333861 54.628026347844312 0 +100.00926733066899 16.47264278758211 82.756302734717281 0 +0.038414503023886937 83.527398611483562 82.756348826146507 0 +0.013053476417894672 16.472630161382778 82.756316792029054 0 +11.800732281751751 99.993731239313561 62.515951096558865 0 +49.999999999999986 66.040327628871182 80.202708333311108 0 +76.977623510204069 100.0208310105252 13.752465081143448 0 +58.333333333333336 14.987897227728119 99.96834712578945 0 +99.943878849060553 58.960837504290339 20.30652697912425 0 +11.800732281751749 88.284130983649561 53.134760428405286 0 +88.199267718248251 88.285123053261998 53.13842373240773 0 +39.365533647457042 26.409640298208622 -0.039413441841515962 0 +99.990989306207538 84.322770917481407 38.507091156462586 0 +99.949106874926144 83.527417734905299 82.756370117106258 0 +12.853424155388225 23.022376489795889 0.0018562745317467488 0 +0.023643081588829773 23.022376489795889 13.75246032703436 0 +31.743361928860345 16.788675020453372 12.847483317024148 0 +23.022376489795914 -0.04851794561793632 87.150030212897889 0 +76.977623510204069 87.149977836210155 0.010480417379483242 0 +11.800732281751753 -0.032551314607189852 38.507091156462579 0 +-0.021379177431299468 13.643986978305776 38.507091156462579 0 +11.800732281751751 99.994785246641101 38.507091156462579 0 +11.492908843537414 100.02165748593373 11.492908843537418 0 +0.017301913105711719 11.492908843537414 11.492908843537418 0 +11.492908843537418 0.015206032770379352 88.507091156462579 0 +11.492908843537418 11.492908843537418 0.011722574607119896 0 +88.507091156462579 0.0091033607841382036 11.492908843537418 0 +88.507091156462579 11.49290884353741 -0.044501934955046174 0 +11.492908843537418 99.996971859460885 88.507091156462593 0 +23.022376489795914 100.03137254899407 87.149953463732828 0 +72.222222222222214 64.569200554863272 100.02138528612542 0 +82.063868507228392 65.621294271164203 0.018880356260496001 0 +83.963037884805033 99.992055339956096 83.963037884805033 0 +57.215904237118039 62.083350509210717 61.648291467201588 0 +70.913431204546441 65.311668046475319 60.491559863440187 0 +72.333775425198183 15.546809646511278 54.181222237294278 0 +38.513984362181191 37.16772288644232 61.473041136244156 0 +61.01707066847257 47.679742279565964 31.639858313823066 0 +34.469699251502945 50.43927710384294 37.84320629925412 0 +48.592152121480751 72.7417394436591 27.838904768162607 0 +63.391534384361798 81.638447001335351 36.251226840552476 0 +27.170817388164437 26.60083582367351 26.682986531868387 0 +49.696891227338888 54.721334696269665 48.630692535397863 0 +45.375597021370872 17.050173339480526 71.026137237835187 0 +82.582290948863076 14.924894824089288 38.604637226315674 0 +82.398916835764737 33.613500221682031 14.609137631398173 0 +19.010147070996105 80.904938538110514 55.262068364605582 0 +75.869917853921393 65.315249781858398 22.076899650049544 0 +18.410597869154536 34.971897087518641 -0.048330705856415079 0 +51.193667455174932 27.655477725670185 22.139998882522086 0 +26.481708348330496 22.963353020013688 76.958696835921501 0 +26.456127213638979 77.105460999076257 77.155146592567789 0 +68.504790690806075 79.299073199018139 78.70917659486912 0 +60.997264332374257 22.24524120650624 77.269539297443686 0 +71.512204811604249 34.500507177432439 100.00089212330067 0 +38.935699276126336 15.627401066691025 27.801811998444641 0 +85.107104668510615 86.134233727333168 13.860299050698405 0 +21.626145219483764 46.946398899485594 19.233664788530952 0 +14.970389867463425 15.734231291916352 19.922369695796935 0 +58.333333333333321 13.026305164253113 15.447146184474578 0 +43.828649356692267 47.606737514731577 18.634590558230467 0 +61.111111111111114 25.869291967599999 99.978777380006647 0 +33.008802042170942 83.919460568526688 32.668525311769962 0 +38.888888888888872 63.374081360155515 100.00966748679116 0 +17.494868021192637 38.725828478987403 40.538485914647211 0 +16.19160371245863 59.675583088824752 40.797786241200065 0 +23.293799245272609 69.035326175475063 23.964546148515641 0 +0.041886890023306478 88.692683424004954 88.507091156462593 0 +28.901288384714409 36.642259455269055 86.831720316604461 0 +46.493103389793106 34.372669194213692 40.673565967335634 0 +49.246638490119238 18.261588321875557 39.918993050903637 0 +86.067519614454142 57.471011144913547 12.930806667769421 0 +51.36207039224157 84.995118222912453 15.693545629835015 0 +80.520062622728517 66.754333792784749 41.284040096486997 0 +81.502073057035389 84.423355903624241 36.523496778628058 0 +89.965311871707598 78.838062011318797 44.516302091671704 0 +72.222222222222214 35.68939784399408 78.642674994382062 0 +0.031238428079291225 24.011188244897944 24.999999999999989 0 +49.105628904848572 83.892045209507458 72.990073885032217 0 +22.714553051581554 13.883561918854319 37.397179337370794 0 +70.024376367543766 83.018157001247573 18.522814360074715 0 +28.261326163662044 62.986952314296808 86.618442231870617 0 +35.054820270207486 87.350332917252274 16.654771171109925 0 +45.565793370887121 32.956548505655796 78.831060530392421 0 +32.571646521946349 68.287739533818936 42.756657449519793 0 +67.407905506637533 13.235510753463997 86.116013327038132 0 +11.492908843537418 11.307316575995053 99.988845342215427 0 +58.464006761240775 60.301101408202136 18.373003847684416 0 +68.289192977120365 25.682856157161215 13.433887080442153 0 +64.674877153524946 33.492455198701649 42.615467247132884 0 +64.912782673965765 17.9445594832473 40.574673798300452 0 +62.590763111024437 63.817356307710263 39.945216361312035 0 +15.991209637005788 82.893855228091724 15.706940648882124 0 +30.512503259502623 83.211348473217427 54.604990454215518 0 +82.213098651260083 68.030104155304898 82.519981205577821 0 +89.531833351737717 70.741279978340515 71.580927447455039 0 +56.948312639511698 86.715666044266015 86.260131716515971 0 +16.818188672902679 77.82456181444168 37.661061748652685 0 +85.200505645614868 16.27559733431621 18.332959305182023 0 +79.036111890300674 47.180649650186012 25.699611567829994 0 +48.796283675339282 87.340540428085319 33.968943216200806 0 +11.038204272555307 88.323242577816373 34.051025035247648 0 +37.024474020031938 15.016403917069626 85.788201162230337 0 +85.768780372255492 13.766852109532168 87.994423178087999 0 +13.815593112178076 32.372946984832524 16.104386188454662 0 +38.427375147300502 84.453148927367451 86.304680924780612 0 +11.170682117186891 11.370662196364625 33.832267604613428 0 +100.02644902136792 36.634616408006323 43.655265518011305 0 +38.639524487156081 67.466751984131832 14.447295211739025 0 +53.251781925997157 13.576874627042123 86.254944005358652 0 +12.077194445174726 65.986366154122734 15.493991315920145 0 +83.976587272691305 30.838851605624832 44.692960470666335 0 +14.324283032605313 23.628935417019669 68.65361267157985 0 +12.021645209227657 0.0013297556631641783 73.976957746978556 0 +12.419031463939355 10.337019095089461 64.428578443698825 0 +20.16909098949996 35.197563330396946 74.102355223276703 0 +99.978860474739776 70.790777850222014 80.032816191068918 0 +12.021623223122447 99.98519200053461 73.976957746978556 0 +20.022563880097472 64.755523855838518 74.184397153146165 0 +30.120441181826447 27.868233672571705 43.245390211808129 0 +35.586566332702773 33.842716441952632 14.327281005000128 0 +26.775429873348436 36.963621145240005 61.349239649825201 0 +27.577840291738127 55.894498887325042 50.605656573922289 0 +83.711455739597554 85.228116285457986 76.733870791483412 0 +69.483841748116077 100.00785906501696 82.558161187662876 0 +76.272715794901487 89.098512873548728 87.783301133929555 0 +89.030944179903656 87.581467108972191 88.197290400095412 0 +60.650873120598092 63.21087788868202 100.02591505635962 0 +69.560089463313204 64.822141713256315 75.326255262536492 0 +67.641330971334341 60.770769187820768 87.983950085301117 0 +64.148953397565251 47.922996748094356 48.838146900494436 0 +48.569852315345962 71.010225632499541 44.024158578929324 0 +34.178794586214231 99.978734737854211 68.895366746041219 0 +14.294345259312697 26.168444699163551 87.156895729398641 0 +14.222208696275093 73.862486170024312 87.192174735403 0 +47.749720258911026 56.943969794136478 31.261273462373509 0 +74.206629653416471 25.210591170883266 29.361068846622935 0 +65.885324479379506 41.657653843527129 14.97916751715502 0 +99.963816545307623 34.224650535427173 31.687548116624477 0 +0.009216781126724527 62.945519591895476 41.968721483454438 0 +87.067982896803613 76.4756411173733 -0.031225037437285885 0 +Triangles +580 +122 163 167 9 +162 124 102 18 +355 191 119 4 +355 119 324 4 +159 96 104 18 +152 38 39 15 +41 13 104 16 +18 19 177 16 +18 217 19 9 +109 108 234 17 +165 124 101 18 +161 103 92 11 +106 5 70 19 +157 356 66 6 +27 20 187 17 +23 216 24 7 +9 26 53 4 +44 47 176 19 +2 47 44 19 +139 60 59 5 +156 134 43 9 +111 110 203 17 +56 192 55 8 +136 72 71 14 +95 91 212 11 +16 91 95 11 +171 124 165 18 +178 81 219 12 +44 182 43 6 +44 43 134 9 +228 113 64 8 +228 64 166 8 +185 51 248 8 +131 42 43 19 +176 131 43 19 +157 4 66 6 +330 140 208 17 +218 28 177 16 +37 137 36 15 +4 42 39 9 +147 23 22 7 +49 235 357 8 +28 27 180 17 +28 177 27 16 +179 30 31 13 +179 31 76 13 +114 149 180 17 +171 224 278 18 +166 231 265 8 +250 35 34 14 +107 303 3 18 +48 107 3 19 +80 81 334 10 +76 77 179 13 +125 117 189 14 +109 110 171 18 +230 333 95 13 +19 181 10 4 +138 35 137 15 +63 147 200 7 +4 42 131 19 +69 4 131 19 +54 49 14 8 +120 157 182 6 +271 159 97 18 +271 97 98 18 +5 92 103 11 +5 103 70 15 +5 70 92 12 +47 48 176 19 +35 34 183 9 +93 133 219 12 +239 6 79 5 +239 79 168 5 +172 116 115 14 +96 13 104 18 +96 41 13 15 +90 91 212 11 +70 69 133 12 +70 152 69 15 +218 105 130 16 +70 92 133 12 +200 142 207 7 +9 61 243 7 +9 244 61 8 +245 81 334 10 +58 145 57 8 +203 175 205 17 +154 122 217 9 +65 166 64 8 +195 7 78 6 +157 43 42 6 +172 189 117 14 +33 32 154 9 +84 265 85 8 +76 31 15 13 +157 356 120 6 +198 128 194 6 +216 209 169 7 +61 142 243 7 +162 106 103 18 +172 189 116 14 +39 38 156 9 +19 10 27 16 +19 217 10 9 +155 39 66 14 +271 98 99 18 +147 216 209 7 +172 35 250 14 +324 158 119 4 +229 15 31 4 +229 60 15 4 +179 333 230 13 +102 103 162 18 +62 146 113 8 +169 65 209 7 +114 21 187 17 +75 238 74 5 +68 195 7 6 +68 7 226 14 +3 303 108 18 +3 108 241 17 +123 344 164 11 +57 58 168 5 +152 38 137 15 +46 169 65 7 +41 151 96 15 +215 202 167 9 +133 178 219 12 +84 186 265 8 +84 83 186 8 +98 247 97 11 +130 218 177 16 +79 6 82 6 +164 280 170 11 +112 149 180 17 +73 125 189 14 +249 91 16 10 +77 249 16 10 +174 211 190 10 +263 116 310 14 +163 167 202 9 +72 71 144 10 +32 40 151 15 +150 181 25 4 +56 192 188 8 +27 180 187 17 +182 294 237 6 +138 98 99 15 +196 79 78 6 +150 26 53 4 +201 229 127 4 +25 26 150 4 +47 48 330 17 +250 251 34 14 +4 42 157 6 +44 237 182 6 +83 198 194 6 +116 37 115 14 +93 87 8 11 +213 87 93 11 +39 156 42 9 +13 96 94 11 +41 13 94 13 +160 96 97 11 +151 97 96 15 +130 177 18 16 +130 18 17 16 +145 186 206 8 +251 34 33 14 +133 92 93 12 +120 294 182 6 +193 294 120 6 +144 249 341 10 +105 112 11 18 +142 26 25 7 +142 25 207 7 +41 104 130 16 +40 41 130 16 +55 54 223 5 +10 27 20 17 +5 103 106 18 +118 248 143 8 +88 87 213 11 +7 75 221 10 +7 226 75 14 +7 75 238 5 +212 247 160 11 +216 236 24 7 +109 171 124 18 +188 145 210 8 +57 210 145 8 +199 197 148 5 +199 148 73 5 +55 197 56 5 +229 31 30 4 +72 211 144 10 +174 144 211 10 +144 174 341 10 +131 70 69 19 +106 70 131 19 +126 170 280 11 +29 12 158 4 +249 77 76 10 +249 76 144 10 +153 30 136 14 +12 29 32 14 +20 217 252 9 +21 114 22 17 +175 22 114 17 +187 114 180 17 +80 334 221 10 +56 188 210 8 +57 56 210 8 +154 18 17 9 +98 99 344 11 +160 247 97 11 +38 116 155 14 +148 73 74 5 +215 134 202 9 +129 184 206 8 +160 212 95 11 +163 183 122 9 +20 10 25 7 +136 227 30 14 +139 223 59 5 +23 216 147 7 +198 82 83 6 +94 96 160 11 +83 186 145 8 +238 168 74 5 +160 94 95 11 +102 103 152 15 +156 43 42 9 +128 196 195 6 +67 133 178 12 +150 191 355 4 +1 46 240 6 +1 240 86 6 +227 15 31 14 +161 93 213 11 +230 77 95 13 +344 247 98 11 +192 143 118 8 +138 34 33 15 +237 45 2 6 +221 349 74 10 +135 349 221 10 +201 59 60 4 +242 231 166 8 +86 231 242 8 +228 184 129 8 +224 111 110 18 +356 66 67 6 +278 121 271 18 +71 15 227 14 +246 87 88 10 +108 234 241 17 +51 191 225 4 +152 103 70 15 +105 104 130 16 +159 104 105 18 +241 48 330 17 +178 80 68 12 +67 178 68 12 +181 25 10 4 +105 28 218 16 +11 28 105 16 +196 198 128 6 +24 2 236 7 +49 59 14 4 +36 137 35 15 +23 134 215 9 +143 357 248 8 +251 153 136 14 +225 127 204 4 +225 204 119 4 +158 29 204 4 +57 56 148 5 +203 149 114 17 +241 3 48 17 +99 137 100 15 +234 140 241 17 +178 81 80 12 +243 26 142 7 +153 32 33 14 +111 121 224 18 +278 224 121 18 +75 74 263 14 +97 96 159 18 +147 22 200 7 +140 175 205 17 +140 205 234 17 +123 344 247 11 +123 247 212 11 +130 40 12 16 +32 12 40 15 +59 54 14 5 +130 17 12 16 +32 17 12 9 +61 146 62 8 +253 338 202 9 +186 129 206 8 +263 116 155 14 +194 193 84 6 +219 284 81 12 +93 284 219 12 +35 163 183 9 +177 27 19 16 +92 93 161 11 +63 62 113 8 +192 188 118 8 +188 145 206 8 +21 252 167 9 +68 80 7 12 +32 29 153 14 +33 154 183 9 +102 152 137 15 +123 170 89 11 +44 2 237 6 +220 176 48 19 +220 48 107 19 +66 133 67 12 +4 69 133 12 +4 133 66 12 +20 207 25 7 +232 294 240 6 +148 74 168 5 +217 20 10 9 +250 117 172 14 +39 4 66 14 +338 37 253 9 +182 43 157 6 +40 333 41 13 +94 41 333 13 +82 58 145 8 +82 6 58 8 +338 38 37 9 +334 221 135 10 +107 220 131 19 +355 324 181 4 +355 181 150 4 +102 161 103 11 +126 213 161 11 +126 161 102 11 +90 89 123 11 +97 138 98 15 +232 86 240 6 +85 86 232 6 +85 232 193 6 +86 231 85 8 +60 229 201 4 +112 28 11 17 +37 253 36 9 +194 120 193 6 +71 76 15 10 +8 81 284 12 +8 284 93 12 +215 167 22 9 +190 135 349 10 +60 139 71 5 +60 71 15 5 +151 97 138 15 +150 52 191 4 +150 53 52 4 +50 49 201 4 +59 201 49 4 +40 333 12 13 +21 167 22 9 +338 134 202 9 +83 194 84 6 +32 154 17 9 +73 211 72 10 +43 176 44 19 +357 235 143 8 +116 189 310 14 +186 265 129 8 +85 84 193 6 +168 79 78 5 +40 41 151 15 +88 170 89 11 +138 35 34 15 +203 114 175 17 +75 74 221 10 +126 170 88 11 +126 88 213 11 +51 52 191 4 +263 67 155 14 +176 131 220 19 +245 135 334 10 +246 135 245 10 +165 171 278 18 +67 356 195 6 +74 349 73 10 +107 162 106 18 +107 214 162 18 +251 153 33 14 +199 197 139 5 +90 212 123 11 +227 71 136 14 +29 333 30 13 +236 45 2 7 +158 17 12 4 +224 110 171 18 +101 280 100 11 +101 100 137 15 +164 99 100 11 +163 202 253 9 +214 108 109 18 +124 214 109 18 +214 124 162 18 +185 248 118 8 +101 126 102 11 +280 126 101 11 +124 101 102 18 +64 209 147 7 +245 87 246 10 +8 87 245 10 +107 106 131 19 +58 6 239 5 +58 239 168 5 +195 78 196 6 +147 64 63 7 +72 125 136 14 +111 149 112 17 +237 294 45 6 +46 45 294 6 +196 79 82 6 +196 82 198 6 +28 180 112 17 +175 23 208 17 +45 169 46 7 +223 54 59 5 +71 139 72 5 +76 71 144 10 +216 169 236 7 +206 188 118 8 +145 82 83 8 +123 164 170 11 +95 77 16 13 +168 78 238 5 +7 238 78 5 +137 38 37 15 +100 165 101 18 +24 47 2 17 +208 47 24 17 +23 24 208 17 +23 134 24 9 +154 183 122 9 +20 21 187 17 +20 252 21 9 +56 148 197 5 +33 151 138 15 +18 324 17 4 +90 249 91 10 +89 90 174 10 +89 174 190 10 +146 53 52 8 +159 105 121 18 +207 21 200 7 +168 57 148 5 +38 37 116 14 +34 183 33 9 +203 149 111 17 +142 62 200 7 +227 30 31 14 +195 67 68 6 +172 36 35 14 +228 113 184 8 +241 330 140 17 +214 303 107 18 +112 121 111 18 +229 127 204 4 +29 333 12 13 +64 209 65 7 +22 200 21 7 +23 22 175 17 +200 63 62 7 +62 61 142 7 +110 205 203 17 +175 140 208 17 +174 90 341 10 +50 248 51 8 +65 242 166 8 +9 26 243 7 +206 184 118 8 +185 118 184 8 +51 185 52 8 +122 217 252 9 +189 74 310 14 +146 184 113 8 +169 45 236 7 +192 143 235 8 +192 235 55 8 +117 250 251 14 +20 207 21 7 +136 251 125 14 +155 39 38 14 +7 80 221 10 +263 67 226 14 +51 225 50 4 +172 115 36 14 +191 119 225 4 +127 225 201 4 +50 201 225 4 +99 344 164 11 +38 338 156 9 +112 121 105 18 +185 146 52 8 +265 231 85 8 +137 101 102 15 +99 165 278 18 +99 278 271 18 +357 248 50 8 +65 46 1 7 +146 244 53 8 +153 29 30 14 +88 89 190 10 +88 190 246 10 +30 204 229 4 +109 234 205 17 +110 109 205 17 +341 90 249 10 +108 303 214 18 +1 242 86 8 +1 242 65 8 +53 9 244 8 +184 185 146 8 +63 64 113 8 +146 244 61 8 +235 54 49 8 +8 245 81 10 +29 204 30 4 +251 125 117 14 +36 163 35 9 +139 199 72 5 +119 204 158 4 +36 115 37 14 +73 189 74 14 +66 155 67 14 +73 199 72 5 +211 349 73 10 +156 134 338 9 +129 228 166 8 +129 166 265 8 +47 208 330 17 +252 167 122 9 +50 49 357 8 +193 232 294 6 +263 310 74 14 +230 77 179 13 +271 121 159 18 +280 164 100 11 +240 294 46 6 +211 349 190 10 +22 215 23 9 +32 151 33 15 +179 30 333 13 +253 163 36 9 +99 165 100 18 +72 125 73 14 +138 99 137 15 +75 263 226 14 +135 246 190 10 +94 95 333 13 +226 67 68 14 +55 54 235 8 +18 181 324 4 +18 19 181 4 +55 197 223 5 +44 134 24 9 +44 24 2 9 +17 158 324 4 +356 195 128 6 +217 154 18 9 +356 120 194 6 +128 356 194 6 +69 39 152 15 +69 4 39 15 +139 197 223 5 +Tetrahedra +1947 +120 321 281 294 1 +116 268 310 141 2 +122 270 163 167 3 +345 346 269 222 2 +176 193 4 42 0 +23 200 236 147 0 +162 124 102 106 0 +254 347 306 132 1 +291 292 15 227 1 +355 119 324 191 0 +159 41 96 104 3 +152 335 38 39 2 +41 177 13 104 0 +18 217 19 177 3 +285 165 101 124 3 +161 92 70 103 2 +106 176 5 70 0 +282 157 66 356 1 +27 217 20 187 3 +296 23 24 216 1 +180 28 177 173 3 +9 53 315 26 1 +2 44 176 47 0 +19 181 324 25 0 +279 325 256 283 1 +311 32 33 312 2 +156 281 134 43 1 +351 92 70 161 2 +295 313 322 222 2 +111 175 110 203 0 +56 55 289 192 1 +136 291 72 71 1 +16 95 212 91 0 +19 324 10 25 0 +89 190 246 90 0 +231 321 85 232 1 +261 307 328 353 1 +171 124 165 319 3 +352 308 254 304 1 +107 165 3 108 0 +178 334 81 219 2 +44 43 134 182 1 +221 74 246 135 0 +350 220 330 241 3 +228 64 166 113 0 +185 288 51 248 1 +255 339 282 281 1 +176 131 43 42 0 +69 193 70 92 0 +213 246 88 322 2 +157 4 66 120 0 +307 306 287 167 1 +309 128 327 283 1 +40 130 177 104 0 +330 208 331 140 3 +11 218 177 28 0 +173 302 114 149 3 +37 137 36 222 2 +139 297 223 273 1 +332 4 39 42 3 +47 236 234 48 0 +147 23 22 272 1 +49 235 357 273 1 +341 249 77 91 0 +292 290 127 204 1 +70 176 5 193 0 +28 177 27 180 3 +179 76 30 31 0 +174 341 77 91 0 +173 114 180 149 3 +171 111 224 278 0 +86 166 265 231 0 +250 35 34 345 2 +313 190 174 295 2 +291 297 139 273 1 +48 107 3 303 3 +165 159 3 108 0 +80 246 81 334 0 +30 76 179 77 0 +125 348 117 189 1 +289 192 297 304 1 +109 171 165 110 0 +332 37 300 253 3 +343 230 95 333 2 +261 19 10 181 1 +203 111 175 187 0 +138 35 137 222 2 +63 147 200 276 1 +106 193 5 176 0 +69 4 131 42 0 +66 157 120 128 0 +61 142 9 26 0 +54 49 14 273 1 +281 120 182 157 1 +271 97 98 159 0 +232 193 240 46 0 +5 70 92 103 2 +186 325 274 206 1 +35 34 183 347 1 +351 93 219 133 2 +110 111 203 326 3 +47 331 176 330 3 +321 258 274 281 1 +341 313 174 269 2 +239 168 6 79 0 +172 116 115 222 2 +96 41 13 104 3 +43 331 329 176 3 +281 182 134 43 1 +90 212 342 91 2 +70 152 69 133 2 +326 114 175 260 3 +218 320 105 130 3 +257 256 297 304 1 +70 133 69 92 0 +61 200 207 142 0 +9 244 61 243 1 +245 219 81 334 2 +58 57 309 145 1 +203 175 205 326 3 +154 122 217 173 3 +261 181 150 353 1 +270 302 278 326 3 +65 166 64 113 0 +195 128 7 78 0 +175 11 234 28 0 +157 120 43 42 0 +172 117 348 189 1 +107 124 214 106 0 +130 41 151 159 3 +308 251 347 132 1 +165 102 106 103 0 +33 32 154 132 1 +76 15 177 31 0 +337 277 255 286 1 +157 356 120 128 0 +77 30 95 333 0 +305 266 276 353 1 +198 194 327 128 1 +216 209 169 272 1 +157 281 120 282 1 +61 243 315 142 1 +162 70 106 103 3 +295 172 116 189 2 +39 281 38 156 1 +19 217 10 27 3 +157 155 66 39 1 +25 324 177 26 0 +271 98 99 165 0 +190 174 73 197 0 +172 348 116 189 1 +350 241 214 303 3 +147 209 169 216 0 +172 35 250 222 2 +324 158 119 132 1 +229 60 15 31 0 +179 230 312 333 2 +324 191 177 26 0 +102 162 106 103 0 +62 146 113 305 1 +128 67 93 133 0 +212 95 159 94 0 +169 65 209 236 0 +114 175 21 187 0 +308 256 257 304 1 +131 332 329 42 3 +290 251 308 132 1 +282 301 255 283 1 +75 238 74 318 1 +354 254 266 353 1 +327 84 186 274 1 +68 7 226 195 1 +43 120 193 176 0 +3 108 241 303 3 +123 344 164 222 2 +66 335 155 141 2 +305 262 185 354 1 +213 92 161 103 0 +207 175 27 187 0 +152 38 137 285 3 +279 317 74 189 1 +46 169 65 275 1 +251 290 153 132 1 +159 293 173 121 3 +41 160 151 96 2 +287 215 167 202 1 +290 136 291 125 1 +133 178 219 141 2 +84 83 186 265 0 +98 97 346 247 2 +206 58 57 192 0 +226 178 68 141 2 +130 218 177 104 0 +79 128 6 82 0 +273 264 143 248 1 +164 280 170 222 2 +61 207 9 142 0 +109 165 159 110 0 +112 180 187 149 0 +73 348 125 189 1 +293 302 270 173 3 +77 249 16 91 0 +336 255 281 338 1 +174 190 73 211 0 +263 116 310 141 2 +111 110 159 165 0 +163 286 167 202 1 +354 118 277 304 1 +246 245 81 334 0 +64 236 200 209 0 +72 144 136 71 2 +32 40 151 130 3 +150 324 181 25 0 +306 183 328 132 1 +57 56 188 192 0 +258 274 255 337 1 +251 290 308 125 1 +27 28 180 187 0 +193 182 237 294 0 +138 98 99 271 3 +83 327 309 198 1 +196 318 79 78 1 +150 53 191 26 0 +201 229 127 119 0 +25 150 191 26 0 +159 212 94 247 0 +47 330 176 48 3 +257 297 139 291 1 +250 251 34 347 1 +315 150 25 26 1 +193 237 45 46 0 +176 43 120 42 0 +39 4 157 42 1 +311 40 312 333 2 +178 219 81 133 0 +89 322 313 170 2 +193 176 1 46 0 +44 323 237 182 1 +83 327 198 194 1 +116 37 115 222 2 +300 267 253 202 3 +245 213 351 246 2 +213 93 8 87 0 +288 191 262 51 1 +68 128 7 195 0 +213 212 90 91 0 +39 157 156 42 1 +317 257 73 348 1 +41 13 94 96 2 +151 160 97 96 2 +130 18 17 177 0 +321 84 193 274 1 +145 206 325 186 1 +310 301 279 189 1 +257 264 291 290 1 +305 185 184 354 1 +142 207 9 26 0 +251 34 33 345 2 +285 124 102 162 3 +177 30 76 31 0 +128 133 93 92 0 +235 55 297 273 1 +262 146 315 305 1 +193 120 182 294 0 +50 177 191 51 0 +124 107 165 106 0 +342 144 341 249 2 +200 65 1 236 0 +200 142 276 353 1 +105 11 159 112 0 +200 307 207 353 1 +352 325 256 304 1 +169 147 236 209 0 +126 280 298 322 2 +319 175 140 260 3 +307 200 276 353 1 +116 155 335 141 2 +142 25 207 26 0 +298 351 152 161 2 +290 30 153 204 1 +299 289 317 256 1 +269 346 311 247 2 +40 41 130 104 0 +256 308 257 348 1 +289 256 297 257 1 +55 54 223 273 1 +315 146 62 305 1 +220 350 107 303 3 +114 203 302 326 3 +10 20 207 27 0 +5 106 70 103 3 +319 110 205 326 3 +231 166 321 275 1 +118 143 304 248 1 +7 226 75 221 2 +325 289 299 256 1 +324 177 10 25 0 +170 280 322 222 2 +97 311 151 346 2 +39 157 281 156 1 +156 281 43 157 1 +7 168 75 238 0 +188 210 325 299 1 +212 160 94 247 0 +178 226 68 221 2 +296 216 24 236 1 +206 325 277 304 1 +109 124 165 171 0 +57 188 210 145 0 +83 198 128 193 0 +199 148 73 197 0 +55 56 289 197 1 +340 311 312 333 2 +66 67 157 128 0 +38 298 37 335 2 +69 133 128 92 0 +289 257 317 256 1 +229 30 158 31 0 +174 72 144 211 0 +144 76 174 341 0 +123 346 269 247 2 +190 73 168 197 0 +106 131 69 70 0 +126 280 322 170 2 +43 193 182 176 0 +29 12 158 177 0 +40 32 311 312 2 +140 208 234 47 0 +249 76 144 77 0 +174 211 144 269 2 +153 312 30 136 2 +77 16 139 174 0 +12 29 32 312 2 +165 111 171 121 0 +20 217 252 187 3 +175 21 22 114 0 +48 241 220 303 3 +187 114 180 173 3 +292 30 290 204 1 +124 165 102 106 0 +80 246 334 221 0 +174 190 211 295 2 +57 56 210 188 0 +154 18 17 130 3 +98 344 346 99 2 +96 160 97 247 0 +304 264 288 248 1 +165 106 5 103 0 +38 155 335 116 2 +275 233 258 272 1 +172 117 295 222 2 +291 264 297 273 1 +148 73 74 317 1 +215 336 134 202 1 +326 175 319 260 3 +275 45 323 294 1 +157 4 120 42 0 +305 142 315 353 1 +129 206 277 184 1 +266 258 337 272 1 +16 95 159 212 0 +311 160 95 212 2 +143 235 297 273 1 +72 257 291 125 1 +132 290 153 204 1 +144 340 269 125 2 +163 183 122 306 1 +20 261 10 25 1 +292 136 30 227 1 +213 87 245 284 2 +139 223 59 273 1 +254 354 316 353 1 +23 147 169 216 0 +130 154 18 173 3 +327 186 145 283 1 +198 83 128 82 0 +41 40 177 104 0 +86 193 1 46 0 +127 119 50 201 0 +219 351 133 141 2 +261 328 252 217 1 +187 177 217 173 3 +41 94 160 96 2 +217 19 261 328 1 +83 186 145 327 1 +275 258 296 272 1 +238 168 74 318 1 +160 95 212 94 0 +131 152 69 70 3 +264 290 316 225 1 +67 356 157 128 0 +226 318 314 195 1 +102 152 162 103 3 +16 212 213 91 0 +156 157 43 42 1 +348 117 308 125 1 +269 117 295 125 2 +128 318 196 195 1 +93 67 178 133 0 +237 2 176 193 0 +150 355 324 191 0 +1 240 86 46 0 +227 292 15 31 1 +161 351 93 213 2 +230 77 95 333 0 +344 98 346 247 2 +107 176 193 106 0 +192 143 118 248 0 +138 34 33 293 3 +130 41 159 104 3 +237 2 193 45 0 +175 207 21 187 0 +135 221 74 349 0 +190 16 246 91 0 +96 13 159 104 0 +93 193 8 128 0 +201 60 50 59 0 +119 355 324 132 1 +86 242 166 231 0 +228 129 337 184 1 +224 111 110 326 3 +193 128 93 92 0 +356 157 66 67 0 +278 271 165 121 0 +128 193 6 82 0 +112 105 11 320 3 +231 86 242 275 1 +75 226 318 314 1 +112 11 234 175 0 +71 291 15 227 1 +229 292 30 31 1 +252 114 187 173 3 +47 234 140 330 0 +344 123 346 222 2 +287 307 22 200 1 +263 74 221 349 2 +108 214 234 241 3 +186 84 265 274 1 +51 288 191 225 1 +43 331 134 329 3 +194 274 327 282 1 +332 39 156 42 3 +152 70 162 103 3 +292 136 291 290 1 +159 105 130 104 3 +234 241 330 48 0 +114 270 167 260 3 +70 193 5 92 0 +67 178 68 80 0 +117 172 348 259 1 +128 196 79 78 0 +32 153 158 132 1 +69 128 193 92 0 +261 181 10 25 1 +11 105 218 28 0 +196 128 79 198 0 +213 165 5 103 0 +24 208 2 236 0 +271 98 165 159 0 +256 352 301 283 1 +49 59 14 273 1 +266 337 233 272 1 +287 22 23 272 1 +36 137 35 222 2 +354 185 118 304 1 +251 312 136 269 2 +116 348 301 189 1 +23 336 134 215 1 +143 192 357 248 0 +13 159 94 96 0 +171 109 124 319 3 +200 147 63 209 0 +251 153 136 312 2 +285 38 37 332 3 +158 60 229 31 0 +225 119 127 204 0 +262 185 146 305 1 +158 153 29 204 1 +57 56 148 299 1 +249 343 16 91 2 +65 1 86 166 0 +23 296 134 336 1 +237 193 232 46 0 +203 114 302 149 3 +60 201 50 158 0 +246 90 190 91 0 +241 234 3 48 0 +258 255 281 336 1 +147 233 209 272 1 +99 137 100 222 2 +47 234 330 48 0 +234 350 140 241 3 +324 328 154 132 1 +128 178 80 81 0 +193 2 176 45 0 +298 152 102 161 2 +159 98 344 247 0 +295 116 268 189 2 +61 243 142 26 0 +340 311 343 342 2 +153 32 33 132 1 +278 111 224 121 0 +320 159 105 130 3 +75 314 74 263 1 +97 151 96 159 3 +65 1 166 265 0 +147 22 200 272 1 +326 270 114 260 3 +177 130 18 173 3 +176 106 69 70 0 +176 69 131 42 0 +140 205 234 175 0 +158 30 177 31 0 +320 173 302 121 3 +29 158 30 177 0 +217 19 10 261 1 +267 332 300 253 3 +186 327 274 283 1 +269 211 144 125 2 +123 212 344 247 0 +313 123 170 222 2 +181 19 10 25 0 +61 200 9 207 0 +175 234 207 28 0 +32 130 12 40 3 +59 54 14 273 1 +130 17 12 40 0 +32 17 12 130 3 +61 146 62 315 1 +30 136 292 153 1 +265 83 186 206 0 +170 322 313 222 2 +253 267 338 202 3 +233 65 64 275 1 +264 254 308 304 1 +186 274 129 206 1 +277 325 352 304 1 +301 263 155 116 1 +315 142 261 353 1 +14 54 223 197 0 +194 84 274 193 1 +188 192 289 304 1 +320 105 11 28 3 +18 19 324 177 0 +117 172 295 189 2 +93 219 81 284 0 +66 128 4 69 0 +270 35 183 163 3 +77 16 174 91 0 +305 276 142 353 1 +177 19 10 27 0 +92 351 93 161 2 +63 276 62 113 1 +192 188 118 304 1 +299 317 279 256 1 +188 325 145 206 1 +278 300 270 326 3 +21 252 167 114 3 +59 14 177 49 0 +93 128 8 81 0 +67 128 93 81 0 +286 287 167 202 1 +128 68 7 80 0 +67 68 128 80 0 +93 178 81 133 0 +128 67 80 178 0 +32 29 153 312 2 +307 328 252 261 1 +346 269 311 345 2 +33 154 183 132 1 +80 221 334 178 2 +132 153 158 204 1 +92 213 5 103 0 +159 165 109 108 0 +123 313 269 222 2 +299 57 210 145 1 +311 269 212 342 2 +102 152 137 285 3 +134 267 260 202 3 +266 287 307 306 1 +123 89 313 170 2 +328 183 154 132 1 +44 323 2 237 1 +220 107 176 48 0 +66 67 128 133 0 +69 66 128 133 0 +4 66 69 133 0 +320 302 111 121 3 +20 10 207 25 0 +275 232 240 294 1 +148 74 168 279 1 +332 156 329 42 3 +40 130 17 177 0 +281 39 282 157 1 +298 335 152 351 2 +217 20 10 27 3 +250 117 172 222 2 +225 316 119 204 1 +39 4 66 157 1 +339 338 253 37 1 +182 120 43 157 0 +94 40 41 333 0 +82 265 6 206 0 +82 6 58 145 0 +176 193 45 46 0 +108 234 3 241 0 +338 339 38 37 1 +270 302 114 173 3 +309 327 145 283 1 +234 111 112 175 0 +334 221 135 141 2 +340 76 249 77 2 +350 107 131 220 3 +355 181 150 324 0 +102 213 161 103 0 +126 161 102 213 0 +90 89 123 170 0 +311 340 343 333 2 +65 1 265 113 0 +97 346 138 98 2 +167 270 163 260 3 +262 315 52 150 1 +232 193 86 240 0 +198 194 128 193 0 +85 193 86 232 0 +86 231 85 232 1 +266 233 276 272 1 +158 60 201 229 0 +16 212 159 213 0 +297 55 223 273 1 +188 289 210 299 1 +159 111 165 121 0 +130 293 154 173 3 +112 11 175 28 0 +165 280 102 213 0 +300 37 36 253 3 +194 193 274 120 1 +71 15 139 76 0 +87 246 88 213 2 +8 93 81 284 0 +215 167 22 287 1 +190 322 135 349 2 +60 15 139 71 0 +234 175 110 111 0 +151 97 138 293 3 +150 53 52 191 0 +151 41 96 159 3 +65 265 166 113 0 +59 50 201 49 0 +40 12 312 333 2 +21 167 22 114 3 +291 229 127 201 1 +318 279 74 314 1 +338 267 134 202 3 +83 84 327 194 1 +176 329 220 331 3 +218 105 177 104 0 +32 154 17 130 3 +150 191 324 25 0 +208 267 331 140 3 +73 72 174 211 0 +293 271 278 121 3 +191 262 52 150 1 +221 178 226 141 2 +261 150 25 315 1 +176 107 3 48 0 +43 44 331 176 3 +357 235 143 273 1 +122 183 293 173 3 +106 69 131 176 0 +217 20 252 261 1 +257 308 290 125 1 +215 287 336 202 1 +268 116 310 189 2 +60 291 139 273 1 +183 154 293 173 3 +177 18 217 173 3 +254 308 316 264 1 +221 246 334 135 0 +354 264 288 304 1 +138 97 98 293 3 +186 265 129 274 1 +335 133 152 351 2 +299 56 148 289 1 +76 227 15 31 2 +83 84 194 193 0 +194 120 128 193 0 +234 236 3 48 0 +277 274 255 283 1 +208 134 331 267 3 +299 56 289 210 1 +85 84 193 321 1 +111 110 165 171 0 +286 258 266 272 1 +169 23 236 147 0 +94 41 311 333 2 +40 41 151 130 3 +341 76 174 77 0 +251 33 347 132 1 +347 306 163 286 1 +240 1 242 275 1 +213 88 89 170 0 +138 35 34 293 3 +102 161 152 103 2 +152 161 70 103 2 +311 41 40 333 2 +203 114 175 326 3 +116 259 115 339 1 +75 74 221 263 2 +126 88 213 170 0 +51 191 262 52 1 +198 128 79 82 0 +77 230 343 340 2 +258 281 296 336 1 +263 67 155 141 2 +156 281 336 134 1 +43 182 44 176 0 +72 174 139 197 0 +213 89 90 344 0 +176 329 131 220 3 +246 245 334 135 0 +281 323 296 182 1 +276 287 266 272 1 +209 233 64 275 1 +309 83 198 82 1 +165 171 278 121 0 +317 148 199 197 1 +314 67 195 356 1 +227 76 179 31 2 +316 254 264 304 1 +190 74 73 349 0 +224 171 278 326 3 +287 23 336 272 1 +92 133 93 351 2 +107 214 162 106 0 +262 316 354 353 1 +114 252 270 173 3 +201 119 50 158 0 +180 177 27 187 3 +291 136 292 227 1 +317 279 348 189 1 +251 153 33 132 1 +275 209 233 272 1 +93 67 81 178 0 +128 67 178 81 0 +151 345 33 346 2 +192 118 357 248 0 +346 311 151 345 2 +269 117 345 222 2 +315 53 52 150 1 +165 300 278 326 3 +111 302 224 121 3 +219 93 81 133 0 +257 199 139 197 1 +51 177 191 52 0 +60 158 50 59 0 +297 192 143 304 1 +264 127 291 290 1 +300 163 260 202 3 +191 177 50 49 0 +15 60 158 31 0 +191 53 177 26 0 +171 110 319 326 3 +52 53 177 191 0 +90 123 342 212 2 +171 165 278 326 3 +144 227 136 71 2 +136 179 30 227 2 +80 334 81 178 2 +187 180 177 173 3 +312 29 30 333 2 +127 264 291 273 1 +12 312 32 40 2 +342 123 269 212 2 +323 236 2 45 1 +158 17 12 32 1 +29 158 12 32 1 +153 158 29 32 1 +224 110 171 326 3 +150 262 315 353 1 +154 17 158 32 1 +325 277 274 206 1 +345 117 250 222 2 +101 100 137 280 2 +164 99 100 222 2 +340 230 343 333 2 +163 253 286 202 1 +141 135 268 349 2 +346 34 33 138 2 +175 207 27 28 0 +182 323 237 294 1 +241 350 220 303 3 +177 217 19 27 3 +275 296 169 272 1 +200 175 236 234 0 +342 212 343 91 2 +88 126 322 170 2 +214 109 165 108 0 +124 109 165 214 0 +124 165 107 214 0 +184 277 266 354 1 +214 124 162 106 0 +304 185 118 248 1 +280 101 102 126 0 +124 101 102 165 0 +167 21 22 307 1 +299 210 325 145 1 +233 64 147 209 1 +312 32 33 153 2 +120 281 182 294 1 +281 182 43 157 1 +73 211 295 125 2 +63 233 147 272 1 +179 76 340 77 2 +119 316 355 132 1 +278 171 111 121 0 +300 138 165 278 3 +335 66 133 141 2 +8 245 246 87 0 +214 165 107 108 0 +168 299 148 279 1 +178 67 68 141 2 +180 112 320 149 3 +229 158 127 119 0 +201 158 229 119 0 +112 320 11 28 3 +107 131 220 106 0 +335 116 298 37 2 +11 105 177 218 0 +219 178 334 141 2 +337 129 265 274 1 +279 301 314 283 1 +69 4 332 131 3 +58 168 6 239 0 +128 195 196 78 0 +325 299 145 283 1 +209 147 63 64 0 +255 301 352 283 1 +176 330 220 48 3 +348 308 257 125 1 +276 63 147 272 1 +173 320 159 121 3 +136 269 340 125 2 +75 318 74 314 1 +144 72 136 125 2 +50 191 119 51 0 +73 317 348 189 1 +187 111 112 149 0 +184 266 113 305 1 +198 128 327 309 1 +46 237 45 294 0 +196 198 79 82 0 +28 112 320 180 3 +136 227 291 71 1 +175 23 208 260 3 +343 95 16 91 2 +45 169 46 275 1 +28 218 177 173 3 +64 65 200 236 0 +334 351 219 141 2 +191 288 316 225 1 +39 282 339 281 1 +223 54 59 273 1 +174 71 72 139 0 +76 71 174 139 0 +174 76 139 77 0 +340 144 342 249 2 +76 71 144 174 0 +144 71 72 174 0 +325 188 289 304 1 +296 216 236 169 1 +281 258 296 323 1 +206 6 58 192 0 +57 188 206 192 0 +206 188 118 192 0 +200 209 63 64 0 +69 176 4 42 0 +145 83 309 82 1 +233 64 166 228 1 +297 289 257 197 1 +328 19 261 181 1 +123 164 170 222 2 +232 231 321 275 1 +291 60 139 71 1 +291 60 229 201 1 +213 102 165 103 0 +30 177 76 77 0 +177 30 95 77 0 +95 16 177 77 0 +30 177 95 94 0 +29 177 30 94 0 +177 29 40 94 0 +40 177 94 41 0 +177 13 94 41 0 +29 12 177 40 0 +12 17 177 40 0 +177 53 9 26 0 +309 57 299 145 1 +234 11 207 28 0 +268 295 322 222 2 +300 171 319 326 3 +30 292 290 153 1 +7 168 238 78 0 +188 210 145 325 1 +130 105 218 104 0 +137 38 37 285 3 +128 282 194 327 1 +285 100 101 165 3 +169 65 236 46 0 +208 24 2 47 0 +216 147 209 272 1 +169 296 216 272 1 +355 316 328 132 1 +250 259 117 308 1 +23 134 24 208 3 +354 288 185 304 1 +67 263 155 282 1 +154 183 122 173 3 +20 252 21 187 3 +56 57 148 197 0 +291 136 72 125 1 +180 28 112 187 0 +175 112 28 187 0 +33 151 138 293 3 +290 127 291 292 1 +73 148 74 197 0 +176 120 193 42 0 +193 120 4 42 0 +69 193 4 176 0 +69 176 70 193 0 +27 20 207 187 0 +241 220 330 48 3 +344 280 165 213 0 +97 346 151 138 2 +252 270 167 114 3 +18 324 17 177 0 +173 320 302 149 3 +60 139 59 273 1 +212 159 344 247 0 +329 267 330 331 3 +142 315 25 26 1 +352 254 286 277 1 +259 348 116 172 1 +311 97 160 247 2 +190 90 174 91 0 +174 16 190 91 0 +346 97 311 247 2 +144 76 341 77 0 +269 313 174 295 2 +154 158 324 132 1 +77 343 16 249 2 +90 342 249 91 2 +74 73 168 190 0 +301 279 256 283 1 +327 128 282 283 1 +27 175 28 187 0 +27 177 217 187 3 +89 174 190 90 0 +182 237 176 193 0 +175 207 234 200 0 +225 264 127 273 1 +83 194 198 193 0 +291 60 15 229 1 +146 53 52 315 1 +348 301 259 116 1 +293 300 270 278 3 +159 320 105 121 3 +286 266 287 272 1 +259 352 348 308 1 +207 175 21 200 0 +7 68 226 221 2 +168 57 148 299 1 +193 128 83 82 0 +343 311 95 212 2 +143 264 304 248 1 +38 335 37 116 2 +293 34 33 183 3 +187 203 111 149 0 +43 120 182 193 0 +142 276 62 200 1 +227 179 30 31 2 +195 67 68 128 0 +66 120 193 128 0 +66 193 4 128 0 +128 193 4 69 0 +66 120 4 193 0 +172 36 35 222 2 +266 228 184 113 1 +337 258 233 272 1 +176 44 331 47 3 +193 107 3 176 0 +193 274 120 321 1 +277 325 274 283 1 +234 241 140 330 0 +285 124 267 319 3 +20 207 261 25 1 +207 142 261 25 1 +214 107 350 303 3 +211 269 174 295 2 +308 290 316 264 1 +181 261 150 25 1 +112 111 159 121 0 +142 207 261 353 1 +132 306 316 353 1 +337 274 255 277 1 +23 22 200 147 0 +231 242 166 275 1 +315 261 150 353 1 +111 203 302 149 3 +236 175 208 234 0 +236 208 2 47 0 +234 267 140 350 3 +200 147 209 236 0 +229 292 127 204 1 +40 29 12 333 0 +64 65 236 209 0 +140 267 319 260 3 +277 254 266 354 1 +234 208 236 47 0 +240 193 86 46 0 +22 21 175 200 0 +23 22 175 200 0 +308 259 352 254 1 +127 290 225 204 1 +281 296 134 182 1 +354 277 254 304 1 +158 154 32 132 1 +62 200 61 142 0 +23 200 175 236 0 +110 175 205 203 0 +205 175 110 234 0 +234 175 208 140 0 +174 90 341 91 0 +331 267 330 140 3 +50 51 288 248 1 +148 199 73 317 1 +86 65 166 242 0 +341 144 77 249 0 +9 243 61 26 0 +237 44 182 176 0 +206 118 277 184 1 +185 118 184 354 1 +288 316 262 191 1 +30 158 127 229 0 +282 274 281 120 1 +264 257 297 304 1 +9 315 243 26 1 +23 287 336 215 1 +28 320 105 218 3 +292 136 290 153 1 +58 145 309 82 1 +161 298 351 126 2 +205 175 319 326 3 +51 262 185 52 1 +206 145 83 186 0 +21 252 261 307 1 +270 183 293 122 3 +292 227 30 31 1 +297 264 143 273 1 +142 243 315 26 1 +134 336 338 202 1 +154 293 33 183 3 +82 6 145 206 0 +145 6 58 206 0 +145 58 57 206 0 +57 188 145 206 0 +268 295 189 349 2 +232 86 231 275 1 +287 307 276 266 1 +194 274 282 120 1 +332 338 37 253 3 +328 122 252 217 1 +189 74 310 349 2 +292 229 15 31 1 +114 203 175 187 0 +332 38 37 338 3 +118 185 184 206 0 +74 310 279 189 1 +282 274 255 281 1 +316 191 119 355 1 +279 299 148 317 1 +69 152 131 332 3 +146 184 113 305 1 +190 139 174 197 0 +175 140 205 319 3 +258 337 321 274 1 +297 257 139 197 1 +337 277 286 266 1 +323 169 236 45 1 +270 252 122 173 3 +165 171 300 326 3 +307 306 328 353 1 +192 235 297 143 1 +114 21 252 187 3 +192 55 297 235 1 +117 250 251 345 2 +250 345 34 251 2 +270 163 183 122 3 +329 156 43 42 3 +293 270 122 173 3 +265 145 83 206 0 +293 138 300 278 3 +261 20 21 207 1 +286 287 336 272 1 +136 340 144 125 2 +136 290 251 125 1 +323 281 258 294 1 +187 114 203 149 0 +302 278 224 121 3 +77 95 16 343 2 +107 213 3 165 0 +165 107 213 106 0 +213 106 5 165 0 +92 161 93 213 0 +256 308 348 352 1 +87 213 245 246 2 +220 131 176 106 0 +107 220 176 106 0 +335 66 155 39 2 +335 155 38 39 2 +205 110 203 326 3 +261 328 181 353 1 +77 340 343 249 2 +7 221 75 80 0 +7 68 221 80 2 +178 221 68 80 2 +263 226 314 67 1 +265 86 1 166 0 +341 269 174 144 2 +344 90 123 170 0 +343 340 342 249 2 +281 321 258 294 1 +90 313 174 341 2 +314 263 67 282 1 +335 268 298 116 2 +277 255 352 283 1 +298 137 37 222 2 +350 214 234 319 3 +207 20 21 187 0 +54 14 223 59 0 +223 14 139 59 0 +191 316 262 355 1 +282 356 66 67 1 +291 257 290 125 1 +111 110 171 224 0 +287 286 336 202 1 +264 308 257 304 1 +51 50 288 225 1 +119 127 50 225 0 +260 167 215 202 3 +288 264 316 225 1 +298 268 322 222 2 +295 73 125 189 2 +172 115 36 222 2 +57 56 299 210 1 +309 279 314 283 1 +191 316 119 225 1 +51 191 119 225 0 +50 127 201 225 0 +215 134 260 202 3 +253 338 336 202 1 +119 50 51 225 0 +37 116 298 222 2 +130 218 320 173 3 +144 76 227 71 2 +76 71 15 227 2 +99 164 100 344 0 +112 320 111 121 3 +310 263 141 349 2 +83 84 186 327 1 +259 35 347 250 1 +323 258 296 275 1 +38 338 156 281 1 +225 290 316 204 1 +267 332 253 338 3 +316 306 254 353 1 +338 253 336 255 1 +320 112 105 121 3 +257 264 297 291 1 +195 318 196 78 1 +129 228 206 184 0 +318 168 74 279 1 +185 146 52 262 1 +152 285 102 162 3 +140 208 267 260 3 +192 55 289 297 1 +198 128 309 196 1 +86 265 85 231 0 +274 282 255 283 1 +275 169 209 272 1 +64 233 147 63 1 +156 329 43 134 3 +258 233 321 337 1 +322 280 298 222 2 +137 101 102 285 3 +285 101 102 124 3 +228 337 166 233 1 +166 65 64 233 1 +89 170 344 213 0 +344 170 280 213 0 +191 355 262 150 1 +99 271 165 278 0 +280 137 298 222 2 +351 135 268 141 2 +357 50 273 248 1 +142 200 207 353 1 +236 65 1 46 0 +146 53 315 244 1 +82 145 83 265 0 +253 286 259 163 1 +75 168 74 238 0 +169 236 45 46 0 +153 29 30 312 2 +142 315 62 305 1 +88 190 246 89 0 +357 118 185 248 0 +212 123 269 247 2 +82 145 265 206 0 +127 30 229 204 0 +2 44 237 176 0 +77 230 95 343 2 +110 109 205 234 0 +44 134 323 182 1 +323 134 296 182 1 +108 214 109 234 3 +184 118 277 354 1 +341 90 249 91 0 +241 108 214 303 3 +182 281 323 294 1 +216 23 236 169 0 +216 23 24 236 0 +236 23 24 208 0 +23 175 208 236 0 +38 339 116 37 1 +1 242 86 240 1 +1 65 86 242 0 +273 50 288 248 1 +245 351 219 334 2 +252 20 21 261 1 +118 206 277 304 1 +116 268 298 222 2 +181 328 355 353 1 +337 228 266 233 1 +233 228 266 113 1 +233 64 228 113 1 +288 262 185 51 1 +310 268 189 349 2 +228 206 184 244 0 +206 185 184 244 0 +184 185 146 244 0 +146 185 52 244 0 +185 51 52 244 0 +53 146 52 244 0 +334 135 351 141 2 +184 244 146 113 0 +146 244 62 113 0 +62 244 63 113 0 +63 244 64 113 0 +65 64 244 113 0 +65 244 1 113 0 +219 245 81 284 2 +228 244 184 113 0 +146 61 62 244 0 +235 357 54 49 0 +168 74 190 246 0 +168 74 246 75 0 +75 74 246 221 0 +75 246 80 221 0 +255 352 286 277 1 +246 168 80 81 0 +81 168 8 246 0 +8 245 81 246 0 +168 7 246 80 0 +246 7 75 80 0 +168 7 75 246 0 +87 8 245 284 2 +213 280 102 126 0 +165 100 101 280 0 +201 50 225 273 1 +61 315 62 142 1 +158 29 30 204 0 +257 139 72 291 1 +325 352 256 283 1 +312 179 136 340 2 +165 101 102 280 0 +218 130 177 173 3 +157 282 120 356 1 +228 265 206 244 0 +251 117 269 125 2 +213 170 280 126 0 +315 53 150 26 1 +55 54 168 197 0 +228 265 244 113 0 +299 325 279 283 1 +265 228 166 113 0 +300 36 35 163 3 +72 73 174 197 0 +139 199 72 197 0 +345 35 34 138 2 +45 237 323 294 1 +225 127 201 273 1 +351 161 70 152 2 +201 291 60 273 1 +241 214 234 350 3 +127 291 201 273 1 +119 158 127 204 0 +129 265 186 206 0 +129 228 265 206 0 +329 350 220 330 3 +309 198 196 82 1 +256 289 297 304 1 +336 23 296 272 1 +158 30 127 204 0 +36 115 37 222 2 +73 74 168 197 0 +175 111 112 187 0 +292 229 30 204 1 +214 124 109 319 3 +277 352 254 304 1 +212 311 160 247 2 +318 168 79 78 1 +128 314 318 195 1 +278 302 224 326 3 +314 282 128 283 1 +63 200 62 276 1 +260 267 300 202 3 +135 351 245 334 2 +317 73 74 189 1 +308 254 316 132 1 +264 297 143 304 1 +318 7 238 78 1 +331 329 220 330 3 +312 251 345 269 2 +99 138 271 278 3 +274 277 129 206 1 +312 345 311 269 2 +306 286 167 163 1 +280 100 137 222 2 +321 274 120 281 1 +29 153 30 204 1 +159 105 112 121 0 +20 217 10 261 1 +126 298 102 161 2 +336 253 286 255 1 +118 325 188 206 1 +188 289 299 325 1 +271 138 293 278 3 +66 155 67 141 2 +161 351 213 126 2 +270 35 293 183 3 +116 295 268 222 2 +316 264 354 304 1 +322 190 295 349 2 +329 350 131 220 3 +291 229 15 292 1 +195 7 318 78 1 +242 1 65 275 1 +86 232 240 275 1 +291 139 72 71 1 +199 139 72 257 1 +73 199 72 257 1 +347 259 286 163 1 +293 35 34 183 3 +329 267 134 338 3 +344 99 164 222 2 +238 168 318 78 1 +309 196 79 82 1 +246 74 190 349 0 +211 73 295 349 2 +301 310 314 263 1 +156 329 134 338 3 +240 242 86 275 1 +35 34 347 250 1 +257 289 317 197 1 +56 55 168 197 0 +346 345 138 222 2 +290 264 127 225 1 +99 344 346 222 2 +126 351 268 298 2 +292 127 291 229 1 +267 330 140 350 3 +351 335 133 141 2 +133 66 67 141 2 +268 351 335 298 2 +129 166 265 228 0 +254 259 352 286 1 +47 208 330 140 0 +167 215 22 260 3 +156 338 336 281 1 +337 129 277 184 1 +286 254 266 277 1 +302 293 270 278 3 +200 307 276 287 1 +125 117 295 189 2 +21 307 207 200 1 +310 116 301 189 1 +252 122 307 167 1 +21 252 307 167 1 +122 306 167 163 1 +50 49 357 273 1 +308 257 290 264 1 +73 199 257 317 1 +325 277 352 283 1 +140 175 208 260 3 +193 237 232 294 0 +172 295 116 222 2 +226 314 68 195 1 +180 320 173 149 3 +263 310 74 349 2 +230 179 312 340 2 +230 179 340 77 2 +216 23 147 272 1 +321 232 275 294 1 +120 193 321 294 1 +135 74 246 349 0 +146 315 52 262 1 +94 29 40 333 0 +136 251 269 125 2 +252 122 167 270 3 +318 7 75 238 1 +325 145 186 283 1 +234 109 205 319 3 +67 263 226 141 2 +143 192 118 304 1 +132 316 328 353 1 +165 271 159 121 0 +307 21 22 200 1 +328 181 355 324 1 +352 348 256 301 1 +351 246 135 245 2 +133 67 178 141 2 +271 293 159 121 3 +199 73 72 197 0 +142 261 25 315 1 +267 208 134 260 3 +38 137 37 298 2 +225 288 264 273 1 +101 137 298 280 2 +61 244 146 315 1 +167 307 22 287 1 +304 288 185 248 1 +343 212 95 91 2 +266 286 306 254 1 +22 175 114 260 3 +217 122 252 173 3 +259 254 347 286 1 +138 293 98 271 3 +256 257 317 348 1 +274 255 281 258 1 +231 265 85 321 1 +299 309 145 283 1 +280 164 100 222 2 +345 312 33 153 2 +189 73 74 349 2 +295 269 313 222 2 +36 259 172 35 1 +254 308 259 347 1 +38 39 339 281 1 +216 296 23 272 1 +181 355 150 353 1 +155 282 66 67 1 +268 322 246 213 2 +155 157 66 282 1 +157 282 155 39 1 +90 342 341 249 2 +301 282 314 283 1 +339 301 259 255 1 +166 321 265 231 1 +321 84 274 265 1 +85 84 321 265 1 +321 193 85 232 1 +325 186 274 283 1 +245 8 81 284 2 +54 235 49 273 1 +275 258 321 294 1 +312 179 30 136 2 +232 321 193 294 1 +240 46 275 294 1 +33 347 183 34 1 +153 251 33 345 2 +211 190 73 349 0 +153 251 345 312 2 +137 100 101 285 3 +22 215 23 260 3 +173 293 302 121 3 +339 38 281 338 1 +258 337 255 286 1 +258 337 286 266 1 +310 74 314 263 1 +317 299 148 289 1 +296 258 336 272 1 +150 355 262 353 1 +233 276 63 113 1 +350 267 329 332 3 +295 268 322 349 2 +306 266 254 353 1 +215 22 23 287 1 +141 268 310 349 2 +270 300 35 163 3 +350 330 140 241 3 +329 267 350 330 3 +56 192 289 188 1 +210 56 289 188 1 +137 36 35 300 3 +278 302 293 121 3 +194 84 327 274 1 +49 50 201 273 1 +285 300 165 319 3 +258 255 336 286 1 +350 234 267 319 3 +116 301 259 339 1 +187 217 252 173 3 +101 298 102 126 2 +101 280 298 126 2 +9 53 244 315 1 +316 290 132 204 1 +290 136 251 153 1 +282 274 327 283 1 +163 300 253 202 3 +46 65 1 275 1 +46 1 240 275 1 +302 320 111 149 3 +297 55 289 197 1 +6 309 79 82 1 +6 58 309 82 1 +293 97 98 271 3 +71 60 15 291 1 +225 50 288 273 1 +168 54 14 197 0 +74 148 168 197 0 +293 97 271 159 3 +151 97 293 159 3 +130 159 151 293 3 +32 151 293 130 3 +32 293 154 130 3 +314 128 309 283 1 +299 279 309 283 1 +32 293 33 154 3 +32 151 33 293 3 +116 263 155 141 2 +295 211 269 125 2 +126 268 322 298 2 +179 227 136 340 2 +311 312 33 345 2 +117 345 251 269 2 +201 59 49 273 1 +339 301 155 116 1 +33 251 347 34 1 +250 251 347 308 1 +315 262 305 353 1 +35 183 163 347 1 +134 23 215 260 3 +321 337 265 274 1 +337 129 166 265 1 +321 337 166 265 1 +57 168 148 197 0 +336 258 286 272 1 +337 277 266 184 1 +228 337 266 184 1 +134 23 24 296 1 +331 134 329 267 3 +176 331 220 330 3 +131 329 43 42 3 +316 355 328 353 1 +352 256 308 304 1 +256 325 289 304 1 +116 335 268 141 2 +179 312 30 333 2 +38 152 137 298 2 +152 102 137 298 2 +101 137 102 298 2 +282 263 155 301 1 +213 268 322 126 2 +300 253 36 163 3 +302 270 114 326 3 +83 327 145 309 1 +107 214 108 303 0 +137 37 36 300 3 +137 37 300 285 3 +137 100 285 300 3 +300 100 285 165 3 +300 99 100 165 3 +138 99 300 165 3 +72 73 257 125 1 +211 73 72 125 2 +348 257 73 125 1 +308 117 251 125 1 +293 130 159 173 3 +300 35 293 270 3 +138 35 293 300 3 +35 138 137 300 3 +138 99 137 300 3 +137 99 100 300 3 +143 357 273 248 1 +273 288 264 248 1 +307 122 252 328 1 +306 122 307 328 1 +75 226 314 263 1 +325 118 188 304 1 +141 221 135 349 2 +148 317 74 279 1 +226 7 318 195 1 +345 250 35 222 2 +135 322 268 349 2 +135 246 190 349 0 +354 254 316 304 1 +178 221 334 141 2 +22 287 200 272 1 +276 233 63 272 1 +289 56 148 197 1 +287 306 286 167 1 +266 287 306 286 1 +141 263 221 349 2 +57 56 168 197 0 +148 317 289 197 1 +3 241 48 303 3 +279 256 317 348 1 +320 28 180 173 3 +218 28 320 173 3 +307 122 306 167 1 +163 270 300 260 3 +21 261 207 307 1 +279 256 348 301 1 +117 259 348 308 1 +130 320 159 173 3 +116 259 172 115 1 +295 190 211 349 2 +189 295 73 349 2 +117 251 250 308 1 +317 199 257 197 1 +58 57 168 309 1 +309 57 168 299 1 +168 279 309 299 1 +276 142 62 305 1 +58 168 239 309 1 +239 168 79 309 1 +124 285 165 319 3 +6 239 79 309 1 +6 58 239 309 1 +97 160 151 311 2 +41 160 311 151 2 +41 311 40 151 2 +40 32 151 311 2 +151 32 33 311 2 +90 89 174 313 2 +345 34 33 346 2 +151 346 33 138 2 +345 34 346 138 2 +59 201 60 273 1 +249 342 343 91 2 +342 311 343 212 2 +90 89 313 123 2 +171 165 300 319 3 +113 266 276 305 1 +22 23 175 260 3 +237 323 2 45 1 +159 213 344 165 0 +355 328 324 132 1 +311 95 160 94 2 +41 94 311 160 2 +306 316 254 132 1 +114 167 22 260 3 +89 190 174 313 2 +314 67 68 195 1 +267 234 140 319 3 +344 89 90 170 0 +116 301 263 310 1 +282 314 263 301 1 +94 311 95 333 2 +30 29 94 333 0 +226 67 68 314 1 +246 322 135 190 2 +357 55 235 54 0 +50 324 119 191 0 +259 253 163 36 1 +19 177 10 324 0 +18 19 181 324 0 +25 191 324 26 0 +310 74 279 314 1 +301 310 279 314 1 +185 184 146 305 1 +61 244 315 243 1 +9 315 244 243 1 +348 279 301 189 1 +325 299 279 256 1 +45 323 169 275 1 +226 7 75 318 1 +309 168 79 318 1 +309 318 79 196 1 +128 309 196 318 1 +128 309 318 314 1 +279 318 309 314 1 +279 168 309 318 1 +89 190 313 322 2 +313 190 295 322 2 +77 230 179 333 0 +88 322 246 190 2 +124 350 267 319 3 +124 214 350 319 3 +54 55 223 197 0 +67 226 68 141 2 +246 351 268 213 2 +213 322 88 126 2 +89 88 322 170 2 +89 88 190 322 2 +326 300 270 260 3 +211 72 144 125 2 +37 253 259 36 1 +234 214 109 319 3 +208 23 134 260 3 +109 110 205 319 3 +37 339 116 115 1 +347 306 286 254 1 +213 351 268 126 2 +163 167 260 202 3 +114 187 180 149 0 +285 267 300 319 3 +44 134 24 323 1 +323 134 24 296 1 +296 24 323 236 1 +323 24 2 236 1 +44 24 2 323 1 +296 169 236 323 1 +12 17 324 177 0 +12 324 158 177 0 +177 324 158 31 0 +324 15 158 31 0 +177 15 324 31 0 +15 60 177 324 0 +60 177 324 59 0 +59 177 324 49 0 +324 177 191 49 0 +324 191 50 49 0 +59 324 50 49 0 +59 158 50 324 0 +50 158 119 324 0 +233 166 65 275 1 +131 4 332 42 3 +301 339 282 255 1 +99 346 138 222 2 +281 255 339 338 1 +17 324 18 154 1 +17 158 324 154 1 +12 17 158 324 0 +60 324 158 59 0 +15 60 324 158 0 +133 351 70 152 2 +203 111 302 326 3 +302 111 224 326 3 +282 356 314 128 1 +356 67 195 128 0 +282 67 314 356 1 +242 65 166 275 1 +166 233 321 275 1 +233 258 321 275 1 +328 18 324 154 1 +217 18 328 154 1 +122 217 328 154 1 +183 154 122 328 1 +183 328 122 306 1 +320 112 111 149 3 +266 305 354 353 1 +323 296 169 275 1 +217 18 19 328 1 +328 18 19 181 1 +328 18 181 324 1 +314 356 195 128 1 +356 120 194 282 1 +128 356 194 282 1 +128 120 194 356 0 +329 131 43 176 3 +338 255 339 253 1 +331 44 2 47 3 +24 331 2 47 3 +208 331 24 47 3 +47 331 330 208 3 +208 134 24 331 3 +134 44 24 331 3 +24 44 2 331 3 +43 44 134 331 3 +135 351 268 246 2 +99 138 137 222 2 +346 123 269 222 2 +267 285 300 332 3 +285 37 300 332 3 +38 285 152 332 3 +152 38 332 39 3 +332 38 156 39 3 +138 345 35 222 2 +69 152 332 39 3 +69 4 39 332 3 +296 281 134 336 1 +322 135 268 246 2 +179 30 77 333 0 +312 12 29 333 2 +311 343 95 333 2 +95 30 94 333 0 +306 347 183 132 1 +69 335 152 39 2 +4 335 69 39 2 +4 66 335 39 2 +4 66 133 335 2 +4 133 69 335 2 +69 133 152 335 2 +298 38 152 335 2 +337 129 274 277 1 +228 129 166 337 1 +205 140 234 319 3 +319 300 326 260 3 +165 138 99 278 3 +156 336 338 134 1 +156 332 329 338 3 +332 267 329 338 3 +332 38 338 156 3 +155 339 116 38 1 +276 200 287 272 1 +115 37 339 259 1 +117 172 259 250 1 +226 263 221 141 2 +253 259 339 37 1 +115 37 259 36 1 +255 259 339 253 1 +340 227 136 144 2 +297 139 223 197 1 +55 297 223 197 1 +269 312 136 340 2 +311 312 269 340 2 +347 254 308 132 1 +290 308 316 132 1 +253 336 286 202 1 +14 223 139 197 0 +340 76 227 144 2 +340 76 144 249 2 +179 76 227 340 2 +54 55 235 273 1 +344 164 170 123 0 +311 269 342 340 2 +340 144 269 342 2 +342 144 269 341 2 +342 313 341 269 2 +313 123 269 342 2 +90 123 313 342 2 +90 313 341 342 2 +344 164 100 280 0 +165 344 100 280 0 +165 99 100 344 0 +165 98 99 344 0 +355 316 262 353 1 +347 183 163 306 1 +46 45 275 294 1 +240 232 46 294 0 +232 237 46 294 0 +123 344 346 247 2 +98 346 138 99 2 +212 90 123 344 0 +213 344 90 212 0 +159 213 212 344 0 +165 98 344 159 0 +280 164 170 344 0 +151 311 33 345 2 +209 64 65 275 1 +275 323 258 294 1 +282 339 155 39 1 +39 339 155 38 1 +65 169 209 275 1 +132 119 316 204 1 +132 158 119 204 1 +168 139 190 197 0 +328 306 132 353 1 +354 305 262 353 1 +347 259 250 308 1 +301 259 255 352 1 +35 259 172 250 1 +163 259 36 35 1 +154 217 18 173 3 +131 350 329 332 3 +131 332 152 350 3 +332 285 152 350 3 +350 285 152 162 3 +350 70 162 152 3 +131 70 350 152 3 +131 70 106 350 3 +350 70 106 162 3 +107 162 350 106 3 +107 350 131 106 3 +107 214 350 162 3 +214 124 350 162 3 +350 124 285 162 3 +350 124 267 285 3 +332 267 285 350 3 +263 75 226 221 2 +113 276 62 305 1 +206 118 325 304 1 +357 51 50 248 0 +357 185 51 248 0 +347 33 183 132 1 +312 230 340 333 2 +351 268 335 141 2 +133 92 70 351 2 +96 97 159 247 0 +96 159 94 247 0 +266 307 276 353 1 +307 266 306 353 1 +307 261 207 353 1 +110 109 171 319 3 +163 347 259 35 1 +301 282 339 155 1 +352 301 259 348 1 +115 259 172 36 1 +117 269 295 222 2 +352 259 255 286 1 +286 259 255 253 1 +264 288 316 354 1 +262 288 185 354 1 +316 288 262 354 1 +305 184 266 354 1 +319 267 300 260 3 +159 97 98 247 0 +49 357 54 14 0 +233 337 166 321 1 +233 266 276 113 1 +64 233 63 113 1 +192 235 143 357 0 +96 94 160 247 0 +276 147 200 272 1 +269 311 212 247 2 +3 107 108 303 0 +351 245 219 284 2 +87 93 8 284 2 +48 220 107 303 3 +213 351 93 284 2 +213 245 351 284 2 +118 185 206 357 0 +206 185 244 357 0 +185 51 244 357 0 +51 50 244 357 0 +49 244 50 357 0 +49 14 244 357 0 +87 213 93 284 2 +357 206 265 244 0 +118 357 206 192 0 +93 351 219 284 2 +357 58 6 192 0 +357 57 58 192 0 +357 56 57 192 0 +357 55 56 192 0 +192 55 235 357 0 +Corners +16 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +Edges +124 +4 42 8 +105 104 26 +38 39 6 +41 13 7 +13 104 26 +18 19 1 +109 108 28 +106 5 27 +5 70 16 +109 110 28 +79 6 19 +23 24 2 +9 53 11 +9 26 3 +2 44 8 +2 47 10 +47 48 10 +89 90 22 +59 60 13 +32 33 6 +111 110 28 +56 55 12 +72 71 17 +16 95 24 +16 91 22 +19 10 1 +10 25 3 +107 3 27 +3 108 28 +44 43 8 +43 42 8 +69 70 16 +4 66 15 +11 28 4 +2 45 9 +37 36 6 +4 39 6 +23 22 2 +28 27 4 +30 31 5 +35 34 6 +48 3 10 +80 81 20 +76 77 18 +90 91 22 +69 4 16 +61 9 14 +54 14 12 +49 14 11 +97 98 25 +5 92 23 +5 103 25 +8 87 22 +96 13 25 +58 57 12 +65 64 14 +7 78 19 +107 106 27 +102 103 25 +84 85 21 +6 82 21 +76 15 18 +15 31 5 +10 27 4 +25 26 3 +98 99 25 +60 15 13 +95 94 24 +75 74 17 +68 7 15 +1 46 9 +84 83 21 +77 16 18 +57 56 12 +45 46 9 +79 78 19 +93 8 23 +13 94 24 +97 96 25 +18 17 1 +34 33 6 +93 92 23 +50 51 11 +86 1 21 +65 1 14 +105 11 26 +11 112 28 +40 41 7 +55 54 12 +10 20 2 +88 87 22 +7 75 17 +85 86 21 +66 67 15 +38 37 6 +29 12 5 +58 6 12 +12 32 6 +21 22 2 +73 74 17 +83 82 21 +111 112 28 +71 15 17 +67 68 15 +24 2 2 +59 14 13 +36 35 6 +81 8 20 +99 100 25 +88 89 22 +29 30 5 +12 40 7 +17 12 1 +61 62 14 +63 62 14 +50 49 11 +7 80 20 +53 52 11 +73 72 17 +51 52 11 +101 100 25 +101 102 25 +63 64 14 +20 21 2 +End diff --git a/Stream_support/test/Stream_support/test_MEDIT.cpp b/Stream_support/test/Stream_support/test_MEDIT.cpp index aebdc7763e23..b7468d4c5e89 100644 --- a/Stream_support/test/Stream_support/test_MEDIT.cpp +++ b/Stream_support/test/Stream_support/test_MEDIT.cpp @@ -8,27 +8,38 @@ typedef CGAL::Simple_cartesian Kernel; typedef Kernel::Point_3 Point_3; + int main() { - const std::string filename = CGAL::data_file_path("meshes/elephant.mesh"); + const std::string filename = "./data/polyhedral_complex.mesh"; std::ifstream input(filename); std::vector points; - std::vector subdomains; std::vector> cells; + std::vector subdomains; + std::vector> corners; bool verbose = false; - bool success = CGAL::IO::read_MEDIT(input, points, cells, CGAL::parameters::subdomains(std::ref(subdomains)).verbose(verbose)); + bool success = CGAL::IO::read_MEDIT(input, points, cells, CGAL::parameters::subdomains(std::ref(subdomains)).corners_with_indices(std::ref(corners)).verbose(verbose)); assert(success); + for(auto c : corners) + std ::cout << c.v << std::endl; + std::ostringstream output; output.precision(17); - CGAL::IO::write_MEDIT(output, points, cells, CGAL::parameters::subdomains(std::cref(subdomains))); + CGAL::IO::write_MEDIT(output, points, cells, CGAL::parameters::subdomains(std::cref(subdomains)).corners_with_indices(std::cref(corners))); std::istringstream input2(output.str()); std::vector points2; std::vector> cells2; std::vector subdomains2; - success = CGAL::IO::read_MEDIT(input2, points2, cells2, CGAL::parameters::subdomains(std::ref(subdomains2)).verbose(verbose)); + std::vector> corners2; + success = CGAL::IO::read_MEDIT(input2, points2, cells2, CGAL::parameters::subdomains(std::ref(subdomains2)).corners_with_indices(std::ref(corners2)).verbose(verbose)); + + for(auto c : corners2) + std ::cout << c.v << std::endl; + assert(points == points2); assert(cells == cells2); assert(subdomains == subdomains2); + assert(corners == corners2); assert(success); return 0; } From f24f1e0bef1c67dd791107af3cbac1712c2af499 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 17 Sep 2026 13:18:59 +0100 Subject: [PATCH 14/72] Switch to CornerWithIndexRange instead of std::vector --- Stream_support/include/CGAL/IO/MEDIT.h | 7 ++++--- Stream_support/test/Stream_support/test_MEDIT.cpp | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 2dc71caf78c5..7c7a61b41d1a 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -63,7 +63,7 @@ template // either Corner_with_index or a tuple/pair/array + class CornerWithIndexRange> // either Corner_with_index or a tuple/pair/array bool read_MEDIT(std::istream& is, PointRange& points, TetrahedronRange& tetrahedra, @@ -71,7 +71,7 @@ bool read_MEDIT(std::istream& is, std::vector& facets_with_indices, bool read_facets_with_indices, std::vector& edges_with_indices, - std::vector& corners_with_indices, + CornerWithIndexRange& corners_with_indices, bool verbose, bool& is_CGAL_mesh) { @@ -247,7 +247,8 @@ bool read_MEDIT(std::istream& is, std::cerr << "Issue while reading corners" << std::endl; return false; } - corners_with_indices.push_back({offset + n}); + // typename CornerWithIndex::value_type cwi = {offset + n}; + corners_with_indices.push_back( {offset + n} ); } } diff --git a/Stream_support/test/Stream_support/test_MEDIT.cpp b/Stream_support/test/Stream_support/test_MEDIT.cpp index b7468d4c5e89..b3160784ee11 100644 --- a/Stream_support/test/Stream_support/test_MEDIT.cpp +++ b/Stream_support/test/Stream_support/test_MEDIT.cpp @@ -4,6 +4,7 @@ #include #include #include +#include typedef CGAL::Simple_cartesian Kernel; typedef Kernel::Point_3 Point_3; @@ -15,7 +16,7 @@ int main() { std::vector points; std::vector> cells; std::vector subdomains; - std::vector> corners; + std::deque> corners; bool verbose = false; bool success = CGAL::IO::read_MEDIT(input, points, cells, CGAL::parameters::subdomains(std::ref(subdomains)).corners_with_indices(std::ref(corners)).verbose(verbose)); assert(success); @@ -30,7 +31,7 @@ int main() { std::vector points2; std::vector> cells2; std::vector subdomains2; - std::vector> corners2; + std::deque> corners2; success = CGAL::IO::read_MEDIT(input2, points2, cells2, CGAL::parameters::subdomains(std::ref(subdomains2)).corners_with_indices(std::ref(corners2)).verbose(verbose)); for(auto c : corners2) From 426107e8cb4906314f6e1c2f04d19294e6d3d055 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 17 Sep 2026 14:07:42 +0100 Subject: [PATCH 15/72] Add Edges --- Stream_support/include/CGAL/IO/MEDIT.h | 19 +++++++++++++++---- .../test/Stream_support/test_MEDIT.cpp | 12 ++++++------ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 7c7a61b41d1a..252389902e53 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -62,7 +62,7 @@ struct Corner_with_index template // either Corner_with_index or a tuple/pair/array bool read_MEDIT(std::istream& is, PointRange& points, @@ -70,7 +70,7 @@ bool read_MEDIT(std::istream& is, std::vector& subdomains, std::vector& facets_with_indices, bool read_facets_with_indices, - std::vector& edges_with_indices, + EdgeWithIndexRange& edges_with_indices, CornerWithIndexRange& corners_with_indices, bool verbose, bool& is_CGAL_mesh) @@ -248,7 +248,7 @@ bool read_MEDIT(std::istream& is, return false; } // typename CornerWithIndex::value_type cwi = {offset + n}; - corners_with_indices.push_back( {offset + n} ); + corners_with_indices.push_back( {offset + n - 1 } ); } } @@ -457,6 +457,7 @@ bool write_MEDIT(std::ostream& os, // subdomains std::vector default_subdomains; std::vector> default_corners; + std::vector> default_edges; using Subdomains = typename internal_np::Lookup_named_param_def>::reference; Subdomains subdomains = choose_parameter(get_parameter_reference(np, internal_np::subdomains), default_subdomains); @@ -464,6 +465,10 @@ bool write_MEDIT(std::ostream& os, using Corners_with_indices = typename internal_np::Lookup_named_param_def>>::reference; Corners_with_indices corners = choose_parameter(get_parameter_reference(np, internal_np::corners_with_indices), default_corners); + using Edges_with_indices = typename internal_np::Lookup_named_param_def>>::reference; + Edges_with_indices edges = choose_parameter(get_parameter_reference(np, internal_np::edges_with_indices), default_edges); + + if constexpr (is_default_parameter::value) default_subdomains.resize(tetrahedra.size(), 1); @@ -482,7 +487,13 @@ bool write_MEDIT(std::ostream& os, if(!corners.empty()){ os << "Corners\n" << corners.size() << "\n"; for(const auto& c : corners) - os << c.v << "\n"; + os << c.v + 1 << "\n"; + } + + if(!corners.empty()){ + os << "Edges\n" << edges.size() << "\n"; + for(const auto& e : edges) + os << std::get<0>(e) +1 << " " << std::get<1>(e) + 1 << " " << std::get<2>(e) << "\n"; } os <<"End\n"; return true; diff --git a/Stream_support/test/Stream_support/test_MEDIT.cpp b/Stream_support/test/Stream_support/test_MEDIT.cpp index b3160784ee11..fceca59e8f19 100644 --- a/Stream_support/test/Stream_support/test_MEDIT.cpp +++ b/Stream_support/test/Stream_support/test_MEDIT.cpp @@ -16,9 +16,10 @@ int main() { std::vector points; std::vector> cells; std::vector subdomains; + std::vector> edges; std::deque> corners; bool verbose = false; - bool success = CGAL::IO::read_MEDIT(input, points, cells, CGAL::parameters::subdomains(std::ref(subdomains)).corners_with_indices(std::ref(corners)).verbose(verbose)); + bool success = CGAL::IO::read_MEDIT(input, points, cells, CGAL::parameters::subdomains(std::ref(subdomains)).edges_with_indices(std::ref(edges)).corners_with_indices(std::ref(corners)).verbose(verbose)); assert(success); for(auto c : corners) @@ -26,21 +27,20 @@ int main() { std::ostringstream output; output.precision(17); - CGAL::IO::write_MEDIT(output, points, cells, CGAL::parameters::subdomains(std::cref(subdomains)).corners_with_indices(std::cref(corners))); + CGAL::IO::write_MEDIT(output, points, cells, CGAL::parameters::subdomains(std::cref(subdomains)).edges_with_indices(std::cref(edges)).corners_with_indices(std::cref(corners))); std::istringstream input2(output.str()); std::vector points2; std::vector> cells2; std::vector subdomains2; + std::vector> edges2; std::deque> corners2; - success = CGAL::IO::read_MEDIT(input2, points2, cells2, CGAL::parameters::subdomains(std::ref(subdomains2)).corners_with_indices(std::ref(corners2)).verbose(verbose)); - - for(auto c : corners2) - std ::cout << c.v << std::endl; + success = CGAL::IO::read_MEDIT(input2, points2, cells2, CGAL::parameters::subdomains(std::ref(subdomains2)).edges_with_indices(std::ref(edges2)).corners_with_indices(std::ref(corners2)).verbose(verbose)); assert(points == points2); assert(cells == cells2); assert(subdomains == subdomains2); assert(corners == corners2); + assert(edges == edges2); assert(success); return 0; } From ed79fa016f897f2cd8727602d582e9432f552f00 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 17 Sep 2026 14:11:17 +0100 Subject: [PATCH 16/72] Add Edges --- Stream_support/include/CGAL/IO/MEDIT.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 252389902e53..7f7eba707991 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -490,7 +490,7 @@ bool write_MEDIT(std::ostream& os, os << c.v + 1 << "\n"; } - if(!corners.empty()){ + if(!edges.empty()){ os << "Edges\n" << edges.size() << "\n"; for(const auto& e : edges) os << std::get<0>(e) +1 << " " << std::get<1>(e) + 1 << " " << std::get<2>(e) << "\n"; From b50903cc6886a8182e4bd44f008988add5e4a85e Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 17 Sep 2026 14:29:32 +0100 Subject: [PATCH 17/72] Add Facets --- Stream_support/include/CGAL/IO/MEDIT.h | 11 ++++++- .../test/Stream_support/test_MEDIT.cpp | 30 +++++++++++++------ 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 7f7eba707991..015069702c9e 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -458,6 +458,7 @@ bool write_MEDIT(std::ostream& os, std::vector default_subdomains; std::vector> default_corners; std::vector> default_edges; + std::vector> default_facets; using Subdomains = typename internal_np::Lookup_named_param_def>::reference; Subdomains subdomains = choose_parameter(get_parameter_reference(np, internal_np::subdomains), default_subdomains); @@ -468,6 +469,8 @@ bool write_MEDIT(std::ostream& os, using Edges_with_indices = typename internal_np::Lookup_named_param_def>>::reference; Edges_with_indices edges = choose_parameter(get_parameter_reference(np, internal_np::edges_with_indices), default_edges); + using Facets_with_indices = typename internal_np::Lookup_named_param_def>>::reference; + Facets_with_indices facets = choose_parameter(get_parameter_reference(np, internal_np::facets_with_indices), default_facets); if constexpr (is_default_parameter::value) default_subdomains.resize(tetrahedra.size(), 1); @@ -487,7 +490,7 @@ bool write_MEDIT(std::ostream& os, if(!corners.empty()){ os << "Corners\n" << corners.size() << "\n"; for(const auto& c : corners) - os << c.v + 1 << "\n"; + os << c + 1 << "\n"; } if(!edges.empty()){ @@ -495,6 +498,12 @@ bool write_MEDIT(std::ostream& os, for(const auto& e : edges) os << std::get<0>(e) +1 << " " << std::get<1>(e) + 1 << " " << std::get<2>(e) << "\n"; } + + if(!facets.empty()){ + os << "Triangles\n" << facets.size() << "\n"; + for(const auto& f : facets) + os << std::get<0>(f) +1 << " " << std::get<1>(f) + 1 << " " << std::get<2>(f) + 1 << " " << std::get<3>(f) << "\n"; + } os <<"End\n"; return true; } diff --git a/Stream_support/test/Stream_support/test_MEDIT.cpp b/Stream_support/test/Stream_support/test_MEDIT.cpp index fceca59e8f19..483387345622 100644 --- a/Stream_support/test/Stream_support/test_MEDIT.cpp +++ b/Stream_support/test/Stream_support/test_MEDIT.cpp @@ -5,11 +5,12 @@ #include #include #include +#include +#include typedef CGAL::Simple_cartesian Kernel; typedef Kernel::Point_3 Point_3; - int main() { const std::string filename = "./data/polyhedral_complex.mesh"; std::ifstream input(filename); @@ -17,30 +18,41 @@ int main() { std::vector> cells; std::vector subdomains; std::vector> edges; - std::deque> corners; + std::vector> facets; + std::deque corners; bool verbose = false; - bool success = CGAL::IO::read_MEDIT(input, points, cells, CGAL::parameters::subdomains(std::ref(subdomains)).edges_with_indices(std::ref(edges)).corners_with_indices(std::ref(corners)).verbose(verbose)); + bool success = CGAL::IO::read_MEDIT(input, points, cells, CGAL::parameters::subdomains(std::ref(subdomains)) + .facets_with_indices(std::ref(facets)) + .edges_with_indices(std::ref(edges)) + .corners_with_indices(std::ref(corners)) + .verbose(verbose)); assert(success); - for(auto c : corners) - std ::cout << c.v << std::endl; - std::ostringstream output; output.precision(17); - CGAL::IO::write_MEDIT(output, points, cells, CGAL::parameters::subdomains(std::cref(subdomains)).edges_with_indices(std::cref(edges)).corners_with_indices(std::cref(corners))); + CGAL::IO::write_MEDIT(output, points, cells, CGAL::parameters::subdomains(std::cref(subdomains)) + .facets_with_indices(std::cref(facets)) + .edges_with_indices(std::cref(edges)) + .corners_with_indices(std::cref(corners))); std::istringstream input2(output.str()); std::vector points2; std::vector> cells2; std::vector subdomains2; std::vector> edges2; - std::deque> corners2; - success = CGAL::IO::read_MEDIT(input2, points2, cells2, CGAL::parameters::subdomains(std::ref(subdomains2)).edges_with_indices(std::ref(edges2)).corners_with_indices(std::ref(corners2)).verbose(verbose)); + std::vector> facets2; + std::deque corners2; + success = CGAL::IO::read_MEDIT(input2, points2, cells2, CGAL::parameters::subdomains(std::ref(subdomains2)) + .facets_with_indices(std::ref(facets2)) + .edges_with_indices(std::ref(edges2)) + .corners_with_indices(std::ref(corners2)) + .verbose(verbose)); assert(points == points2); assert(cells == cells2); assert(subdomains == subdomains2); assert(corners == corners2); assert(edges == edges2); + assert(facets == facets2); assert(success); return 0; } From 60f666b9c73592934c5415644b15fb69f1cd7ba1 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 17 Sep 2026 14:33:19 +0100 Subject: [PATCH 18/72] Add Facets --- Stream_support/include/CGAL/IO/MEDIT.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 015069702c9e..53c6292c905c 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -61,14 +61,14 @@ struct Corner_with_index template // either Corner_with_index or a tuple/pair/array bool read_MEDIT(std::istream& is, PointRange& points, TetrahedronRange& tetrahedra, std::vector& subdomains, - std::vector& facets_with_indices, + FacetWithIndexRange& facets_with_indices, bool read_facets_with_indices, EdgeWithIndexRange& edges_with_indices, CornerWithIndexRange& corners_with_indices, @@ -479,7 +479,7 @@ bool write_MEDIT(std::ostream& os, os << points.size() << "\n"; for (const Point_3& p : points) os << p << " 0\n"; - os << "Triangles\n0\nTetrahedra\n"; + os << "Tetrahedra\n"; os << tetrahedra.size() << "\n"; for (std::size_t k=0; k Date: Thu, 17 Sep 2026 15:33:09 +0100 Subject: [PATCH 19/72] Stick to Corner_with_index as there are other formats than MEDIT. Make it work for .._with_index classes --- Stream_support/include/CGAL/IO/MEDIT.h | 50 +++++++++++++++++-- .../test/Stream_support/test_MEDIT.cpp | 4 +- 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 53c6292c905c..67ada4fd1498 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -51,19 +51,61 @@ template struct Corner_with_index { int v; + CornerIndex corner_index; bool operator==(const Corner_with_index& rhs) const { - return (v == rhs.v); + return (v == rhs.v) && (corner_index == rhs.corner_index); } }; +template +int get_zero(const T& t) +{ + return std::get<0>(t); +} + +template +int get_one(const T& t) +{ + return std::get<1>(t); +} + +template +int get_two(const T& t) +{ + return std::get<2>(t); +} + +template +int get_zero(const Corner_with_index& t) +{ + return t.v; +} + +template +int get_zero(const Edge_with_index& t) +{ + return t.v0; +} + +template +int get_one(const Edge_with_index& t) +{ + return t.v1; +} + +template +CurveIndex get_two(const Edge_with_index& t) +{ + return t.curve_index; +} template // either Corner_with_index or a tuple/pair/array + class CornerWithIndexRange> // either Corner_with_index or a tuple/pair/array bool read_MEDIT(std::istream& is, PointRange& points, TetrahedronRange& tetrahedra, @@ -490,13 +532,13 @@ bool write_MEDIT(std::ostream& os, if(!corners.empty()){ os << "Corners\n" << corners.size() << "\n"; for(const auto& c : corners) - os << c + 1 << "\n"; + os << internal::get_zero(c) + 1 << "\n"; } if(!edges.empty()){ os << "Edges\n" << edges.size() << "\n"; for(const auto& e : edges) - os << std::get<0>(e) +1 << " " << std::get<1>(e) + 1 << " " << std::get<2>(e) << "\n"; + os << internal::get_zero(e) +1 << " " << internal::get_one(e) + 1 << " " << internal::get_two(e) << "\n"; } if(!facets.empty()){ diff --git a/Stream_support/test/Stream_support/test_MEDIT.cpp b/Stream_support/test/Stream_support/test_MEDIT.cpp index 483387345622..820382195674 100644 --- a/Stream_support/test/Stream_support/test_MEDIT.cpp +++ b/Stream_support/test/Stream_support/test_MEDIT.cpp @@ -19,7 +19,7 @@ int main() { std::vector subdomains; std::vector> edges; std::vector> facets; - std::deque corners; + std::deque> corners; bool verbose = false; bool success = CGAL::IO::read_MEDIT(input, points, cells, CGAL::parameters::subdomains(std::ref(subdomains)) .facets_with_indices(std::ref(facets)) @@ -40,7 +40,7 @@ int main() { std::vector subdomains2; std::vector> edges2; std::vector> facets2; - std::deque corners2; + std::deque> corners2; success = CGAL::IO::read_MEDIT(input2, points2, cells2, CGAL::parameters::subdomains(std::ref(subdomains2)) .facets_with_indices(std::ref(facets2)) .edges_with_indices(std::ref(edges2)) From 02861f4c14ec8f9d130ccd6e33e1e0f8276266c5 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 17 Sep 2026 20:02:00 +0100 Subject: [PATCH 20/72] Document named parameters of the write function --- Stream_support/include/CGAL/IO/MEDIT.h | 41 ++++++++++++++++++++------ 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 67ada4fd1498..60694d1f5a8a 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -366,23 +366,23 @@ bool read_MEDIT(std::istream& is, * \cgalParamNEnd * * \cgalParamNBegin{facets_with_indices} - * \cgalParamDescription{a non-const reference wrapper to a container of quadruple of integers that will be filled by this function. - * Each element corresponds to a facet with vertices corresponding to the three first integers, and the last integer being the surface patch index of the facet.} - * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` able to store quadruple of `int`.} + * \cgalParamDescription{a non-const reference wrapper to a container of quadruples of integers that will be filled by this function. + * Each element represents a facet with vertices corresponding to the three first integers, and the last integer being the surface patch index of the facet.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of four integers.} * \cgalParamDefault{facets are ignored} * \cgalParamNEnd * * \cgalParamNBegin{edges_with_indices} - * \cgalParamDescription{a non-const reference wrapper to a container of triple of integers that will be filled by this function. - * Each element corresponds to an edge with vertices corresponding to the two first integers, and the last integer being the curve index of the edge.} - * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` able to store triple of `int`.} + * \cgalParamDescription{a non-const reference wrapper to a container of triples of integers that will be filled by this function. + * Each element represents an edge with vertices corresponding to the two first integers, and the last integer being the curve index of the edge.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of three integers.} * \cgalParamDefault{edges are ignored} * \cgalParamNEnd * * \cgalParamNBegin{corners_with_indices} * \cgalParamDescription{a non-const reference wrapper to a container of pair of integers that will be filled by this function. - * Each element corresponds to a corner at the vertex corresponding to the first integer, the last one being the corner index.} - * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` able to store pair of `int`.} + * Each element represents a corner at the vertex corresponding to the first integer, and the last integer being the corner index.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of two integers.} * \cgalParamDefault{corners are ignored} * \cgalParamNEnd * @@ -466,9 +466,32 @@ bool read_MEDIT(std::istream& is, * \cgalParamNBegin{subdomains} * \cgalParamDescription{a reference wrapper to a container of integers of the same size as `tetrahedra`. * Each element in the container indicates the subdomain index of the corresponding tetrahedron at the same position.} - * \cgalParamType{a `std::reference_wrapper` to a model of the concept `RandomAccessContainer` of integer.} + * \cgalParamType{a `std::reference_wrapper` to a model of the concept `SequenceContainer` of integer.} * \cgalParamDefault{all tetrahedra will have the subdomain id `1`.} * \cgalParamNEnd + * + * \cgalParamNBegin{facets_with_indices} + * \cgalParamDescription{a const reference wrapper to a container of quadruples of integers that will be written by this function. + * Each element corresponds to a facet with vertices corresponding to the three first integers, and the last integer being the surface patch index of the facet.} + * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the quadruples can be accessed with `std::get()} + * \cgalParamDefault{facets are ignored} + * \cgalParamNEnd + * + * \cgalParamNBegin{edges_with_indices} + * \cgalParamDescription{a const reference wrapper to a container of triples of integers that will be written by this function. + * Each element corresponds to an edge with vertices corresponding to the two first integers, and the last integer being the curve index of the edge.} + * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the triples can be accessed with `std::get()`} + * \cgalParamDefault{edges are ignored} + * \cgalParamNEnd + * + * \cgalParamNBegin{corners_with_indices} + * \cgalParamDescription{a const reference wrapper to a container of pair of integers that will be written by this function. + * Each element corresponds to a corner at the vertex corresponding to the first integer, the second integer being the corner index. + * As \medit has no notion of corner indices it is not written.} + * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the pairs can be accessed with `std::get()} + * \cgalParamDefault{corners are ignored} + * \cgalParamNEnd + * * \cgalNamedParamsEnd * * \returns `true` if the writing was successful, `false` otherwise. From 13eadc901bb90a2b85409a5ff1ef4793a6532ae2 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 17 Sep 2026 20:07:49 +0100 Subject: [PATCH 21/72] typo --- Stream_support/include/CGAL/IO/MEDIT.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 60694d1f5a8a..3c0ec7e50659 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -473,7 +473,7 @@ bool read_MEDIT(std::istream& is, * \cgalParamNBegin{facets_with_indices} * \cgalParamDescription{a const reference wrapper to a container of quadruples of integers that will be written by this function. * Each element corresponds to a facet with vertices corresponding to the three first integers, and the last integer being the surface patch index of the facet.} - * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the quadruples can be accessed with `std::get()} + * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the quadruples can be accessed with `std::get()`} * \cgalParamDefault{facets are ignored} * \cgalParamNEnd * @@ -488,7 +488,7 @@ bool read_MEDIT(std::istream& is, * \cgalParamDescription{a const reference wrapper to a container of pair of integers that will be written by this function. * Each element corresponds to a corner at the vertex corresponding to the first integer, the second integer being the corner index. * As \medit has no notion of corner indices it is not written.} - * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the pairs can be accessed with `std::get()} + * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the pairs can be accessed with `std::get()`} * \cgalParamDefault{corners are ignored} * \cgalParamNEnd * From dd5d09910a73a8602c46e2779852972edb105808 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 17 Sep 2026 20:09:30 +0100 Subject: [PATCH 22/72] typo --- Stream_support/include/CGAL/IO/MEDIT.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 3c0ec7e50659..8474fc585be8 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -487,7 +487,7 @@ bool read_MEDIT(std::istream& is, * \cgalParamNBegin{corners_with_indices} * \cgalParamDescription{a const reference wrapper to a container of pair of integers that will be written by this function. * Each element corresponds to a corner at the vertex corresponding to the first integer, the second integer being the corner index. - * As \medit has no notion of corner indices it is not written.} + * As Medit has no notion of corner indices it is not written.} * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the pairs can be accessed with `std::get()`} * \cgalParamDefault{corners are ignored} * \cgalParamNEnd From 59a5e4a093ac8566fc9022e0267973172c12d1b0 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 17 Sep 2026 20:35:36 +0100 Subject: [PATCH 23/72] Link to the section of Medit and move the link to the bibtex entry there --- .../include/CGAL/IO/write_MEDIT.h | 7 +++---- SMDS_3/include/CGAL/IO/File_medit.h | 10 +++++----- .../File_formats/Supported_file_formats.txt | 3 ++- Stream_support/include/CGAL/IO/MEDIT.h | 8 ++------ 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/Constrained_triangulation_3/include/CGAL/IO/write_MEDIT.h b/Constrained_triangulation_3/include/CGAL/IO/write_MEDIT.h index b1dd50e84838..94f48d27003b 100644 --- a/Constrained_triangulation_3/include/CGAL/IO/write_MEDIT.h +++ b/Constrained_triangulation_3/include/CGAL/IO/write_MEDIT.h @@ -32,10 +32,9 @@ namespace IO { /*! * @ingroup PkgCDT3IOFunctions - * @brief outputs a conforming constrained Delaunay triangulation to - * the MEDIT (`.mesh`) file format. - * See \cgalCite{frey:inria-00069921} for a comprehensive description of this - * file format. + * @brief outputs a conforming constrained Delaunay triangulation + * using the \ref IOStreamMedit (`.mesh`). + * * @param os the output stream * @param ccdt the conforming constrained Delaunay triangulation to be written * \param np an optional sequence of \ref bgl_namedparameters "Named Parameters" among the ones listed below diff --git a/SMDS_3/include/CGAL/IO/File_medit.h b/SMDS_3/include/CGAL/IO/File_medit.h index dc53db7efea5..a6900fdec871 100644 --- a/SMDS_3/include/CGAL/IO/File_medit.h +++ b/SMDS_3/include/CGAL/IO/File_medit.h @@ -928,8 +928,8 @@ output_to_medit(std::ostream& os, /** * @ingroup PkgSMDS3IOFunctions - * @brief outputs a mesh complex to the medit (`.mesh`) file format. - * See \cgalCite{frey:inria-00069921} for a comprehensive description of this file format. + * @brief outputs a mesh complex to the using the \ref IOStreamMedit (`.mesh`). + * * @tparam T3 can be instantiated with any 3D triangulation of \cgal provided that its * vertex and cell base class are models of the concepts `SimplicialMeshVertexBase_3` * and `SimplicialMeshCellBase_3`, respectively. @@ -1075,9 +1075,9 @@ void write_MEDIT(std::ostream& os, /** * @ingroup PkgSMDS3IOFunctions - * @brief reads a mesh complex written in 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 + * @brief reads a mesh complex written in the \ref IOStreamMedit (`.mesh`). + +* * @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" diff --git a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt index aa942e9a7946..1586bada337e 100644 --- a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt +++ b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt @@ -543,12 +543,13 @@ A precise specification of the format is available \section IOStreamMedit Medit File Format -The Medit format, using file extension `.mesh`, is a format used by the Medit software. +The Medit format, using file extension `.mesh`, is a format used by the Medit software \cgalCite{frey:inria-00069921}. In \cgal, it is used to represent 3D meshes. A precise specification of the format is available in this report, in the appendices (Section 7.2.1, Page 36). + The following \cgal data structures can be exported into the `.mesh` file format: - `CGAL::Mesh_complex_3_in_triangulation_3`, using the function diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 8474fc585be8..9ad5a8e05c74 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -340,9 +340,8 @@ bool read_MEDIT(std::istream& is, /*! * \ingroup PkgStreamSupportIoFuncsMEDIT * - * \brief reads the content of `is` into `points` and `tetrahedra`. + * \brief reads the content of `is` into `points` and `tetrahedra` using the \ref IOStreamMedit * - * See \cgalCite{frey:inria-00069921} for a comprehensive description of the medit (`.mesh`) file format. * * \attention The tetrahedron soup is not cleared, and the data from the stream are appended. * @@ -445,10 +444,7 @@ bool read_MEDIT(std::istream& is, /*! * \ingroup PkgStreamSupportIoFuncsMEDIT * - * \brief writes the `points` and `tetrahedra`. - * - * See \cgalCite{frey:inria-00069921} for a comprehensive description of the medit (`.mesh`) file format. - * + * \brief writes the `points` and `tetrahedra` using the \ref IOStreamMedit * * \tparam PointRange a model of the concept `ConstRange` whose value type is the point type * \tparam TetrahedronRange a model of the concept `ConstRange` From 9bd16f405a050a50940ada4e7bb0ebd7f76379e5 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 17 Sep 2026 20:38:31 +0100 Subject: [PATCH 24/72] whitespace --- SMDS_3/include/CGAL/IO/File_medit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SMDS_3/include/CGAL/IO/File_medit.h b/SMDS_3/include/CGAL/IO/File_medit.h index a6900fdec871..41286800059b 100644 --- a/SMDS_3/include/CGAL/IO/File_medit.h +++ b/SMDS_3/include/CGAL/IO/File_medit.h @@ -1111,7 +1111,7 @@ void write_MEDIT(std::ostream& os, * triangulation cells from `in`, and builds a valid `T3` from it. * * Note that a valid 3D triangulation of \cgal must have a valid - * data structure (see `TriangulationDataStructure_3 `), + * data structure (see `TriangulationDataStructure_3`), * positively oriented cells, * and cover the geometric convex hull of all points in `t3`. * From 3941e7b3a228fba5f15cf96525b007e65fd11953 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 21 Sep 2026 17:25:58 +0100 Subject: [PATCH 25/72] Fix wording for parameters --- Stream_support/include/CGAL/IO/MEDIT.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 9ad5a8e05c74..ab0378f3fd10 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -358,28 +358,28 @@ bool read_MEDIT(std::istream& is, * \cgalNamedParamsBegin * * \cgalParamNBegin{subdomains} - * \cgalParamDescription{a non-const reference wrapper to a container of integers that will be filled by this function. + * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. * Each element in the container indicates the subdomain index of the corresponding tetrahedron at the same position.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` able to store `int`.} * \cgalParamDefault{subdomains are ignored} * \cgalParamNEnd * * \cgalParamNBegin{facets_with_indices} - * \cgalParamDescription{a non-const reference wrapper to a container of quadruples of integers that will be filled by this function. + * \cgalParamDescription{a non-const reference wrapper of a container of quadruples of integers that will be filled by this function. * Each element represents a facet with vertices corresponding to the three first integers, and the last integer being the surface patch index of the facet.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of four integers.} * \cgalParamDefault{facets are ignored} * \cgalParamNEnd * * \cgalParamNBegin{edges_with_indices} - * \cgalParamDescription{a non-const reference wrapper to a container of triples of integers that will be filled by this function. + * \cgalParamDescription{a non-const reference wrapper of a container of triples of integers that will be filled by this function. * Each element represents an edge with vertices corresponding to the two first integers, and the last integer being the curve index of the edge.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of three integers.} * \cgalParamDefault{edges are ignored} * \cgalParamNEnd * * \cgalParamNBegin{corners_with_indices} - * \cgalParamDescription{a non-const reference wrapper to a container of pair of integers that will be filled by this function. + * \cgalParamDescription{a non-const reference wrapper of a container of pair of integers that will be filled by this function. * Each element represents a corner at the vertex corresponding to the first integer, and the last integer being the corner index.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of two integers.} * \cgalParamDefault{corners are ignored} @@ -460,32 +460,32 @@ bool read_MEDIT(std::istream& is, * * \cgalNamedParamsBegin * \cgalParamNBegin{subdomains} - * \cgalParamDescription{a reference wrapper to a container of integers of the same size as `tetrahedra`. + * \cgalParamDescription{a const reference wrapper of a container of integers of the same size as `tetrahedra`. * Each element in the container indicates the subdomain index of the corresponding tetrahedron at the same position.} * \cgalParamType{a `std::reference_wrapper` to a model of the concept `SequenceContainer` of integer.} * \cgalParamDefault{all tetrahedra will have the subdomain id `1`.} * \cgalParamNEnd * * \cgalParamNBegin{facets_with_indices} - * \cgalParamDescription{a const reference wrapper to a container of quadruples of integers that will be written by this function. + * \cgalParamDescription{a const reference wrapper of a container of quadruples of integers that will be written by this function. * Each element corresponds to a facet with vertices corresponding to the three first integers, and the last integer being the surface patch index of the facet.} * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the quadruples can be accessed with `std::get()`} - * \cgalParamDefault{facets are ignored} + * \cgalParamDefault{facets are not written} * \cgalParamNEnd * * \cgalParamNBegin{edges_with_indices} - * \cgalParamDescription{a const reference wrapper to a container of triples of integers that will be written by this function. + * \cgalParamDescription{a const reference wrapper of a container of triples of integers that will be written by this function. * Each element corresponds to an edge with vertices corresponding to the two first integers, and the last integer being the curve index of the edge.} * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the triples can be accessed with `std::get()`} - * \cgalParamDefault{edges are ignored} + * \cgalParamDefault{edges are not written} * \cgalParamNEnd * * \cgalParamNBegin{corners_with_indices} - * \cgalParamDescription{a const reference wrapper to a container of pair of integers that will be written by this function. + * \cgalParamDescription{a const reference wrapper of a container of pair of integers that will be written by this function. * Each element corresponds to a corner at the vertex corresponding to the first integer, the second integer being the corner index. * As Medit has no notion of corner indices it is not written.} * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the pairs can be accessed with `std::get()`} - * \cgalParamDefault{corners are ignored} + * \cgalParamDefault{corners are not written} * \cgalParamNEnd * * \cgalNamedParamsEnd From 2d653c40678c94d75d0323a6ce70cf8e7551b957 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 22 Sep 2026 09:00:50 +0100 Subject: [PATCH 26/72] Deal with default property maps --- Stream_support/include/CGAL/IO/MEDIT.h | 49 +++++++++++++++++++++----- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index ab0378f3fd10..3cfb4c0a5fdf 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -113,7 +114,9 @@ bool read_MEDIT(std::istream& is, FacetWithIndexRange& facets_with_indices, bool read_facets_with_indices, EdgeWithIndexRange& edges_with_indices, + bool read_edges_with_indices, CornerWithIndexRange& corners_with_indices, + bool read_corners_with_indices, bool verbose, bool& is_CGAL_mesh) { @@ -189,7 +192,7 @@ bool read_MEDIT(std::istream& is, { if(read_facets_with_indices){ is >> nf; - facets_with_indices.reserve(nf); + CGAL::internal::reserve(facets_with_indices, nf); if(verbose) std::cerr << "Reading "<< nf << " triangles" << std::endl; @@ -276,9 +279,15 @@ bool read_MEDIT(std::istream& is, if(line.find("Corners") != std::string::npos) { - is >> ncorners; + if(read_corners_with_indices){ + is >> ncorners; + CGAL::internal::reserve(corners_with_indices, ncorners); + + if(verbose) + std::cerr << "Reading "<< ncorners << " corners" << std::endl; + if(verbose && ncorners == 0) - std::cerr << "Warning: Corners section is ignored" << std::endl; + std::cerr << "Warning: Corners section is empty" << std::endl; for(int i = 0; i < ncorners; ++i) { @@ -292,13 +301,25 @@ bool read_MEDIT(std::istream& is, // typename CornerWithIndex::value_type cwi = {offset + n}; corners_with_indices.push_back( {offset + n - 1 } ); } + }else{ + is >> ncorners; + std::string buffer; + for(int i=0; i> nedges; + if(read_edges_with_indices){ + is >> nedges; + CGAL::internal::reserve(edges_with_indices, nedges); + + if(verbose) + std::cerr << "Reading "<< nedges << " edges" << std::endl; + if(verbose && nedges == 0) - std::cerr << "Warning: Edges section is ignored" << std::endl; + std::cerr << "Warning: Edges section is empty" << std::endl; for(int i = 0; i < nedges; ++i) { @@ -312,7 +333,13 @@ bool read_MEDIT(std::istream& is, edges_with_indices.push_back({offset + n[0] - 1, offset + n[1] - 1, curve_index}); CGAL_assertion(edges_with_indices.size() == static_cast(i + 1)); } + }else{ + is >> nedges; + std::string buffer; + for(int i=0; i>>::reference; Corners_with_indices corners_with_indices = choose_parameter(get_parameter_reference(np, internal_np::corners_with_indices), default_corners_with_indices); - constexpr bool read_facets_with_indices = false; + + constexpr bool is_facets_with_indices_map = !parameters::is_default_parameter::value; + + constexpr bool is_edges_with_indices_map = !parameters::is_default_parameter::value; + + constexpr bool is_corners_with_indices_map = !parameters::is_default_parameter::value; bool is_CGAL_mesh; return internal::read_MEDIT(is, points, tetrahedra, subdomains, - facets_with_indices, read_facets_with_indices, - edges_with_indices, corners_with_indices, + facets_with_indices, is_facets_with_indices_map, + edges_with_indices, is_facets_with_indices_map, + corners_with_indices, is_corners_with_indices_map, verbose, is_CGAL_mesh); } From 552e6557459d4b414c7e938aa604dbbd705f1cff Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 23 Sep 2026 11:03:13 +0100 Subject: [PATCH 27/72] Fix SMDS_3 and with that the CI --- SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h b/SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h index 2044704fefe5..83cbdf3ef192 100644 --- a/SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h +++ b/SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h @@ -722,8 +722,8 @@ bool build_triangulation_from_file(std::istream& is, bool ok = CGAL::IO::internal::read_MEDIT(is, points, finite_cells, subdomains, facet_indices, true, - edge_indices, - corner_indices, + edge_indices, true, + corner_indices, true, verbose, is_CGAL_mesh); From 1330190632eee1653e376be714e0a5bcd0ca1533 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 23 Sep 2026 11:45:51 +0100 Subject: [PATCH 28/72] Add to changelog --- Installation/CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index c11620892c39..12e10deb98dc 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -52,6 +52,10 @@ Release date: December 2026 handle cases when some identical faces are shared between the input meshes. This leads to a significant speed up in those cases. +### [Stream Support](https://doc.cgal.org/6.3/Manual/packages.html#PkgStreamSupport) + +- Added overloaded versions of the functions `CGAL::IO::read_MEDIT()` and `CGAL::IO::write_MEDIT()`, for indexed tetrahedron soups. + ### [Basic Viewer](https://doc.cgal.org/6.3/Manual/packages.html#PkgBasicViewer) - Added the possibility to color the faces by a value mapped to a color palette: the From 3265c16033823d3135aad9a6ba354934ea14b1a6 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 23 Sep 2026 15:14:21 +0200 Subject: [PATCH 29/72] Update Stream_support/include/CGAL/IO/MEDIT.h Co-authored-by: Sebastien Loriot --- Stream_support/include/CGAL/IO/MEDIT.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 3cfb4c0a5fdf..e8fb22dca457 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -566,8 +566,6 @@ bool write_MEDIT(std::ostream& os, using Facets_with_indices = typename internal_np::Lookup_named_param_def>>::reference; Facets_with_indices facets = choose_parameter(get_parameter_reference(np, internal_np::facets_with_indices), default_facets); - if constexpr (is_default_parameter::value) - default_subdomains.resize(tetrahedra.size(), 1); os << "MeshVersionFormatted 1\nDimension 3\nVertices\n"; os << points.size() << "\n"; From 17f6b7cab5b84fb54494d94fa8b750844feb057d Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 23 Sep 2026 15:14:43 +0200 Subject: [PATCH 30/72] Update Stream_support/include/CGAL/IO/MEDIT.h Co-authored-by: Sebastien Loriot --- Stream_support/include/CGAL/IO/MEDIT.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index e8fb22dca457..a622555c99e6 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -574,10 +574,16 @@ bool write_MEDIT(std::ostream& os, os << "Tetrahedra\n"; os << tetrahedra.size() << "\n"; for (std::size_t k=0; k::value) + os << 1 << "\n"; + else + os << subdomains[k] << "\n"; + } if(!corners.empty()){ os << "Corners\n" << corners.size() << "\n"; From fb5535a72970492128ee884a1cacac98be23dc2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 23 Sep 2026 15:48:30 +0200 Subject: [PATCH 31/72] tws --- Stream_support/include/CGAL/IO/MEDIT.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index a622555c99e6..5cd53f4dbe6a 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -579,10 +579,10 @@ bool write_MEDIT(std::ostream& os, << tetrahedra[k][1]+1 << " " << tetrahedra[k][2]+1 << " " << tetrahedra[k][3]+1 << " "; - if constexpr (is_default_parameter::value) + if constexpr (is_default_parameter::value) os << 1 << "\n"; else - os << subdomains[k] << "\n"; + os << subdomains[k] << "\n"; } if(!corners.empty()){ From d9982d5a822396cc14ab58a33db0b4d597adb9c5 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 30 Sep 2026 14:48:34 +0200 Subject: [PATCH 32/72] Apply batched suggestions from code review Co-authored-by: Mael --- Stream_support/include/CGAL/IO/MEDIT.h | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 5cd53f4dbe6a..7ae139d73ff7 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -376,9 +376,9 @@ bool read_MEDIT(std::istream& is, * \tparam TetrahedronRange a model of the concept `BackInsertionSequence` whose `value_type` is `std::array` * * \param is the input stream - * \param points points of the soup of cells + * \param points points of the soup of tetrahedra * \param tetrahedra each element in it describes a tetrahedron - * using the indices of the points in `points` + * \param tetrahedra a range where each element is a tetrahedron described by indices into `points` * * \param np optional \ref bgl_namedparameters "Named Parameters" described below * @@ -477,7 +477,7 @@ bool read_MEDIT(std::istream& is, /*! * \ingroup PkgStreamSupportIoFuncsMEDIT * - * \brief writes the `points` and `tetrahedra` using the \ref IOStreamMedit + * \brief writes a soup of indexed tetrahedra using the \ref IOStreamMedit * * \tparam PointRange a model of the concept `ConstRange` whose value type is the point type * \tparam TetrahedronRange a model of the concept `ConstRange` @@ -485,9 +485,8 @@ bool read_MEDIT(std::istream& is, * whose `value_type` is `std::size_t`. * * \param os the output stream - * \param points points of the soup of cells - * \param tetrahedra each element in it describes a cell - * using the indices of the points in `points` + * \param points points of the soup of tetrahedra + * \param tetrahedra a range where each element is a tetrahedron described by indices into `points` * * \param np optional \ref bgl_namedparameters "Named Parameters" described below * @@ -496,7 +495,7 @@ bool read_MEDIT(std::istream& is, * \cgalParamDescription{a const reference wrapper of a container of integers of the same size as `tetrahedra`. * Each element in the container indicates the subdomain index of the corresponding tetrahedron at the same position.} * \cgalParamType{a `std::reference_wrapper` to a model of the concept `SequenceContainer` of integer.} - * \cgalParamDefault{all tetrahedra will have the subdomain id `1`.} + * \cgalParamDefault{all tetrahedra will be given the subdomain index `1`.} * \cgalParamNEnd * * \cgalParamNBegin{facets_with_indices} From 45a004f11c2fcb22ded3be1a059b2969413522de Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 30 Sep 2026 14:59:32 +0100 Subject: [PATCH 33/72] with_indices -> with_index --- .../internal/parameters_interface.h | 6 +- Stream_support/include/CGAL/IO/MEDIT.h | 92 +++++++++---------- .../test/Stream_support/test_MEDIT.cpp | 18 ++-- 3 files changed, 58 insertions(+), 58 deletions(-) diff --git a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h index 6fc4a1fcefa0..75c25a74f830 100644 --- a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h +++ b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h @@ -69,9 +69,9 @@ CGAL_add_named_parameter(stream_precision_t, stream_precision, stream_precision) CGAL_add_named_parameter(read_only_one_object_t, read_only_one_object, read_only_one_object) CGAL_add_named_parameter(subdomains_t, subdomains, subdomains) -CGAL_add_named_parameter(facets_with_indices_t, facets_with_indices, facets_with_indices) -CGAL_add_named_parameter(edges_with_indices_t, edges_with_indices, edges_with_indices) -CGAL_add_named_parameter(corners_with_indices_t, corners_with_indices, corners_with_indices) +CGAL_add_named_parameter(facets_with_index_t, facets_with_index, facets_with_index) +CGAL_add_named_parameter(edges_with_index_t, edges_with_index, edges_with_index) +CGAL_add_named_parameter(corners_with_index_t, corners_with_index, corners_with_index) // List of named parameters that we use in the package 'Mesh_3' diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 7ae139d73ff7..38cef7c29aeb 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -111,12 +111,12 @@ bool read_MEDIT(std::istream& is, PointRange& points, TetrahedronRange& tetrahedra, std::vector& subdomains, - FacetWithIndexRange& facets_with_indices, - bool read_facets_with_indices, - EdgeWithIndexRange& edges_with_indices, - bool read_edges_with_indices, - CornerWithIndexRange& corners_with_indices, - bool read_corners_with_indices, + FacetWithIndexRange& facets_with_index, + bool read_facets_with_index, + EdgeWithIndexRange& edges_with_index, + bool read_edges_with_index, + CornerWithIndexRange& corners_with_index, + bool read_corners_with_index, bool verbose, bool& is_CGAL_mesh) { @@ -190,9 +190,9 @@ bool read_MEDIT(std::istream& is, if(line.find("Triangles") != std::string::npos) { - if(read_facets_with_indices){ + if(read_facets_with_index){ is >> nf; - CGAL::internal::reserve(facets_with_indices, nf); + CGAL::internal::reserve(facets_with_index, nf); if(verbose) std::cerr << "Reading "<< nf << " triangles" << std::endl; @@ -228,7 +228,7 @@ bool read_MEDIT(std::istream& is, { std::rotate(std::begin(facet), std::next(std::begin(facet)), std::end(facet)); } - facets_with_indices.push_back({facet[0], facet[1], facet[2], surface_patch_id}); + facets_with_index.push_back({facet[0], facet[1], facet[2], surface_patch_id}); } }else{ is >> nf; @@ -279,9 +279,9 @@ bool read_MEDIT(std::istream& is, if(line.find("Corners") != std::string::npos) { - if(read_corners_with_indices){ + if(read_corners_with_index){ is >> ncorners; - CGAL::internal::reserve(corners_with_indices, ncorners); + CGAL::internal::reserve(corners_with_index, ncorners); if(verbose) std::cerr << "Reading "<< ncorners << " corners" << std::endl; @@ -299,7 +299,7 @@ bool read_MEDIT(std::istream& is, return false; } // typename CornerWithIndex::value_type cwi = {offset + n}; - corners_with_indices.push_back( {offset + n - 1 } ); + corners_with_index.push_back( {offset + n - 1 } ); } }else{ is >> ncorners; @@ -311,9 +311,9 @@ bool read_MEDIT(std::istream& is, if(line.find("Edges") != std::string::npos) { - if(read_edges_with_indices){ + if(read_edges_with_index){ is >> nedges; - CGAL::internal::reserve(edges_with_indices, nedges); + CGAL::internal::reserve(edges_with_index, nedges); if(verbose) std::cerr << "Reading "<< nedges << " edges" << std::endl; @@ -330,8 +330,8 @@ bool read_MEDIT(std::istream& is, std::cerr << "Issue while reading edges" << std::endl; return false; } - edges_with_indices.push_back({offset + n[0] - 1, offset + n[1] - 1, curve_index}); - CGAL_assertion(edges_with_indices.size() == static_cast(i + 1)); + edges_with_index.push_back({offset + n[0] - 1, offset + n[1] - 1, curve_index}); + CGAL_assertion(edges_with_index.size() == static_cast(i + 1)); } }else{ is >> nedges; @@ -347,9 +347,9 @@ bool read_MEDIT(std::istream& is, { std::cout << points.size() - std::size_t(offset) << " points" << std::endl; std::cout << tetrahedra.size() << " cells" << std::endl; - std::cout << facets_with_indices.size() << " border facets" << std::endl; - std::cout << edges_with_indices.size() << " edges" << std::endl; - std::cout << corners_with_indices.size() << " corners" << std::endl; + std::cout << facets_with_index.size() << " border facets" << std::endl; + std::cout << edges_with_index.size() << " edges" << std::endl; + std::cout << corners_with_index.size() << " corners" << std::endl; } if(tetrahedra.empty()) @@ -391,21 +391,21 @@ bool read_MEDIT(std::istream& is, * \cgalParamDefault{subdomains are ignored} * \cgalParamNEnd * - * \cgalParamNBegin{facets_with_indices} + * \cgalParamNBegin{facets_with_index} * \cgalParamDescription{a non-const reference wrapper of a container of quadruples of integers that will be filled by this function. * Each element represents a facet with vertices corresponding to the three first integers, and the last integer being the surface patch index of the facet.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of four integers.} * \cgalParamDefault{facets are ignored} * \cgalParamNEnd * - * \cgalParamNBegin{edges_with_indices} + * \cgalParamNBegin{edges_with_index} * \cgalParamDescription{a non-const reference wrapper of a container of triples of integers that will be filled by this function. * Each element represents an edge with vertices corresponding to the two first integers, and the last integer being the curve index of the edge.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of three integers.} * \cgalParamDefault{edges are ignored} * \cgalParamNEnd * - * \cgalParamNBegin{corners_with_indices} + * \cgalParamNBegin{corners_with_index} * \cgalParamDescription{a non-const reference wrapper of a container of pair of integers that will be filled by this function. * Each element represents a corner at the vertex corresponding to the first integer, and the last integer being the corner index.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of two integers.} @@ -443,33 +443,33 @@ bool read_MEDIT(std::istream& is, Subdomains subdomains = choose_parameter(get_parameter_reference(np, internal_np::subdomains), default_subdomains); // facets - std::vector> default_facets_with_indices; - using Facets_with_indices = typename internal_np::Lookup_named_param_def>>::reference; - Facets_with_indices facets_with_indices = choose_parameter(get_parameter_reference(np, internal_np::facets_with_indices), default_facets_with_indices); + std::vector> default_facets_with_index; + using Facets_with_index = typename internal_np::Lookup_named_param_def>>::reference; + Facets_with_index facets_with_index = choose_parameter(get_parameter_reference(np, internal_np::facets_with_index), default_facets_with_index); // edges - std::vector> default_edges_with_indices; - using Edges_with_indices = typename internal_np::Lookup_named_param_def>>::reference; - Edges_with_indices edges_with_indices = choose_parameter(get_parameter_reference(np, internal_np::edges_with_indices), default_edges_with_indices); + std::vector> default_edges_with_index; + using Edges_with_index = typename internal_np::Lookup_named_param_def>>::reference; + Edges_with_index edges_with_index = choose_parameter(get_parameter_reference(np, internal_np::edges_with_index), default_edges_with_index); // corners - std::vector> default_corners_with_indices; - using Corners_with_indices = typename internal_np::Lookup_named_param_def>>::reference; - Corners_with_indices corners_with_indices = choose_parameter(get_parameter_reference(np, internal_np::corners_with_indices), default_corners_with_indices); + std::vector> default_corners_with_index; + using Corners_with_index = typename internal_np::Lookup_named_param_def>>::reference; + Corners_with_index corners_with_index = choose_parameter(get_parameter_reference(np, internal_np::corners_with_index), default_corners_with_index); - constexpr bool is_facets_with_indices_map = !parameters::is_default_parameter::value; + constexpr bool is_facets_with_index_map = !parameters::is_default_parameter::value; - constexpr bool is_edges_with_indices_map = !parameters::is_default_parameter::value; + constexpr bool is_edges_with_index_map = !parameters::is_default_parameter::value; - constexpr bool is_corners_with_indices_map = !parameters::is_default_parameter::value; + constexpr bool is_corners_with_index_map = !parameters::is_default_parameter::value; bool is_CGAL_mesh; return internal::read_MEDIT(is, points, tetrahedra, subdomains, - facets_with_indices, is_facets_with_indices_map, - edges_with_indices, is_facets_with_indices_map, - corners_with_indices, is_corners_with_indices_map, + facets_with_index, is_facets_with_index_map, + edges_with_index, is_facets_with_index_map, + corners_with_index, is_corners_with_index_map, verbose, is_CGAL_mesh); } @@ -498,21 +498,21 @@ bool read_MEDIT(std::istream& is, * \cgalParamDefault{all tetrahedra will be given the subdomain index `1`.} * \cgalParamNEnd * - * \cgalParamNBegin{facets_with_indices} + * \cgalParamNBegin{facets_with_index} * \cgalParamDescription{a const reference wrapper of a container of quadruples of integers that will be written by this function. * Each element corresponds to a facet with vertices corresponding to the three first integers, and the last integer being the surface patch index of the facet.} * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the quadruples can be accessed with `std::get()`} * \cgalParamDefault{facets are not written} * \cgalParamNEnd * - * \cgalParamNBegin{edges_with_indices} + * \cgalParamNBegin{edges_with_index} * \cgalParamDescription{a const reference wrapper of a container of triples of integers that will be written by this function. * Each element corresponds to an edge with vertices corresponding to the two first integers, and the last integer being the curve index of the edge.} * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the triples can be accessed with `std::get()`} * \cgalParamDefault{edges are not written} * \cgalParamNEnd * - * \cgalParamNBegin{corners_with_indices} + * \cgalParamNBegin{corners_with_index} * \cgalParamDescription{a const reference wrapper of a container of pair of integers that will be written by this function. * Each element corresponds to a corner at the vertex corresponding to the first integer, the second integer being the corner index. * As Medit has no notion of corner indices it is not written.} @@ -556,14 +556,14 @@ bool write_MEDIT(std::ostream& os, using Subdomains = typename internal_np::Lookup_named_param_def>::reference; Subdomains subdomains = choose_parameter(get_parameter_reference(np, internal_np::subdomains), default_subdomains); - using Corners_with_indices = typename internal_np::Lookup_named_param_def>>::reference; - Corners_with_indices corners = choose_parameter(get_parameter_reference(np, internal_np::corners_with_indices), default_corners); + using Corners_with_index = typename internal_np::Lookup_named_param_def>>::reference; + Corners_with_index corners = choose_parameter(get_parameter_reference(np, internal_np::corners_with_index), default_corners); - using Edges_with_indices = typename internal_np::Lookup_named_param_def>>::reference; - Edges_with_indices edges = choose_parameter(get_parameter_reference(np, internal_np::edges_with_indices), default_edges); + using Edges_with_index = typename internal_np::Lookup_named_param_def>>::reference; + Edges_with_index edges = choose_parameter(get_parameter_reference(np, internal_np::edges_with_index), default_edges); - using Facets_with_indices = typename internal_np::Lookup_named_param_def>>::reference; - Facets_with_indices facets = choose_parameter(get_parameter_reference(np, internal_np::facets_with_indices), default_facets); + using Facets_with_index = typename internal_np::Lookup_named_param_def>>::reference; + Facets_with_index facets = choose_parameter(get_parameter_reference(np, internal_np::facets_with_index), default_facets); os << "MeshVersionFormatted 1\nDimension 3\nVertices\n"; diff --git a/Stream_support/test/Stream_support/test_MEDIT.cpp b/Stream_support/test/Stream_support/test_MEDIT.cpp index 820382195674..31cd2f8a2c3d 100644 --- a/Stream_support/test/Stream_support/test_MEDIT.cpp +++ b/Stream_support/test/Stream_support/test_MEDIT.cpp @@ -22,18 +22,18 @@ int main() { std::deque> corners; bool verbose = false; bool success = CGAL::IO::read_MEDIT(input, points, cells, CGAL::parameters::subdomains(std::ref(subdomains)) - .facets_with_indices(std::ref(facets)) - .edges_with_indices(std::ref(edges)) - .corners_with_indices(std::ref(corners)) + .facets_with_index(std::ref(facets)) + .edges_with_index(std::ref(edges)) + .corners_with_index(std::ref(corners)) .verbose(verbose)); assert(success); std::ostringstream output; output.precision(17); CGAL::IO::write_MEDIT(output, points, cells, CGAL::parameters::subdomains(std::cref(subdomains)) - .facets_with_indices(std::cref(facets)) - .edges_with_indices(std::cref(edges)) - .corners_with_indices(std::cref(corners))); + .facets_with_index(std::cref(facets)) + .edges_with_index(std::cref(edges)) + .corners_with_index(std::cref(corners))); std::istringstream input2(output.str()); std::vector points2; std::vector> cells2; @@ -42,9 +42,9 @@ int main() { std::vector> facets2; std::deque> corners2; success = CGAL::IO::read_MEDIT(input2, points2, cells2, CGAL::parameters::subdomains(std::ref(subdomains2)) - .facets_with_indices(std::ref(facets2)) - .edges_with_indices(std::ref(edges2)) - .corners_with_indices(std::ref(corners2)) + .facets_with_index(std::ref(facets2)) + .edges_with_index(std::ref(edges2)) + .corners_with_index(std::ref(corners2)) .verbose(verbose)); assert(points == points2); From bf12c54727c2121c8f49ca6e34e9548520158386 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 1 Oct 2026 14:36:56 +0100 Subject: [PATCH 34/72] Rewrite after Mael's review --- .../internal/parameters_interface.h | 8 +- Stream_support/include/CGAL/IO/MEDIT.h | 292 +++++++++--------- .../data/polyhedral_complex.mesh | 32 +- .../test/Stream_support/test_MEDIT.cpp | 30 +- 4 files changed, 186 insertions(+), 176 deletions(-) diff --git a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h index 75c25a74f830..79bfbd43701e 100644 --- a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h +++ b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h @@ -68,10 +68,10 @@ CGAL_add_named_parameter(output_color_t, output_color, output_color) CGAL_add_named_parameter(stream_precision_t, stream_precision, stream_precision) CGAL_add_named_parameter(read_only_one_object_t, read_only_one_object, read_only_one_object) -CGAL_add_named_parameter(subdomains_t, subdomains, subdomains) -CGAL_add_named_parameter(facets_with_index_t, facets_with_index, facets_with_index) -CGAL_add_named_parameter(edges_with_index_t, edges_with_index, edges_with_index) -CGAL_add_named_parameter(corners_with_index_t, corners_with_index, corners_with_index) +// List of named parameters that we use in the package 'Stream_support' +CGAL_add_named_parameter(facets_with_patch_index_t, facets_with_patch_index, facets_with_patch_index) +CGAL_add_named_parameter(edges_with_curve_index_t, edges_with_curve_index, edges_with_curve_index) +CGAL_add_named_parameter(vertices_with_corner_index_t, vertices_with_corner_index, vertices_with_corner_index) // List of named parameters that we use in the package 'Mesh_3' diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 38cef7c29aeb..4c0d3c85305d 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -23,6 +23,7 @@ #include #include #include +#include #include namespace CGAL { @@ -35,26 +36,26 @@ namespace IO { namespace internal { template -struct Facet_with_index +struct Facet_with_patch_index { int v0, v1, v2; SurfacePatchIndex surface_patch_index; }; template -struct Edge_with_index +struct Edge_with_curve_index { int v0, v1; CurveIndex curve_index; }; template -struct Corner_with_index +struct Vertex_with_corner_index { int v; CornerIndex corner_index; - bool operator==(const Corner_with_index& rhs) const + bool operator==(const Vertex_with_corner_index& rhs) const { return (v == rhs.v) && (corner_index == rhs.corner_index); } @@ -79,57 +80,63 @@ int get_two(const T& t) } template -int get_zero(const Corner_with_index& t) +int get_zero(const Vertex_with_corner_index& t) { return t.v; } +template +CornerIndex get_one(const Vertex_with_corner_index& t) +{ + return t.corner_index; +} + template -int get_zero(const Edge_with_index& t) +int get_zero(const Edge_with_curve_index& t) { return t.v0; } template -int get_one(const Edge_with_index& t) +int get_one(const Edge_with_curve_index& t) { return t.v1; } template -CurveIndex get_two(const Edge_with_index& t) +CurveIndex get_two(const Edge_with_curve_index& t) { return t.curve_index; } template // either Corner_with_index or a tuple/pair/array + class CellRange, + class FacetWithIndexRange, // either Facet_with_patch_index or a tuple/array + class EdgeWithIndexRange, // either Edge_with_curve_index or a tuple/array + class CornerWithIndexRange> // either Vertex_with_corner_index or a tuple/pair/array bool read_MEDIT(std::istream& is, PointRange& points, - TetrahedronRange& tetrahedra, - std::vector& subdomains, - FacetWithIndexRange& facets_with_index, - bool read_facets_with_index, - EdgeWithIndexRange& edges_with_index, - bool read_edges_with_index, - CornerWithIndexRange& corners_with_index, - bool read_corners_with_index, + CellRange& cells, + std::vector& subdomain_indices, + FacetWithIndexRange& facets_with_patch_index, + bool read_facets_with_patch_index, + EdgeWithIndexRange& edges_with_curve_index, + bool read_edges_with_curve_index, + CornerWithIndexRange& vertices_with_corner_index, + bool read_vertices_with_corner_index, bool verbose, bool& is_CGAL_mesh) { using Point_3 = typename PointRange::value_type; using FT = typename Kernel_traits::Kernel::FT; using Facet = std::array; - using Tet_with_ref = typename std::iterator_traits::value_type; + using Cell_with_ref = typename std::iterator_traits::value_type; if(!is) return false; int dim; - int nv, nf, ntet, ref, ncorners, nedges; + int nv, nf, ntet, ref, nvertices, nedges, nridges; int offset = static_cast(points.size()); std::string word; @@ -185,14 +192,17 @@ bool read_MEDIT(std::istream& is, return false; } points.emplace_back(x,y,z); + if(ref != 0){ + vertices_with_corner_index.push_back({offset + i, ref}); + } } } if(line.find("Triangles") != std::string::npos) { - if(read_facets_with_index){ + if(read_facets_with_patch_index){ is >> nf; - CGAL::internal::reserve(facets_with_index, nf); + CGAL::internal::reserve(facets_with_patch_index, nf); if(verbose) std::cerr << "Reading "<< nf << " triangles" << std::endl; @@ -228,7 +238,7 @@ bool read_MEDIT(std::istream& is, { std::rotate(std::begin(facet), std::next(std::begin(facet)), std::end(facet)); } - facets_with_index.push_back({facet[0], facet[1], facet[2], surface_patch_id}); + facets_with_patch_index.push_back({facet[0], facet[1], facet[2], surface_patch_id}); } }else{ is >> nf; @@ -242,7 +252,7 @@ bool read_MEDIT(std::istream& is, is >> ntet; if(verbose) - std::cerr << "Reading "<< ntet << " tetrahedra" << std::endl; + std::cerr << "Reading "<< ntet << " cells" << std::endl; for(int i=0; i> n[0] >> n[1] >> n[2] >> n[3] >> reference)) { if(verbose) - std::cerr << "Issue while reading tetrahedra" << std::endl; + std::cerr << "Issue while reading cells" << std::endl; return false; } @@ -266,54 +276,30 @@ bool read_MEDIT(std::istream& is, CGAL_warning(n[j] != n[k]); ) - Tet_with_ref t; + Cell_with_ref t; t[0] = offset + n[0] - 1; t[1] = offset + n[1] - 1; t[2] = offset + n[2] - 1; t[3] = offset + n[3] - 1; - tetrahedra.push_back(t); - subdomains.push_back(reference); + cells.push_back(t); + subdomain_indices.push_back(reference); } } if(line.find("Corners") != std::string::npos) { - if(read_corners_with_index){ - is >> ncorners; - CGAL::internal::reserve(corners_with_index, ncorners); - - if(verbose) - std::cerr << "Reading "<< ncorners << " corners" << std::endl; - - if(verbose && ncorners == 0) - std::cerr << "Warning: Corners section is empty" << std::endl; - - for(int i = 0; i < ncorners; ++i) - { - int n; - if(!(is >> n)) - { - if(verbose) - std::cerr << "Issue while reading corners" << std::endl; - return false; - } - // typename CornerWithIndex::value_type cwi = {offset + n}; - corners_with_index.push_back( {offset + n - 1 } ); - } - }else{ - is >> ncorners; + is >> nvertices; std::string buffer; - for(int i=0; i> nedges; - CGAL::internal::reserve(edges_with_index, nedges); + CGAL::internal::reserve(edges_with_curve_index, nedges); if(verbose) std::cerr << "Reading "<< nedges << " edges" << std::endl; @@ -330,8 +316,8 @@ bool read_MEDIT(std::istream& is, std::cerr << "Issue while reading edges" << std::endl; return false; } - edges_with_index.push_back({offset + n[0] - 1, offset + n[1] - 1, curve_index}); - CGAL_assertion(edges_with_index.size() == static_cast(i + 1)); + edges_with_curve_index.push_back({offset + n[0] - 1, offset + n[1] - 1, curve_index}); + CGAL_assertion(edges_with_curve_index.size() == static_cast(i + 1)); } }else{ is >> nedges; @@ -339,6 +325,14 @@ bool read_MEDIT(std::istream& is, for(int i=0; i> nridges; + std::string buffer; + for(int i=0; i` + * \tparam CellRange a model of the concept `BackInsertionSequence` whose `value_type` is `std::array` * * \param is the input stream - * \param points points of the soup of tetrahedra - * \param tetrahedra each element in it describes a tetrahedron - * \param tetrahedra a range where each element is a tetrahedron described by indices into `points` + * \param points points of the soup of cells + * \param cells a range where each element is a cell described by indices into `points` * * \param np optional \ref bgl_namedparameters "Named Parameters" described below * * \cgalNamedParamsBegin * - * \cgalParamNBegin{subdomains} + * \cgalParamNBegin{subdomain_indices} * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. - * Each element in the container indicates the subdomain index of the corresponding tetrahedron at the same position.} + * Each element in the container indicates the subdomain index of the corresponding cell at the same position.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` able to store `int`.} - * \cgalParamDefault{subdomains are ignored} + * \cgalParamDefault{subdomain_indices are ignored} * \cgalParamNEnd * - * \cgalParamNBegin{facets_with_index} + * \cgalParamNBegin{facets_with_patch_index} * \cgalParamDescription{a non-const reference wrapper of a container of quadruples of integers that will be filled by this function. * Each element represents a facet with vertices corresponding to the three first integers, and the last integer being the surface patch index of the facet.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of four integers.} * \cgalParamDefault{facets are ignored} * \cgalParamNEnd * - * \cgalParamNBegin{edges_with_index} + * \cgalParamNBegin{edges_with_curve_index} * \cgalParamDescription{a non-const reference wrapper of a container of triples of integers that will be filled by this function. * Each element represents an edge with vertices corresponding to the two first integers, and the last integer being the curve index of the edge.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of three integers.} * \cgalParamDefault{edges are ignored} * \cgalParamNEnd * - * \cgalParamNBegin{corners_with_index} + * \cgalParamNBegin{vertices_with_corner_index} * \cgalParamDescription{a non-const reference wrapper of a container of pair of integers that will be filled by this function. * Each element represents a corner at the vertex corresponding to the first integer, and the last integer being the corner index.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of two integers.} - * \cgalParamDefault{corners are ignored} + * \cgalParamDefault{vertices are ignored} * \cgalParamNEnd * * \cgalParamNBegin{verbose} @@ -425,10 +418,10 @@ bool read_MEDIT(std::istream& is, * \see \ref IOStreamMedit */ -template +template bool read_MEDIT(std::istream& is, PointRange& points, - TetrahedronRange& tetrahedra, + CellRange& cells, const CGAL_NP_CLASS& np = parameters::default_values()) { using parameters::choose_parameter; @@ -437,39 +430,39 @@ bool read_MEDIT(std::istream& is, const bool verbose = choose_parameter(get_parameter(np, internal_np::verbose), false); - // subdomains - std::vector default_subdomains; - using Subdomains = typename internal_np::Lookup_named_param_def>::reference; - Subdomains subdomains = choose_parameter(get_parameter_reference(np, internal_np::subdomains), default_subdomains); + // subdomain_indices + std::vector default_subdomain_indices; + using Subdomains = typename internal_np::Lookup_named_param_def>::reference; + Subdomains subdomain_indices = choose_parameter(get_parameter_reference(np, internal_np::subdomain_indices), default_subdomain_indices); // facets - std::vector> default_facets_with_index; - using Facets_with_index = typename internal_np::Lookup_named_param_def>>::reference; - Facets_with_index facets_with_index = choose_parameter(get_parameter_reference(np, internal_np::facets_with_index), default_facets_with_index); + std::vector> default_facets_with_patch_index; + using Facets_with_patch_index = typename internal_np::Lookup_named_param_def>>::reference; + Facets_with_patch_index facets_with_patch_index = choose_parameter(get_parameter_reference(np, internal_np::facets_with_patch_index), default_facets_with_patch_index); // edges - std::vector> default_edges_with_index; - using Edges_with_index = typename internal_np::Lookup_named_param_def>>::reference; - Edges_with_index edges_with_index = choose_parameter(get_parameter_reference(np, internal_np::edges_with_index), default_edges_with_index); + std::vector> default_edges_with_curve_index; + using Edges_with_curve_index = typename internal_np::Lookup_named_param_def>>::reference; + Edges_with_curve_index edges_with_curve_index = choose_parameter(get_parameter_reference(np, internal_np::edges_with_curve_index), default_edges_with_curve_index); - // corners - std::vector> default_corners_with_index; - using Corners_with_index = typename internal_np::Lookup_named_param_def>>::reference; - Corners_with_index corners_with_index = choose_parameter(get_parameter_reference(np, internal_np::corners_with_index), default_corners_with_index); + // vertices + std::vector> default_vertices_with_corner_index; + using Vertices_with_corner_index = typename internal_np::Lookup_named_param_def>>::reference; + Vertices_with_corner_index vertices_with_corner_index = choose_parameter(get_parameter_reference(np, internal_np::vertices_with_corner_index), default_vertices_with_corner_index); - constexpr bool is_facets_with_index_map = !parameters::is_default_parameter::value; + constexpr bool is_facets_with_patch_index_map = !parameters::is_default_parameter::value; - constexpr bool is_edges_with_index_map = !parameters::is_default_parameter::value; + constexpr bool is_edges_with_curve_index_map = !parameters::is_default_parameter::value; - constexpr bool is_corners_with_index_map = !parameters::is_default_parameter::value; + constexpr bool is_vertices_with_corner_index_map = !parameters::is_default_parameter::value; bool is_CGAL_mesh; - return internal::read_MEDIT(is, points, tetrahedra, subdomains, - facets_with_index, is_facets_with_index_map, - edges_with_index, is_facets_with_index_map, - corners_with_index, is_corners_with_index_map, + return internal::read_MEDIT(is, points, cells, subdomain_indices, + facets_with_patch_index, is_facets_with_patch_index_map, + edges_with_curve_index, is_facets_with_patch_index_map, + vertices_with_corner_index, is_vertices_with_corner_index_map, verbose, is_CGAL_mesh); } @@ -477,47 +470,47 @@ bool read_MEDIT(std::istream& is, /*! * \ingroup PkgStreamSupportIoFuncsMEDIT * - * \brief writes a soup of indexed tetrahedra using the \ref IOStreamMedit + * \brief writes a soup of indexed cells using the \ref IOStreamMedit * * \tparam PointRange a model of the concept `ConstRange` whose value type is the point type - * \tparam TetrahedronRange a model of the concept `ConstRange` + * \tparam CellRange a model of the concept `ConstRange` * whose `value_type` is a model of the concept `RandomAccessContainer` * whose `value_type` is `std::size_t`. * * \param os the output stream - * \param points points of the soup of tetrahedra - * \param tetrahedra a range where each element is a tetrahedron described by indices into `points` + * \param points points of the soup of cells + * \param cells a range where each element is a cell described by indices into `points` * * \param np optional \ref bgl_namedparameters "Named Parameters" described below * * \cgalNamedParamsBegin - * \cgalParamNBegin{subdomains} - * \cgalParamDescription{a const reference wrapper of a container of integers of the same size as `tetrahedra`. - * Each element in the container indicates the subdomain index of the corresponding tetrahedron at the same position.} + * \cgalParamNBegin{subdomain_indices} + * \cgalParamDescription{a const reference wrapper of a container of integers of the same size as `cells`. + * Each element in the container indicates the subdomain index of the corresponding cell at the same position.} * \cgalParamType{a `std::reference_wrapper` to a model of the concept `SequenceContainer` of integer.} - * \cgalParamDefault{all tetrahedra will be given the subdomain index `1`.} + * \cgalParamDefault{all cells will be given the subdomain index `1`.} * \cgalParamNEnd * - * \cgalParamNBegin{facets_with_index} + * \cgalParamNBegin{facets_with_patch_index} * \cgalParamDescription{a const reference wrapper of a container of quadruples of integers that will be written by this function. * Each element corresponds to a facet with vertices corresponding to the three first integers, and the last integer being the surface patch index of the facet.} * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the quadruples can be accessed with `std::get()`} * \cgalParamDefault{facets are not written} * \cgalParamNEnd * - * \cgalParamNBegin{edges_with_index} + * \cgalParamNBegin{edges_with_curve_index} * \cgalParamDescription{a const reference wrapper of a container of triples of integers that will be written by this function. * Each element corresponds to an edge with vertices corresponding to the two first integers, and the last integer being the curve index of the edge.} * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the triples can be accessed with `std::get()`} * \cgalParamDefault{edges are not written} * \cgalParamNEnd * - * \cgalParamNBegin{corners_with_index} + * \cgalParamNBegin{vertices_with_corner_index} * \cgalParamDescription{a const reference wrapper of a container of pair of integers that will be written by this function. * Each element corresponds to a corner at the vertex corresponding to the first integer, the second integer being the corner index. * As Medit has no notion of corner indices it is not written.} * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the pairs can be accessed with `std::get()`} - * \cgalParamDefault{corners are not written} + * \cgalParamDefault{vertices are not written} * \cgalParamNEnd * * \cgalNamedParamsEnd @@ -526,13 +519,13 @@ bool read_MEDIT(std::istream& is, * * \see \ref IOStreamMedit */ -template +template bool write_MEDIT(std::ostream& os, const PointRange& points, - const TetrahedronRange& tetrahedra, + const CellRange& cells, const CGAL_NP_CLASS& np = parameters::default_values() #ifndef DOXYGEN_RUNNING - , std::enable_if_t>* = nullptr + , std::enable_if_t>* = nullptr #endif ) @@ -547,46 +540,57 @@ bool write_MEDIT(std::ostream& os, if(!os) return false; - // subdomains - std::vector default_subdomains; - std::vector> default_corners; + // subdomain_indices + std::vector default_subdomain_indices; + std::vector> default_vertices; std::vector> default_edges; std::vector> default_facets; - using Subdomains = typename internal_np::Lookup_named_param_def>::reference; - Subdomains subdomains = choose_parameter(get_parameter_reference(np, internal_np::subdomains), default_subdomains); + using Subdomains = typename internal_np::Lookup_named_param_def>::reference; + Subdomains subdomain_indices = choose_parameter(get_parameter_reference(np, internal_np::subdomain_indices), default_subdomain_indices); - using Corners_with_index = typename internal_np::Lookup_named_param_def>>::reference; - Corners_with_index corners = choose_parameter(get_parameter_reference(np, internal_np::corners_with_index), default_corners); + using Vertices_with_corner_index = typename internal_np::Lookup_named_param_def>>::reference; + Vertices_with_corner_index vertices = choose_parameter(get_parameter_reference(np, internal_np::vertices_with_corner_index), default_vertices); - using Edges_with_index = typename internal_np::Lookup_named_param_def>>::reference; - Edges_with_index edges = choose_parameter(get_parameter_reference(np, internal_np::edges_with_index), default_edges); + using Edges_with_curve_index = typename internal_np::Lookup_named_param_def>>::reference; + Edges_with_curve_index edges = choose_parameter(get_parameter_reference(np, internal_np::edges_with_curve_index), default_edges); - using Facets_with_index = typename internal_np::Lookup_named_param_def>>::reference; - Facets_with_index facets = choose_parameter(get_parameter_reference(np, internal_np::facets_with_index), default_facets); + using Facets_with_patch_index = typename internal_np::Lookup_named_param_def>>::reference; + Facets_with_patch_index facets = choose_parameter(get_parameter_reference(np, internal_np::facets_with_patch_index), default_facets); + + std::map vertex_corner_index_map; + for(const auto& c : vertices){ + vertex_corner_index_map[internal::get_zero(c) + 1] = internal::get_one(c); + } + os << "MeshVersionFormatted 1\nDimension 3\n"; - os << "MeshVersionFormatted 1\nDimension 3\nVertices\n"; + os << "Vertices\n"; os << points.size() << "\n"; - for (const Point_3& p : points) - os << p << " 0\n"; + for (int i = 0; i < static_cast(points.size()); ++i){ + const Point_3& p = points[i]; + std::map::iterator it = vertex_corner_index_map.find(i + 1); + int corner_index = (it != vertex_corner_index_map.end()) ? it->second : 0; + os << p << " " << corner_index << "\n"; + } + os << "Tetrahedra\n"; - os << tetrahedra.size() << "\n"; - for (std::size_t k=0; k::value) + os << cells[k][0]+1 << " " + << cells[k][1]+1 << " " + << cells[k][2]+1 << " " + << cells[k][3]+1 << " "; + if constexpr (is_default_parameter::value) os << 1 << "\n"; else - os << subdomains[k] << "\n"; + os << subdomain_indices[k] << "\n"; } - if(!corners.empty()){ - os << "Corners\n" << corners.size() << "\n"; - for(const auto& c : corners) + if(!vertices.empty()){ + os << "Corners\n" << vertices.size() << "\n"; + for(const auto& c : vertices) os << internal::get_zero(c) + 1 << "\n"; } @@ -594,6 +598,10 @@ bool write_MEDIT(std::ostream& os, os << "Edges\n" << edges.size() << "\n"; for(const auto& e : edges) os << internal::get_zero(e) +1 << " " << internal::get_one(e) + 1 << " " << internal::get_two(e) << "\n"; + + os << "Ridges\n" << edges.size() << "\n"; + for(std::size_t i = 1; i <= edges.size(); ++i) + os << i << "\n"; } if(!facets.empty()){ diff --git a/Stream_support/test/Stream_support/data/polyhedral_complex.mesh b/Stream_support/test/Stream_support/data/polyhedral_complex.mesh index 0dae46b18e59..d7ec2d16cf72 100644 --- a/Stream_support/test/Stream_support/data/polyhedral_complex.mesh +++ b/Stream_support/test/Stream_support/data/polyhedral_complex.mesh @@ -3,22 +3,22 @@ Dimension 3 # CGAL::Mesh_complex_3_in_triangulation_3 Vertices 357 -0 0 0 0 -0 0 50 0 -0 0 100 0 -0 50 66.659999999999997 0 -0 50 100 0 -0 100 0 0 -0 100 50 0 -0 100 100 0 -100 0 0 0 -100 0 50 0 -100 0 100 0 -100 50 66.659999999999997 0 -100 50 100 0 -100 100 0 0 -100 100 50 0 -100 100 100 0 +0 0 0 1 +0 0 50 2 +0 0 100 3 +0 50 66.659999999999997 4 +0 50 100 5 +0 100 0 6 +0 100 50 7 +0 100 100 8 +100 0 0 9 +100 0 50 10 +100 0 100 11 +100 50 66.659999999999997 12 +100 50 100 13 +100 100 0 14 +100 100 50 15 +100 100 100 16 100 39.386215727983412 62.273568757997808 0 100 27.515222328655064 57.986212335080076 0 100 14.378822232785753 53.893969102838732 0 diff --git a/Stream_support/test/Stream_support/test_MEDIT.cpp b/Stream_support/test/Stream_support/test_MEDIT.cpp index 31cd2f8a2c3d..ae814c58316c 100644 --- a/Stream_support/test/Stream_support/test_MEDIT.cpp +++ b/Stream_support/test/Stream_support/test_MEDIT.cpp @@ -19,32 +19,33 @@ int main() { std::vector subdomains; std::vector> edges; std::vector> facets; - std::deque> corners; + std::deque> corners; bool verbose = false; - bool success = CGAL::IO::read_MEDIT(input, points, cells, CGAL::parameters::subdomains(std::ref(subdomains)) - .facets_with_index(std::ref(facets)) - .edges_with_index(std::ref(edges)) - .corners_with_index(std::ref(corners)) + bool success = CGAL::IO::read_MEDIT(input, points, cells, CGAL::parameters::subdomain_indices(std::ref(subdomains)) + .facets_with_patch_index(std::ref(facets)) + .edges_with_curve_index(std::ref(edges)) + .vertices_with_corner_index(std::ref(corners)) .verbose(verbose)); assert(success); std::ostringstream output; output.precision(17); - CGAL::IO::write_MEDIT(output, points, cells, CGAL::parameters::subdomains(std::cref(subdomains)) - .facets_with_index(std::cref(facets)) - .edges_with_index(std::cref(edges)) - .corners_with_index(std::cref(corners))); + CGAL::IO::write_MEDIT(output, points, cells, CGAL::parameters::subdomain_indices(std::cref(subdomains)) + .facets_with_patch_index(std::cref(facets)) + .edges_with_curve_index(std::cref(edges)) + .vertices_with_corner_index(std::cref(corners))); + std::istringstream input2(output.str()); std::vector points2; std::vector> cells2; std::vector subdomains2; std::vector> edges2; std::vector> facets2; - std::deque> corners2; - success = CGAL::IO::read_MEDIT(input2, points2, cells2, CGAL::parameters::subdomains(std::ref(subdomains2)) - .facets_with_index(std::ref(facets2)) - .edges_with_index(std::ref(edges2)) - .corners_with_index(std::ref(corners2)) + std::deque> corners2; + success = CGAL::IO::read_MEDIT(input2, points2, cells2, CGAL::parameters::subdomain_indices(std::ref(subdomains2)) + .facets_with_patch_index(std::ref(facets2)) + .edges_with_curve_index(std::ref(edges2)) + .vertices_with_corner_index(std::ref(corners2)) .verbose(verbose)); assert(points == points2); @@ -54,5 +55,6 @@ int main() { assert(edges == edges2); assert(facets == facets2); assert(success); + std::cout << "done" << std::endl; return 0; } From bc9be5584952025b7653f09a792a75d4c3c29b63 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 1 Oct 2026 15:34:40 +0100 Subject: [PATCH 35/72] WIP writing of vertex corner indices is missing in SMDS_3 --- SMDS_3/include/CGAL/IO/File_medit.h | 69 +++++++++++++++++++------- Stream_support/include/CGAL/IO/MEDIT.h | 2 +- 2 files changed, 52 insertions(+), 19 deletions(-) diff --git a/SMDS_3/include/CGAL/IO/File_medit.h b/SMDS_3/include/CGAL/IO/File_medit.h index 479a1b14fa1f..f85e82e6173d 100644 --- a/SMDS_3/include/CGAL/IO/File_medit.h +++ b/SMDS_3/include/CGAL/IO/File_medit.h @@ -503,7 +503,10 @@ struct Medit_pmap_generator +template bool build_triangulation_from_file(std::istream& is, Tr& tr, const bool verbose, @@ -516,45 +519,75 @@ bool build_triangulation_from_file(std::istream& is, using Subdomain_index = typename Tr::Cell::Subdomain_index; using Surface_patch_index = typename Tr::Cell::Surface_patch_index; - using Facet = std::array; // 3 = id + using Facet = std::array; // 3 = id using Tet_with_ref = std::array; // 4 = id - using Edge_with_index = CGAL::IO::internal::Edge_with_index; - using Corner_with_index = CGAL::IO::internal::Corner_with_index; + using Facet_with_index = CGAL::IO::internal::Facet_with_patch_index; + using Edge_with_index = CGAL::IO::internal::Edge_with_curve_index; + using Corner_with_index = CGAL::IO::internal::Vertex_with_corner_index; std::vector finite_cells; std::vector subdomains; std::vector points; - boost::unordered_map border_facets; + + std::vector facet_indices; std::vector edge_indices; std::vector corner_indices; bool is_CGAL_mesh = false; - if(verbose) { + + if(verbose){ std::cout << "Reading .mesh file..." << std::endl; std::cout << "Replace domain #0 = " << replace_domain_0 << std::endl; std::cout << "Allow non-manifoldness = " << allow_non_manifold << std::endl; } bool ok = CGAL::IO::internal::read_MEDIT(is, points, finite_cells, subdomains, - border_facets, true, - edge_indices, corner_indices, - verbose, is_CGAL_mesh); - if(!ok) { + facet_indices, true, + edge_indices, true, + corner_indices, true, + verbose, + is_CGAL_mesh); + if(!ok){ return false; } + boost::unordered_map border_facets; + border_facets.reserve(facet_indices.size()); + + bool has_negative_surface_patch_ids = false; + Surface_patch_index max_surface_patch_id{0}; + + for (const Facet_with_index& fi : facet_indices) + { + if (fi.surface_patch_index<0) + has_negative_surface_patch_ids=true; + max_surface_patch_id=(std::max)(max_surface_patch_id, fi.surface_patch_index); + border_facets.emplace(CGAL::make_array(fi.v0, fi.v1, fi.v2), fi.surface_patch_index); + } + + if(has_negative_surface_patch_ids) + { + if(verbose) + std::cerr << "Warning: negative surface patch ids" << std::endl; + for(auto& facet_and_patch_id : border_facets) { + if(facet_and_patch_id.second < 0) + facet_and_patch_id.second = max_surface_patch_id - facet_and_patch_id.second; + } + } + if(!is_CGAL_mesh) tr.may_have_badly_oriented_cells(true); - return CGAL::SMDS_3::build_triangulation_with_subdomains_range( - tr, points, finite_cells, - subdomains, border_facets, edge_indices, corner_indices, - cx_edges_oit, - verbose, - replace_domain_0 && !is_CGAL_mesh, - allow_non_manifold, - allow_negative_orientation); + return build_triangulation_with_subdomains_range(tr, + points, finite_cells, subdomains, border_facets, + edge_indices, + corner_indices, + cx_edges_oit, + verbose, + replace_domain_0 && !is_CGAL_mesh, + allow_non_manifold, + allow_negative_orientation); } template > n[0] >> n[1] >> curve_index)) { if(verbose) From 8c8b89a785fe47f6e375147893e7946a687b4c1e Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 1 Oct 2026 19:48:55 +0100 Subject: [PATCH 36/72] fix links --- .../Stream_support/File_formats/Supported_file_formats.txt | 4 ++-- Stream_support/doc/Stream_support/IOstream.txt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt index 1586bada337e..c6e4ad328b3e 100644 --- a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt +++ b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt @@ -558,8 +558,8 @@ The following \cgal data structures can be exported into the `.mesh` file format \link CGAL::IO::write_MEDIT(std::ostream &os, const CGAL::Conforming_constrained_Delaunay_triangulation_3< Traits, Tr > &ccdt, const NamedParameters& np) `CGAL::IO::write_MEDIT()` \endlink. The following function enables to read and write a tetrahedron soup -- \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, TetrahedronRange&, const NamedParameters&) `CGAL::IO::read_MEDIT()` \endlink -- \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const TetrahedronRange&, const NamedParameters&) `CGAL::IO::writeMEDIT()` \endlink +- \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, CellRange&, const NamedParameters&) `CGAL::IO::read_MEDIT()` \endlink +- \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const CellRange&, const NamedParameters&) `CGAL::IO::writeMEDIT()` \endlink \section IOStreamTetgen Tetgen File Format diff --git a/Stream_support/doc/Stream_support/IOstream.txt b/Stream_support/doc/Stream_support/IOstream.txt index a4c3f99690f9..5bc8450ce2f5 100644 --- a/Stream_support/doc/Stream_support/IOstream.txt +++ b/Stream_support/doc/Stream_support/IOstream.txt @@ -505,8 +505,8 @@ which can perform some combinatorial repairing to ensure the input data is a 2-m \ref IOStreamMedit "MEDIT" - \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, TetrahedronRange&, const NamedParameters&) `CGAL::IO::read_MEDIT()` \endlink - \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const TetrahedronRange&, const NamedParameters&) `CGAL::IO::write_MEDIT()` \endlink + \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, CellRange&, const NamedParameters&) `CGAL::IO::read_MEDIT()` \endlink + \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const CellRange&, const NamedParameters&) `CGAL::IO::write_MEDIT()` \endlink From 3357d80881c91a627135e80b72ca1a6491245066 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 2 Oct 2026 15:51:08 +0200 Subject: [PATCH 37/72] perturb and exude are useless here --- SMDS_3/test/SMDS_3/test_c3t3_io_MEDIT.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SMDS_3/test/SMDS_3/test_c3t3_io_MEDIT.cpp b/SMDS_3/test/SMDS_3/test_c3t3_io_MEDIT.cpp index 46bec27f3849..aac6ea2353ff 100644 --- a/SMDS_3/test/SMDS_3/test_c3t3_io_MEDIT.cpp +++ b/SMDS_3/test/SMDS_3/test_c3t3_io_MEDIT.cpp @@ -45,7 +45,8 @@ int test_MEDIT_with_features() Mesh_criteria criteria(CGAL::parameters::edge_size(0.025) .facet_distance(0.005) .cell_size(0.05)); - C3t3 c3t3 = CGAL::make_mesh_3(domain, criteria); + C3t3 c3t3 = CGAL::make_mesh_3(domain, criteria, + CGAL::parameters::no_perturb().no_exude()); const std::size_t nb_facets = c3t3.number_of_facets(); const std::size_t nb_edges = c3t3.number_of_edges(); From fd64b98362e927328d19c0dba8ecb289de8d6229 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 2 Oct 2026 15:54:00 +0200 Subject: [PATCH 38/72] use corner_index for vertices with dimension 0 --- SMDS_3/include/CGAL/IO/File_medit.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/SMDS_3/include/CGAL/IO/File_medit.h b/SMDS_3/include/CGAL/IO/File_medit.h index f85e82e6173d..b01ab34db6b6 100644 --- a/SMDS_3/include/CGAL/IO/File_medit.h +++ b/SMDS_3/include/CGAL/IO/File_medit.h @@ -359,6 +359,10 @@ class Default_vertex_pmap { switch ( r_c3t3_.in_dimension(vh) ) { + case 0: + { + return r_c3t3_.corner_index(vh); + } case 2: { // Check if each incident surface facet of vh has the same surface index @@ -493,7 +497,7 @@ struct Medit_pmap_generator Cell_pmap; typedef Renumber_surface_patches_pmap Facet_pmap; typedef Null_pmap Facet_pmap_twice; - typedef Null_pmap Vertex_pmap; + typedef Default_vertex_pmap Vertex_pmap; bool print_twice() { return false; } }; From 3692ad7e9b095cf76f3729da5cbb216ff12ed961 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 2 Oct 2026 16:09:04 +0200 Subject: [PATCH 39/72] Apply batched indentation suggestions from code review Co-authored-by: Mael --- Stream_support/include/CGAL/IO/MEDIT.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 937f82484559..625edf541c28 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -113,7 +113,7 @@ template // either Vertex_with_corner_index or a tuple/pair/array + class CornerWithIndexRange> // either Vertex_with_corner_index or a tuple/pair/array bool read_MEDIT(std::istream& is, PointRange& points, CellRange& cells, @@ -362,7 +362,7 @@ bool read_MEDIT(std::istream& is, /*! * \ingroup PkgStreamSupportIoFuncsMEDIT * - * \brief reads the content of `is` into `points` and `cells` using the \ref IOStreamMedit + * \brief reads the content of `is` into `points` and `cells` using the \ref IOStreamMedit. * * * \attention The cell soup is not cleared, and the data from the stream are appended. @@ -471,7 +471,7 @@ bool read_MEDIT(std::istream& is, /*! * \ingroup PkgStreamSupportIoFuncsMEDIT * - * \brief writes a soup of indexed cells using the \ref IOStreamMedit + * \brief writes a soup of indexed cells using the \ref IOStreamMedit. * * \tparam PointRange a model of the concept `ConstRange` whose value type is the point type * \tparam CellRange a model of the concept `ConstRange` @@ -561,7 +561,7 @@ bool write_MEDIT(std::ostream& os, std::map vertex_corner_index_map; for(const auto& c : vertices){ - vertex_corner_index_map[internal::get_zero(c) + 1] = internal::get_one(c); + vertex_corner_index_map[internal::get_zero(c) + 1] = internal::get_one(c); } os << "MeshVersionFormatted 1\nDimension 3\n"; From 6a9104562edab750c75f5ef691fedaeb9c5840b4 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 2 Oct 2026 16:15:34 +0200 Subject: [PATCH 40/72] indentation fix --- Stream_support/include/CGAL/IO/MEDIT.h | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 625edf541c28..34e73cd92d72 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -320,19 +320,21 @@ bool read_MEDIT(std::istream& is, edges_with_curve_index.push_back({offset + n[0] - 1, offset + n[1] - 1, curve_index}); CGAL_assertion(edges_with_curve_index.size() == static_cast(i + 1)); } - }else{ - is >> nedges; - std::string buffer; - for(int i=0; i> nedges; + std::string buffer; + for(int i=0; i> nridges; - std::string buffer; - for(int i=0; i> nridges; + std::string buffer; + for(int i=0; i Date: Fri, 2 Oct 2026 16:12:41 +0100 Subject: [PATCH 41/72] Some changes after Mael's review --- Stream_support/doc/Stream_support/dependencies | 1 + Stream_support/include/CGAL/IO/MEDIT.h | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Stream_support/doc/Stream_support/dependencies b/Stream_support/doc/Stream_support/dependencies index 48f34988e106..3c9d71677256 100644 --- a/Stream_support/doc/Stream_support/dependencies +++ b/Stream_support/doc/Stream_support/dependencies @@ -1,6 +1,7 @@ Alpha_shapes_3 Arrangement_on_surface_2 BGL +Circulator Constrained_triangulation_3 Kernel_23 Linear_cell_complex diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 34e73cd92d72..47eaac2fa4a9 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -510,8 +510,7 @@ bool read_MEDIT(std::istream& is, * * \cgalParamNBegin{vertices_with_corner_index} * \cgalParamDescription{a const reference wrapper of a container of pair of integers that will be written by this function. - * Each element corresponds to a corner at the vertex corresponding to the first integer, the second integer being the corner index. - * As Medit has no notion of corner indices it is not written.} + * Each element corresponds to a corner at the vertex corresponding to the first integer, the second integer being the corner index.} * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the pairs can be accessed with `std::get()`} * \cgalParamDefault{vertices are not written} * \cgalParamNEnd From 519da4988f6633a89b84389b862200a920f716d4 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 2 Oct 2026 17:36:01 +0200 Subject: [PATCH 42/72] keep vertex index only for corners --- SMDS_3/include/CGAL/IO/File_medit.h | 97 +++++------------------------ 1 file changed, 15 insertions(+), 82 deletions(-) diff --git a/SMDS_3/include/CGAL/IO/File_medit.h b/SMDS_3/include/CGAL/IO/File_medit.h index b01ab34db6b6..c6a129e1e866 100644 --- a/SMDS_3/include/CGAL/IO/File_medit.h +++ b/SMDS_3/include/CGAL/IO/File_medit.h @@ -266,7 +266,7 @@ class Renumber_surface_patches_pmap if ( elt_it != surface_map_.end() ) return elt_it->second; else - return -1; + return 0; } int get_first_unused_label(const std::set& label_set, @@ -336,87 +336,23 @@ class Use_cell_indices_pmap // ----------------------------------- // Default_vertex_pmap // ----------------------------------- -template +template class Default_vertex_pmap { - typedef typename C3T3::Surface_patch_index Surface_patch_index; - typedef typename C3T3::Subdomain_index Subdomain_index; - typedef typename C3T3::Index Index; typedef typename C3T3::Vertex_handle Vertex_handle; - typedef typename C3T3::Cell_handle Cell_handle; - typedef typename C3T3::Facet Facet; public: - Default_vertex_pmap(const C3T3& c3t3, - const Cell_pmap& c_pmap, - const Facet_pmap& f_pmap) - : c_pmap_(c_pmap) - , f_pmap_(f_pmap) - , r_c3t3_(c3t3) - , edge_index_(0) {} + Default_vertex_pmap(const C3T3& c3t3) + : r_c3t3_(c3t3) + {} int index(const Vertex_handle& vh) const { - switch ( r_c3t3_.in_dimension(vh) ) - { - case 0: - { - return r_c3t3_.corner_index(vh); - } - case 2: - { - // Check if each incident surface facet of vh has the same surface index - typename std::vector facets; - r_c3t3_.triangulation().finite_incident_facets( - vh, std::back_inserter(facets)); - - if ( facets.begin() == facets.end() ) - return -1; - - // Look for the first surface facet - typename std::vector::iterator it_facet = facets.begin(); - while ( ! r_c3t3_.is_in_complex(*it_facet) ) - { - if ( ++it_facet == facets.end() ) - return -1; - } - - Surface_patch_index facet_index = r_c3t3_.surface_patch_index(*it_facet); - Facet facet = *it_facet; - ++it_facet; - - for( ; it_facet != facets.end() ; ++it_facet) - { - // If another index is found, return value for edge vertice - if ( r_c3t3_.is_in_complex(*it_facet) - && !( facet_index == r_c3t3_.surface_patch_index(*it_facet) ) ) - return edge_index_; - } - - return get(f_pmap_,facet); - } - break; - - case 3: - { - // Returns value of any incident cell - typename std::vector cells; - r_c3t3_.triangulation().finite_incident_cells( - vh,std::back_inserter(cells)); - - if ( cells.begin() != cells.end() ) - return get(c_pmap_, *cells.begin()); - else - return -1; - } - break; - - default: - // must not happen - return -1; - break; - } - } + if(r_c3t3_.in_dimension(vh) == 0) + return r_c3t3_.corner_index(vh); + else + return 0; + } friend int get(const Default_vertex_pmap& vmap, const Vertex_handle& vh) { @@ -424,10 +360,7 @@ class Default_vertex_pmap } private: - const Cell_pmap& c_pmap_; - const Facet_pmap& f_pmap_; const C3T3& r_c3t3_; - const unsigned int edge_index_; }; @@ -462,7 +395,7 @@ struct Medit_pmap_generator Cell_pmap; typedef Renumber_surface_patches_pmap Facet_pmap; typedef Null_pmap Facet_pmap_twice; - typedef Default_vertex_pmap Vertex_pmap; + typedef Default_vertex_pmap Vertex_pmap; bool print_twice() { return false; } }; @@ -474,7 +407,7 @@ struct Medit_pmap_generator typedef Renumber_subdomains_pmap Cell_pmap; typedef Use_cell_indices_pmap Facet_pmap; typedef Use_cell_indices_pmap Facet_pmap_twice; - typedef Default_vertex_pmap Vertex_pmap; + typedef Default_vertex_pmap Vertex_pmap; bool print_twice() { return true; } }; @@ -486,7 +419,7 @@ struct Medit_pmap_generator typedef Use_subdomain_indices Cell_pmap; typedef Use_cell_indices_pmap Facet_pmap; typedef Use_cell_indices_pmap Facet_pmap_twice; - typedef Default_vertex_pmap Vertex_pmap; + typedef Default_vertex_pmap Vertex_pmap; bool print_twice() { return true; } }; @@ -497,7 +430,7 @@ struct Medit_pmap_generator Cell_pmap; typedef Renumber_surface_patches_pmap Facet_pmap; typedef Null_pmap Facet_pmap_twice; - typedef Default_vertex_pmap Vertex_pmap; + typedef Default_vertex_pmap Vertex_pmap; bool print_twice() { return false; } }; @@ -881,7 +814,7 @@ output_to_medit(std::ostream& os, Cell_pmap cell_pmap(c3t3); Facet_pmap facet_pmap(c3t3,cell_pmap); Facet_pmap_twice facet_pmap_twice(c3t3,cell_pmap); - Vertex_pmap vertex_pmap(c3t3,cell_pmap,facet_pmap); + Vertex_pmap vertex_pmap(c3t3); const auto& tr = c3t3.triangulation(); From 1dce812bfbf74e7e371571242c4040028f7e41f4 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 6 Oct 2026 11:58:44 +0200 Subject: [PATCH 43/72] Apply batched suggestions from code review Co-authored-by: Mael --- Stream_support/include/CGAL/IO/MEDIT.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 47eaac2fa4a9..0509c52721b9 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -389,14 +389,14 @@ bool read_MEDIT(std::istream& is, * * \cgalParamNBegin{facets_with_patch_index} * \cgalParamDescription{a non-const reference wrapper of a container of quadruples of integers that will be filled by this function. - * Each element represents a facet with vertices corresponding to the three first integers, and the last integer being the surface patch index of the facet.} + * Each element represents a facet with vertices corresponding to the first three integers, and the last integer being the surface patch index of the facet.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of four integers.} * \cgalParamDefault{facets are ignored} * \cgalParamNEnd * * \cgalParamNBegin{edges_with_curve_index} * \cgalParamDescription{a non-const reference wrapper of a container of triples of integers that will be filled by this function. - * Each element represents an edge with vertices corresponding to the two first integers, and the last integer being the curve index of the edge.} + * Each element represents an edge with vertices corresponding to the first two integers, and the last integer being the curve index of the edge.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of three integers.} * \cgalParamDefault{edges are ignored} * \cgalParamNEnd From d91f5ca821c6d10b02e95d8ccf82d419989af0e8 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 6 Oct 2026 13:29:11 +0100 Subject: [PATCH 44/72] explain correspondence --- Stream_support/include/CGAL/IO/MEDIT.h | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 0509c52721b9..d8ce7a9c2488 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -113,7 +113,7 @@ template // either Vertex_with_corner_index or a tuple/pair/array + class VertexWithCornerIndexRange> // either Vertex_with_corner_index or a tuple/pair/array bool read_MEDIT(std::istream& is, PointRange& points, CellRange& cells, @@ -122,14 +122,14 @@ bool read_MEDIT(std::istream& is, bool read_facets_with_patch_index, EdgeWithIndexRange& edges_with_curve_index, bool read_edges_with_curve_index, - CornerWithIndexRange& vertices_with_corner_index, + VertexWithCornerIndexRange& vertices_with_corner_index, bool read_vertices_with_corner_index, bool verbose, bool& is_CGAL_mesh) { using Point_3 = typename PointRange::value_type; - using FT = typename Kernel_traits::Kernel::FT; - using Facet = std::array; + using FT = typename Kernel_traits::Kernel::FT; + using Facet = std::array; using Cell_with_ref = typename std::iterator_traits::value_type; if(!is) @@ -366,7 +366,12 @@ bool read_MEDIT(std::istream& is, * * \brief reads the content of `is` into `points` and `cells` using the \ref IOStreamMedit. * + * The subdomain index corresponds to what \medit calls cell reference, + * facet patch index corresponds to triangle reference, + * edge curve index to edge reference, + * and vertex corner index to vertex reference. * + * \attention Currently only tetrahedral meshes are supported. * \attention The cell soup is not cleared, and the data from the stream are appended. * * \tparam PointRange a model of the concept `BackInsertionSequence` whose value type is the point type @@ -475,6 +480,13 @@ bool read_MEDIT(std::istream& is, * * \brief writes a soup of indexed cells using the \ref IOStreamMedit. * + * The subdomain index corresponds to what \medit calls cell reference, + * facet patch index corresponds to triangle reference, + * edge curve index to edge reference, + * and vertex corner index to vertex reference. + + * \attention Currently only tetrahedral meshes are supported. + * * \tparam PointRange a model of the concept `ConstRange` whose value type is the point type * \tparam CellRange a model of the concept `ConstRange` * whose `value_type` is a model of the concept `RandomAccessContainer` From 26f60cfbfe161c89d3df2365ef85ad6d1a72c1fd Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 6 Oct 2026 13:40:48 +0100 Subject: [PATCH 45/72] Add \medit alias --- Documentation/doc/resources/1.9.6/BaseDoxyfile.in | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/doc/resources/1.9.6/BaseDoxyfile.in b/Documentation/doc/resources/1.9.6/BaseDoxyfile.in index 885480da05d6..f95d38204024 100644 --- a/Documentation/doc/resources/1.9.6/BaseDoxyfile.in +++ b/Documentation/doc/resources/1.9.6/BaseDoxyfile.in @@ -112,6 +112,7 @@ ALIASES = "cgal=%CGAL" \ "api=API" \ "vtk=VTK" \ "itk=ITK" \ + "medit=MEDIT" \ "visualstudio=Visual Studio" \ "taucs=TAUCS" \ "lapack=LAPACK" \ From 1ac492910297b55fc4fbc04d6a26876dc521d35a Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 6 Oct 2026 13:50:25 +0100 Subject: [PATCH 46/72] Add \medit alias --- Documentation/doc/resources/1.14.0/BaseDoxyfile.in | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/doc/resources/1.14.0/BaseDoxyfile.in b/Documentation/doc/resources/1.14.0/BaseDoxyfile.in index 2cc394c72c70..a8f6401b04db 100644 --- a/Documentation/doc/resources/1.14.0/BaseDoxyfile.in +++ b/Documentation/doc/resources/1.14.0/BaseDoxyfile.in @@ -112,6 +112,7 @@ ALIASES = "cgal=%CGAL" \ "api=API" \ "vtk=VTK" \ "itk=ITK" \ + "medit=MEDIT" \ "visualstudio=Visual Studio" \ "taucs=TAUCS" \ "lapack=LAPACK" \ From 837c1470d0ff2eb0f608e1adb05b1f09c52de5ef Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 6 Oct 2026 14:34:37 +0100 Subject: [PATCH 47/72] Turn \attention into \note --- Stream_support/include/CGAL/IO/3MF.h | 2 +- Stream_support/include/CGAL/IO/GOCAD.h | 4 ++-- Stream_support/include/CGAL/IO/LAS.h | 8 ++++---- Stream_support/include/CGAL/IO/MEDIT.h | 6 +++--- Stream_support/include/CGAL/IO/OBJ.h | 4 ++-- Stream_support/include/CGAL/IO/PLY.h | 16 ++++++++-------- Stream_support/include/CGAL/IO/STL.h | 10 +++++----- Stream_support/include/CGAL/IO/VTK.h | 4 ++-- 8 files changed, 27 insertions(+), 27 deletions(-) diff --git a/Stream_support/include/CGAL/IO/3MF.h b/Stream_support/include/CGAL/IO/3MF.h index c10a4be64d2f..ca219238c538 100644 --- a/Stream_support/include/CGAL/IO/3MF.h +++ b/Stream_support/include/CGAL/IO/3MF.h @@ -384,7 +384,7 @@ bool read_3MF(const std::string& fname, * * \brief reads ranges of points and triangles from an input file, using the \ref IOStream3MF. * - * \attention The ranges not cleared, and the data from the file are appended. + * \note The ranges not cleared, and the data from the file are appended. * * \tparam PointRanges a model of the concepts `RandomAccessContainer` and * `BackInsertionSequence` whose `value_type` is diff --git a/Stream_support/include/CGAL/IO/GOCAD.h b/Stream_support/include/CGAL/IO/GOCAD.h index 127908278cd7..954fc361098b 100644 --- a/Stream_support/include/CGAL/IO/GOCAD.h +++ b/Stream_support/include/CGAL/IO/GOCAD.h @@ -166,7 +166,7 @@ bool read_GOCAD(std::istream& is, * * \brief reads the content of `is` into `points` and `polygons`, using the \ref IOStreamGocad. * - * \attention The polygon soup is not cleared, and the data from the stream are appended. + * \note The polygon soup is not cleared, and the data from the stream are appended. * * \tparam PointRange a model of the concept `BackInsertionSequence` whose value type is the point type * \tparam PolygonRange a model of the concept `BackInsertionSequence` whose `value_type` is @@ -214,7 +214,7 @@ bool read_GOCAD(std::istream& is, * * \brief reads the content of the file `fname` into `points` and `polygons`, using the \ref IOStreamGocad. * - * \attention The polygon soup is not cleared, and the data from the file are appended. + * \note The polygon soup is not cleared, and the data from the file are appended. * * \tparam PointRange a model of the concept `BackInsertionSequence` whose value type is the point type * \tparam PolygonRange a model of the concept `BackInsertionSequence` whose `value_type` is diff --git a/Stream_support/include/CGAL/IO/LAS.h b/Stream_support/include/CGAL/IO/LAS.h index e0e51eb29f81..dd76225f6b3d 100644 --- a/Stream_support/include/CGAL/IO/LAS.h +++ b/Stream_support/include/CGAL/IO/LAS.h @@ -95,7 +95,7 @@ make_las_point_reader(PointMap point_map); - `LAS_property::B` with type `unsigned short` - `LAS_property::I` with type `unsigned short` - \attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. + \note To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. \tparam OutputIteratorValueType type of objects that can be put in `PointOutputIterator`. It must be a model of `DefaultConstructible` and defaults to `value_type_traits::%type`. @@ -125,7 +125,7 @@ bool read_LAS_with_properties(std::istream& is, Potential additional properties are ignored. - \attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. + \note To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. \tparam OutputIteratorValueType type of objects that can be put in `PointOutputIterator`. It must be a model of `DefaultConstructible` and defaults to `value_type_traits::%type`. @@ -237,7 +237,7 @@ make_las_point_writer(PointMap point_map); See documentation of `read_LAS_with_properties()` for the list of available `LAS_property::Tag` classes. - \attention To write to a binary file, the flag `std::ios::binary` must be set during the creation of the `ofstream`. + \note To write to a binary file, the flag `std::ios::binary` must be set during the creation of the `ofstream`. \tparam PointRange is a model of `ConstRange`. The value type of its iterator is the key type of the named parameter `point_map`. @@ -266,7 +266,7 @@ bool write_LAS_with_properties(std::ostream& os, ///< output stream. \brief writes the range of `points` (positions only), using the \ref IOStreamLAS. - \attention To write to a binary file, the flag `std::ios::binary` must be set during the creation of the `ofstream`. + \note To write to a binary file, the flag `std::ios::binary` must be set during the creation of the `ofstream`. \tparam PointRange is a model of `ConstRange`. The value type of its iterator is the key type of the named parameter `point_map`. diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index d8ce7a9c2488..40248018cd38 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -371,8 +371,8 @@ bool read_MEDIT(std::istream& is, * edge curve index to edge reference, * and vertex corner index to vertex reference. * - * \attention Currently only tetrahedral meshes are supported. - * \attention The cell soup is not cleared, and the data from the stream are appended. + * \note Currently only tetrahedral meshes are supported. + * \note The cell soup is not cleared, and the data from the stream are appended. * * \tparam PointRange a model of the concept `BackInsertionSequence` whose value type is the point type * \tparam CellRange a model of the concept `BackInsertionSequence` whose `value_type` is `std::array` @@ -485,7 +485,7 @@ bool read_MEDIT(std::istream& is, * edge curve index to edge reference, * and vertex corner index to vertex reference. - * \attention Currently only tetrahedral meshes are supported. + * \note Currently only tetrahedral meshes are supported. * * \tparam PointRange a model of the concept `ConstRange` whose value type is the point type * \tparam CellRange a model of the concept `ConstRange` diff --git a/Stream_support/include/CGAL/IO/OBJ.h b/Stream_support/include/CGAL/IO/OBJ.h index 4877651fe0ac..74e1be293e65 100644 --- a/Stream_support/include/CGAL/IO/OBJ.h +++ b/Stream_support/include/CGAL/IO/OBJ.h @@ -305,7 +305,7 @@ bool read_OBJ(std::istream& is, * * \brief reads the content of `is` into `points` and `polygons`, using the \ref IOStreamOBJ. * - * \attention The polygon soup is not cleared, and the data from the stream are appended. + * \note The polygon soup is not cleared, and the data from the stream are appended. * * \tparam PointRange a model of the concept `BackInsertionSequence` whose value type is the point type * \tparam PolygonRange a model of the concept `BackInsertionSequence` whose `value_type` is @@ -355,7 +355,7 @@ bool read_OBJ(std::istream& is, * * \brief reads the content of the file `fname` into `points` and `polygons`, using the \ref IOStreamOBJ. * - * \attention The polygon soup is not cleared, and the data from the file are appended. + * \note The polygon soup is not cleared, and the data from the file are appended. * * \tparam PointRange a model of the concept `BackInsertionSequence` whose value type is the point type. * \tparam PolygonRange a model of the concept `BackInsertionSequence` whose `value_type` is diff --git a/Stream_support/include/CGAL/IO/PLY.h b/Stream_support/include/CGAL/IO/PLY.h index ad87a6d670a7..ce9db4ec8fe7 100644 --- a/Stream_support/include/CGAL/IO/PLY.h +++ b/Stream_support/include/CGAL/IO/PLY.h @@ -273,9 +273,9 @@ bool read_PLY(std::istream& is, * * \brief reads the content of `is` into `points` and `polygons`, using the \ref IOStreamPLY. * - * \attention The polygon soup is not cleared, and the data from the stream are appended. + * \note The polygon soup is not cleared, and the data from the stream are appended. * - * \attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. + * \note To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. * * \tparam PointRange a model of the concept `BackInsertionSequence` whose value type is the point type * \tparam PolygonRange a model of the concept `BackInsertionSequence` whose `value_type` is @@ -349,7 +349,7 @@ bool read_PLY(std::istream& is, * * \brief reads the content of `fname` into `points` and `polygons`, using the \ref IOStreamPLY. * - * \attention The polygon soup is not cleared, and the data from the file are appended. + * \note The polygon soup is not cleared, and the data from the file are appended. * * \tparam PointRange a model of the concept `BackInsertionSequence` whose value type is the point type. * \tparam PolygonRange a model of the concept `BackInsertionSequence` whose `value_type` is @@ -431,7 +431,7 @@ bool read_PLY(const std::string& fname, * * \brief writes the content of `points` and `polygons` in `out`, using the \ref IOStreamPLY. * - * \attention To write to a binary file, the flag `std::ios::binary` must be set during the creation + * \note To write to a binary file, the flag `std::ios::binary` must be set during the creation * of the `ofstream`, and the \link PkgStreamSupportEnumRef `IO::Mode` \endlink * of the stream must be set to `BINARY`. * @@ -644,7 +644,7 @@ make_ply_normal_reader(VectorMap normal_map); second element of the tuple should be a functor that constructs the value type of `PropertyMap` from N objects of types `T`. - \attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. + \note To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. \tparam OutputIteratorValueType type of objects that can be put in `PointOutputIterator`. It must be a model of `DefaultConstructible` and defaults to `value_type_traits::%type`. @@ -675,7 +675,7 @@ bool read_PLY_with_properties(std::istream& is, Potential additional point properties and faces are ignored. - \attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. + \note To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. \tparam OutputIteratorValueType type of objects that can be put in `PointOutputIterator`. It must be a model of `DefaultConstructible` and defaults to `value_type_traits::%type`. @@ -839,7 +839,7 @@ bool read_PLY(const std::string& fname, be provided for `PropertyMap::value_type` that handles both ASCII and binary output (see `CGAL::IO::get_mode()`). - \attention To write to a binary file, the flag `std::ios::binary` must be set during the creation + \note To write to a binary file, the flag `std::ios::binary` must be set during the creation of the `ofstream`, and the \link PkgStreamSupportEnumRef `IO::Mode` \endlink of the stream must be set to `BINARY`. @@ -867,7 +867,7 @@ template Date: Wed, 7 Oct 2026 10:07:42 +0200 Subject: [PATCH 48/72] Apply batched suggestions from code review Co-authored-by: Mael --- Stream_support/include/CGAL/IO/MEDIT.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 40248018cd38..71b77045886d 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -371,7 +371,7 @@ bool read_MEDIT(std::istream& is, * edge curve index to edge reference, * and vertex corner index to vertex reference. * - * \note Currently only tetrahedral meshes are supported. + * \note Currently, only tetrahedral cells are supported. * \note The cell soup is not cleared, and the data from the stream are appended. * * \tparam PointRange a model of the concept `BackInsertionSequence` whose value type is the point type @@ -485,7 +485,7 @@ bool read_MEDIT(std::istream& is, * edge curve index to edge reference, * and vertex corner index to vertex reference. - * \note Currently only tetrahedral meshes are supported. + * \note Currently only tetrahedral cells are supported. * * \tparam PointRange a model of the concept `ConstRange` whose value type is the point type * \tparam CellRange a model of the concept `ConstRange` From 67329bcd542c34fed98f9185ccebb6e2f1e8c7f3 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 7 Oct 2026 09:37:48 +0100 Subject: [PATCH 49/72] Fix vertices_with_corner_index --- Stream_support/include/CGAL/IO/MEDIT.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 71b77045886d..a754503cbf64 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -522,9 +522,10 @@ bool read_MEDIT(std::istream& is, * * \cgalParamNBegin{vertices_with_corner_index} * \cgalParamDescription{a const reference wrapper of a container of pair of integers that will be written by this function. - * Each element corresponds to a corner at the vertex corresponding to the first integer, the second integer being the corner index.} + * Each element corresponds to a corner at the vertex corresponding to the first integer, the second integer being the corner index. + * For vertices not in the container, the corner index is set to `0`.} * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the pairs can be accessed with `std::get()`} - * \cgalParamDefault{vertices are not written} + * \cgalParamDefault{corners are not written} * \cgalParamNEnd * * \cgalNamedParamsEnd From 0bb9923698d792eb50d2a530dcdeefb29f37f256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 7 Oct 2026 20:28:42 +0200 Subject: [PATCH 50/72] fix errors --- .../examples/Linear_cell_complex/tetsoup_to_lcc.cpp | 2 +- .../include/CGAL/Periodic_3_mesh_3/IO/File_medit.h | 2 +- Stream_support/include/CGAL/IO/MEDIT.h | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Linear_cell_complex/examples/Linear_cell_complex/tetsoup_to_lcc.cpp b/Linear_cell_complex/examples/Linear_cell_complex/tetsoup_to_lcc.cpp index e64dc5072c91..a29ec0714ce6 100644 --- a/Linear_cell_complex/examples/Linear_cell_complex/tetsoup_to_lcc.cpp +++ b/Linear_cell_complex/examples/Linear_cell_complex/tetsoup_to_lcc.cpp @@ -24,7 +24,7 @@ int main(int argc, char** argv) return 1; } - CGAL::IO::read_MEDIT(in, points, tetras, CGAL::parameters::subdomains(std::ref(subdomains))); + CGAL::IO::read_MEDIT(in, points, tetras, CGAL::parameters::subdomain_indices(std::ref(subdomains))); //filter out subdomain 0 std::vector> filtered_tetras; 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 a16d9872e198..773c9a25835c 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 @@ -305,7 +305,7 @@ void output_to_medit(std::ostream& os, Cell_pmap cell_pmap(c3t3); Facet_pmap facet_pmap(c3t3, cell_pmap); Facet_pmap_twice facet_pmap_twice(c3t3, cell_pmap); - Vertex_pmap vertex_pmap(c3t3, cell_pmap, facet_pmap); + Vertex_pmap vertex_pmap(c3t3); Periodic_3_mesh_3::output_to_medit(os, c3t3, occurrence_count, distinguish_copies, vertex_pmap, facet_pmap, cell_pmap, facet_pmap_twice); diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index a754503cbf64..42daaf6137d8 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -192,7 +192,7 @@ bool read_MEDIT(std::istream& is, return false; } points.emplace_back(x,y,z); - if(ref != 0){ + if(read_vertices_with_corner_index && ref != 0){ vertices_with_corner_index.push_back({offset + i, ref}); } } @@ -289,6 +289,7 @@ bool read_MEDIT(std::istream& is, if(line.find("Corners") != std::string::npos) { + // TODO: are we sure we always ignore the info? is >> nvertices; std::string buffer; for(int i=0; i::value; + constexpr bool is_edges_with_curve_index_map = !parameters::is_default_parameter::value; constexpr bool is_vertices_with_corner_index_map = !parameters::is_default_parameter::value; @@ -469,7 +471,7 @@ bool read_MEDIT(std::istream& is, return internal::read_MEDIT(is, points, cells, subdomain_indices, facets_with_patch_index, is_facets_with_patch_index_map, - edges_with_curve_index, is_facets_with_patch_index_map, + edges_with_curve_index, is_edges_with_curve_index_map, vertices_with_corner_index, is_vertices_with_corner_index_map, verbose, is_CGAL_mesh); } From c653411de92f2e962970c35fc5066ca1336f1a76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 7 Oct 2026 20:33:33 +0200 Subject: [PATCH 51/72] fix another error --- SMDS_3/include/CGAL/IO/File_tetgen.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SMDS_3/include/CGAL/IO/File_tetgen.h b/SMDS_3/include/CGAL/IO/File_tetgen.h index 407b2a539264..a0afb6159a78 100644 --- a/SMDS_3/include/CGAL/IO/File_tetgen.h +++ b/SMDS_3/include/CGAL/IO/File_tetgen.h @@ -45,7 +45,7 @@ output_to_tetgen(std::string filename, Cell_pmap cell_pmap(c3t3); Facet_pmap facet_pmap(c3t3,cell_pmap); Facet_pmap_twice facet_pmap_twice(c3t3,cell_pmap); - Vertex_pmap vertex_pmap(c3t3,cell_pmap,facet_pmap); + Vertex_pmap vertex_pmap(c3t3); output_to_tetgen(filename, c3t3, From f3eb5f8c11539b814fe9ce307a5d6c3bafd4dd71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 7 Oct 2026 20:48:48 +0200 Subject: [PATCH 52/72] workaround warnings --- Stream_support/include/CGAL/IO/MEDIT.h | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 42daaf6137d8..451ef5f9ef33 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -42,6 +42,30 @@ struct Facet_with_patch_index SurfacePatchIndex surface_patch_index; }; +template +struct get_surface_path_index_type +{ + using type = int; +}; + +template +struct get_surface_path_index_type> +{ + using type = SurfacePatchIndex; +}; + +template +struct get_surface_path_index_type> +{ + using type = I; +}; + +template +struct get_surface_path_index_type> +{ + using type = I; +}; + template struct Edge_with_curve_index { @@ -210,7 +234,7 @@ bool read_MEDIT(std::istream& is, for(int i=0; i::value_type>::type surface_patch_id; if(!(is >> n[0] >> n[1] >> n[2] >> surface_patch_id)) { if(verbose) From 89baa30905e829a55afd7480bccb9e08dc49de09 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 8 Oct 2026 09:43:08 +0100 Subject: [PATCH 53/72] typo --- .../include/CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PMP_Mesh_repair/include/CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h b/PMP_Mesh_repair/include/CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h index 6789ac6a9ca2..2a0a10867d2a 100644 --- a/PMP_Mesh_repair/include/CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h +++ b/PMP_Mesh_repair/include/CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h @@ -71,7 +71,7 @@ namespace IO { * \cgalParamNEnd * * \cgalParamNBegin{repair_polygon_soup} - * \cgalParamDescription{a parameter used indicate whether `CGAL::Polygon_mesh_processing::repair_polygon_soup()` + * \cgalParamDescription{a parameter used to indicate whether `CGAL::Polygon_mesh_processing::repair_polygon_soup()` * should be called on the intermediate polygon soup.} * \cgalParamType{Boolean} * \cgalParamDefault{`true`} From 5be0c56e7fe849c0baf4b5d788bcfd23e5dd268a Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 8 Oct 2026 14:59:57 +0100 Subject: [PATCH 54/72] Only what is in Corners is a corner --- Stream_support/include/CGAL/IO/MEDIT.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 451ef5f9ef33..a49b36b33fdb 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -162,6 +162,7 @@ bool read_MEDIT(std::istream& is, int dim; int nv, nf, ntet, ref, nvertices, nedges, nridges; int offset = static_cast(points.size()); + std::vector refs; std::string word; is >> word >> dim; // MeshVersionFormatted 1 @@ -216,9 +217,7 @@ bool read_MEDIT(std::istream& is, return false; } points.emplace_back(x,y,z); - if(read_vertices_with_corner_index && ref != 0){ - vertices_with_corner_index.push_back({offset + i, ref}); - } + refs.emplace_back(ref); } } @@ -313,11 +312,14 @@ bool read_MEDIT(std::istream& is, if(line.find("Corners") != std::string::npos) { - // TODO: are we sure we always ignore the info? is >> nvertices; - std::string buffer; - for(int i=0; i> ci; + if(read_vertices_with_corner_index){ + vertices_with_corner_index.push_back({offset + i, refs[ci-1]}); + } + } } if(line.find("Edges") != std::string::npos) From 4cde78121214df60c671d54ee43026e1d7739db1 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 9 Oct 2026 09:37:29 +0100 Subject: [PATCH 55/72] WIP: Change the low level function. test_MEDIT passes, SMDS will be next --- Installation/CHANGES.md | 2 - SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h | 1 + .../internal/parameters_interface.h | 7 +- .../File_formats/Supported_file_formats.txt | 4 +- .../doc/Stream_support/IOstream.txt | 4 +- Stream_support/include/CGAL/IO/MEDIT.h | 256 ++++++++++-------- .../test/Stream_support/test_MEDIT.cpp | 70 ++--- 7 files changed, 181 insertions(+), 163 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index dbec2151eeb3..9ebef6ac55ea 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -73,8 +73,6 @@ Release date: December 2026 `is_face_valued` and `face_value` (with `face_value_name` for the legend). As an example, the surface mesh drawer exposes the aspect ratio of each face. - - ## [Release 6.2](https://github.com/CGAL/cgal/releases/tag/v6.2) Release date: June 2026 diff --git a/SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h b/SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h index 75cb2cb23b39..a6eea92dcd0a 100644 --- a/SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h +++ b/SMDS_3/include/CGAL/SMDS_3/tet_soup_to_c3t3.h @@ -698,6 +698,7 @@ bool build_triangulation_with_subdomains_range(Tr& tr, allow_negative_orientation); } + } // namespace SMDS_3 } // namespace CGAL diff --git a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h index 4f090205e29b..6f58d44aad14 100644 --- a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h +++ b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h @@ -69,9 +69,10 @@ CGAL_add_named_parameter(stream_precision_t, stream_precision, stream_precision) CGAL_add_named_parameter(read_only_one_object_t, read_only_one_object, read_only_one_object) // List of named parameters that we use in the package 'Stream_support' -CGAL_add_named_parameter(facets_with_patch_index_t, facets_with_patch_index, facets_with_patch_index) -CGAL_add_named_parameter(edges_with_curve_index_t, edges_with_curve_index, edges_with_curve_index) -CGAL_add_named_parameter(vertices_with_corner_index_t, vertices_with_corner_index, vertices_with_corner_index) +CGAL_add_named_parameter(tetrahedra_t, tetrahedra, tetrahedra) +CGAL_add_named_parameter(edges_t, edges, edges) +CGAL_add_named_parameter(ridges_t, ridges, ridges) +CGAL_add_named_parameter(corners_t, corners, corners) // List of named parameters that we use in the package 'Mesh_3' diff --git a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt index 139a1d1d76aa..5d8a52ce83f8 100644 --- a/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt +++ b/Stream_support/doc/Stream_support/File_formats/Supported_file_formats.txt @@ -558,8 +558,8 @@ The following \cgal data structures can be exported into the `.mesh` file format \link CGAL::IO::write_MEDIT(std::ostream &os, const CGAL::Conforming_constrained_Delaunay_triangulation_3< Traits, Tr > &ccdt, const NamedParameters& np) `CGAL::IO::write_MEDIT()` \endlink. The following function enables to read and write a tetrahedron soup -- \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, CellRange&, const NamedParameters&) `CGAL::IO::read_MEDIT()` \endlink -- \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const CellRange&, const NamedParameters&) `CGAL::IO::writeMEDIT()` \endlink +- \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, const NamedParameters&) `CGAL::IO::read_MEDIT()` \endlink +- \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const NamedParameters&) `CGAL::IO::writeMEDIT()` \endlink \section IOStreamTetgen Tetgen File Format diff --git a/Stream_support/doc/Stream_support/IOstream.txt b/Stream_support/doc/Stream_support/IOstream.txt index 5bc8450ce2f5..44d270c89fc9 100644 --- a/Stream_support/doc/Stream_support/IOstream.txt +++ b/Stream_support/doc/Stream_support/IOstream.txt @@ -505,8 +505,8 @@ which can perform some combinatorial repairing to ensure the input data is a 2-m \ref IOStreamMedit "MEDIT" - \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, CellRange&, const NamedParameters&) `CGAL::IO::read_MEDIT()` \endlink - \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const CellRange&, const NamedParameters&) `CGAL::IO::write_MEDIT()` \endlink + \link CGAL::IO::read_MEDIT(std::istream&, PointRange&, const NamedParameters&) `CGAL::IO::read_MEDIT()` \endlink + \link CGAL::IO::write_MEDIT(std::ostream&, const PointRange&, const NamedParameters&) `CGAL::IO::write_MEDIT()` \endlink diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index a49b36b33fdb..84eefaf6f669 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -36,7 +36,7 @@ namespace IO { namespace internal { template -struct Facet_with_patch_index +struct Facet { int v0, v1, v2; SurfacePatchIndex surface_patch_index; @@ -49,7 +49,7 @@ struct get_surface_path_index_type }; template -struct get_surface_path_index_type> +struct get_surface_path_index_type> { using type = SurfacePatchIndex; }; @@ -67,7 +67,7 @@ struct get_surface_path_index_type> }; template -struct Edge_with_curve_index +struct Edge { int v0, v1; CurveIndex curve_index; @@ -116,45 +116,47 @@ CornerIndex get_one(const Vertex_with_corner_index& t) } template -int get_zero(const Edge_with_curve_index& t) +int get_zero(const Edge& t) { return t.v0; } template -int get_one(const Edge_with_curve_index& t) +int get_one(const Edge& t) { return t.v1; } template -CurveIndex get_two(const Edge_with_curve_index& t) +CurveIndex get_two(const Edge& t) { return t.curve_index; } -template // either Vertex_with_corner_index or a tuple/pair/array +template // either Vertex_with_corner_index or a tuple/pair/array bool read_MEDIT(std::istream& is, - PointRange& points, - CellRange& cells, - std::vector& subdomain_indices, - FacetWithIndexRange& facets_with_patch_index, - bool read_facets_with_patch_index, - EdgeWithIndexRange& edges_with_curve_index, - bool read_edges_with_curve_index, - VertexWithCornerIndexRange& vertices_with_corner_index, - bool read_vertices_with_corner_index, + PointWithIndexRange& points, + CellWithIndexRange& cells, + FacetWithIndexRange& facets, + bool read_facets, + EdgeWithIndexRange& edges, + bool read_edges, + RidgeRange& ridges, + bool read_ridges, + CornerRange& corners, + bool read_corners, bool verbose, bool& is_CGAL_mesh) { - using Point_3 = typename PointRange::value_type; + using Point_3 = typename PointWithIndexRange::value_type::first_type; using FT = typename Kernel_traits::Kernel::FT; using Facet = std::array; - using Cell_with_ref = typename std::iterator_traits::value_type; + using Cell_with_ref = typename std::iterator_traits::value_type; if(!is) return false; @@ -162,7 +164,6 @@ bool read_MEDIT(std::istream& is, int dim; int nv, nf, ntet, ref, nvertices, nedges, nridges; int offset = static_cast(points.size()); - std::vector refs; std::string word; is >> word >> dim; // MeshVersionFormatted 1 @@ -216,16 +217,15 @@ bool read_MEDIT(std::istream& is, std::cerr << "Issue while reading vertices" << std::endl; return false; } - points.emplace_back(x,y,z); - refs.emplace_back(ref); + points.emplace_back(std::make_pair(Point_3(x,y,z),ref)); } } if(line.find("Triangles") != std::string::npos) { - if(read_facets_with_patch_index){ + if(read_facets){ is >> nf; - CGAL::internal::reserve(facets_with_patch_index, nf); + CGAL::internal::reserve(facets, nf); if(verbose) std::cerr << "Reading "<< nf << " triangles" << std::endl; @@ -261,7 +261,7 @@ bool read_MEDIT(std::istream& is, { std::rotate(std::begin(facet), std::next(std::begin(facet)), std::end(facet)); } - facets_with_patch_index.push_back({facet[0], facet[1], facet[2], surface_patch_id}); + facets.push_back({facet[0], facet[1], facet[2], surface_patch_id}); } }else{ is >> nf; @@ -304,9 +304,9 @@ bool read_MEDIT(std::istream& is, t[1] = offset + n[1] - 1; t[2] = offset + n[2] - 1; t[3] = offset + n[3] - 1; + t[4] = reference; cells.push_back(t); - subdomain_indices.push_back(reference); } } @@ -316,17 +316,17 @@ bool read_MEDIT(std::istream& is, int ci; for(int i=0; i> ci; - if(read_vertices_with_corner_index){ - vertices_with_corner_index.push_back({offset + i, refs[ci-1]}); + if(read_corners){ + corners.push_back(offset + i); } } } if(line.find("Edges") != std::string::npos) { - if(read_edges_with_curve_index){ + if(read_edges){ is >> nedges; - CGAL::internal::reserve(edges_with_curve_index, nedges); + CGAL::internal::reserve(edges, nedges); if(verbose) std::cerr << "Reading "<< nedges << " edges" << std::endl; @@ -344,8 +344,8 @@ bool read_MEDIT(std::istream& is, std::cerr << "Issue while reading edges" << std::endl; return false; } - edges_with_curve_index.push_back({offset + n[0] - 1, offset + n[1] - 1, curve_index}); - CGAL_assertion(edges_with_curve_index.size() == static_cast(i + 1)); + edges.push_back({offset + n[0] - 1, offset + n[1] - 1, curve_index}); + CGAL_assertion(edges.size() == static_cast(i + 1)); } } else @@ -359,9 +359,13 @@ bool read_MEDIT(std::istream& is, if(line.find("Ridges") != std::string::npos) { is >> nridges; - std::string buffer; - for(int i=0; i> ci; + if(read_ridges){ + ridges.push_back(offset + i); + } + } } } @@ -371,16 +375,15 @@ bool read_MEDIT(std::istream& is, { std::cout << points.size() - std::size_t(offset) << " points" << std::endl; std::cout << cells.size() << " cells" << std::endl; - std::cout << facets_with_patch_index.size() << " border facets" << std::endl; - std::cout << edges_with_curve_index.size() << " edges" << std::endl; - std::cout << vertices_with_corner_index.size() << " vertices" << std::endl; + std::cout << facets.size() << " facets" << std::endl; + std::cout << edges.size() << " edges" << std::endl; + std::cout << ridges.size() << " ridges" << std::endl; + std::cout << corners.size() << " corners" << std::endl; } if(cells.empty()) return false; - CGAL_assertion(cells.size() == subdomain_indices.size()); - return true; } @@ -391,7 +394,7 @@ bool read_MEDIT(std::istream& is, /*! * \ingroup PkgStreamSupportIoFuncsMEDIT * - * \brief reads the content of `is` into `points` and `cells` using the \ref IOStreamMedit. + * \brief reads the content of `is` into `points` and the named parameters using the \ref IOStreamMedit. * * The subdomain index corresponds to what \medit calls cell reference, * facet patch index corresponds to triangle reference, @@ -402,39 +405,45 @@ bool read_MEDIT(std::istream& is, * \note The cell soup is not cleared, and the data from the stream are appended. * * \tparam PointRange a model of the concept `BackInsertionSequence` whose value type is the point type - * \tparam CellRange a model of the concept `BackInsertionSequence` whose `value_type` is `std::array` * * \param is the input stream * \param points points of the soup of cells - * \param cells a range where each element is a cell described by indices into `points` * * \param np optional \ref bgl_namedparameters "Named Parameters" described below * * \cgalNamedParamsBegin * - * \cgalParamNBegin{subdomain_indices} - * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. - * Each element in the container indicates the subdomain index of the corresponding cell at the same position.} - * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` able to store `int`.} - * \cgalParamDefault{subdomain_indices are ignored} + * + * \cgalParamNBegin{tetrahedra} + * \cgalParamDescription{a non-const reference wrapper of a container of quintuples of integers that will be filled by this function. + * Each element represents a tetrahedron with vertices corresponding to the first four integers, and the last integer being the subdomin index of the tetrahedron.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of five integers.} + * \cgalParamDefault{facets are ignored} * \cgalParamNEnd * - * \cgalParamNBegin{facets_with_patch_index} + * \cgalParamNBegin{facets} * \cgalParamDescription{a non-const reference wrapper of a container of quadruples of integers that will be filled by this function. * Each element represents a facet with vertices corresponding to the first three integers, and the last integer being the surface patch index of the facet.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of four integers.} * \cgalParamDefault{facets are ignored} * \cgalParamNEnd * - * \cgalParamNBegin{edges_with_curve_index} + * \cgalParamNBegin{edges} * \cgalParamDescription{a non-const reference wrapper of a container of triples of integers that will be filled by this function. * Each element represents an edge with vertices corresponding to the first two integers, and the last integer being the curve index of the edge.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of three integers.} * \cgalParamDefault{edges are ignored} * \cgalParamNEnd * - * \cgalParamNBegin{vertices_with_corner_index} - * \cgalParamDescription{a non-const reference wrapper of a container of pair of integers that will be filled by this function. + * \cgalParamNBegin{ridges} + * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. + * Each element in the container indicates the subdomain index of the corresponding cell at the same position.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` able to store `int`.} + * \cgalParamDefault{ridges are ignored} + * \cgalParamNEnd + * + * \cgalParamNBegin{corners} + * \cgalParamDescription{a non-const reference wrapper of a container of pairs of integers that will be filled by this function. * Each element represents a corner at the vertex corresponding to the first integer, and the last integer being the corner index.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of two integers.} * \cgalParamDefault{vertices are ignored} @@ -453,10 +462,9 @@ bool read_MEDIT(std::istream& is, * \see \ref IOStreamMedit */ -template +template bool read_MEDIT(std::istream& is, PointRange& points, - CellRange& cells, const CGAL_NP_CLASS& np = parameters::default_values()) { using parameters::choose_parameter; @@ -465,40 +473,48 @@ bool read_MEDIT(std::istream& is, const bool verbose = choose_parameter(get_parameter(np, internal_np::verbose), false); - // subdomain_indices - std::vector default_subdomain_indices; - using Subdomains = typename internal_np::Lookup_named_param_def>::reference; - Subdomains subdomain_indices = choose_parameter(get_parameter_reference(np, internal_np::subdomain_indices), default_subdomain_indices); + // cells + std::vector> default_tetrahedra; + using Tetrahedra = typename internal_np::Lookup_named_param_def>>::reference; + Tetrahedra tetrahedra = choose_parameter(get_parameter_reference(np, internal_np::tetrahedra), default_tetrahedra); - // facets - std::vector> default_facets_with_patch_index; - using Facets_with_patch_index = typename internal_np::Lookup_named_param_def>>::reference; - Facets_with_patch_index facets_with_patch_index = choose_parameter(get_parameter_reference(np, internal_np::facets_with_patch_index), default_facets_with_patch_index); + // triangles + std::vector> default_triangles; + using Triangles = typename internal_np::Lookup_named_param_def>>::reference; + Triangles triangles = choose_parameter(get_parameter_reference(np, internal_np::triangles), default_triangles); // edges - std::vector> default_edges_with_curve_index; - using Edges_with_curve_index = typename internal_np::Lookup_named_param_def>>::reference; - Edges_with_curve_index edges_with_curve_index = choose_parameter(get_parameter_reference(np, internal_np::edges_with_curve_index), default_edges_with_curve_index); + std::vector> default_edges; + using Edges = typename internal_np::Lookup_named_param_def>>::reference; + Edges edges = choose_parameter(get_parameter_reference(np, internal_np::edges), default_edges); - // vertices - std::vector> default_vertices_with_corner_index; - using Vertices_with_corner_index = typename internal_np::Lookup_named_param_def>>::reference; - Vertices_with_corner_index vertices_with_corner_index = choose_parameter(get_parameter_reference(np, internal_np::vertices_with_corner_index), default_vertices_with_corner_index); + // ridges + std::vector default_ridges; + using Ridges = typename internal_np::Lookup_named_param_def>::reference; + Ridges ridges = choose_parameter(get_parameter_reference(np, internal_np::ridges), default_ridges); + // corners + std::vector> default_corners; + using Corners = typename internal_np::Lookup_named_param_def>>::reference; + Corners corners = choose_parameter(get_parameter_reference(np, internal_np::corners), default_corners); - constexpr bool is_facets_with_patch_index_map = !parameters::is_default_parameter::value; + constexpr bool is_triangles_map = !parameters::is_default_parameter::value; - constexpr bool is_edges_with_curve_index_map = !parameters::is_default_parameter::value; + constexpr bool is_edges_map = !parameters::is_default_parameter::value; + + constexpr bool is_ridges_map = !parameters::is_default_parameter::value; + + constexpr bool is_corners_map = !parameters::is_default_parameter::value; - constexpr bool is_vertices_with_corner_index_map = !parameters::is_default_parameter::value; bool is_CGAL_mesh; - return internal::read_MEDIT(is, points, cells, subdomain_indices, - facets_with_patch_index, is_facets_with_patch_index_map, - edges_with_curve_index, is_edges_with_curve_index_map, - vertices_with_corner_index, is_vertices_with_corner_index_map, + return internal::read_MEDIT(is, points, tetrahedra, + triangles, is_triangles_map, + edges, is_edges_map, + ridges, is_ridges_map, + corners, is_corners_map, verbose, is_CGAL_mesh); } @@ -527,31 +543,30 @@ bool read_MEDIT(std::istream& is, * \param np optional \ref bgl_namedparameters "Named Parameters" described below * * \cgalNamedParamsBegin - * \cgalParamNBegin{subdomain_indices} + * \cgalParamNBegin{ridges} * \cgalParamDescription{a const reference wrapper of a container of integers of the same size as `cells`. * Each element in the container indicates the subdomain index of the corresponding cell at the same position.} * \cgalParamType{a `std::reference_wrapper` to a model of the concept `SequenceContainer` of integer.} * \cgalParamDefault{all cells will be given the subdomain index `1`.} * \cgalParamNEnd * - * \cgalParamNBegin{facets_with_patch_index} + * \cgalParamNBegin{facets} * \cgalParamDescription{a const reference wrapper of a container of quadruples of integers that will be written by this function. * Each element corresponds to a facet with vertices corresponding to the three first integers, and the last integer being the surface patch index of the facet.} * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the quadruples can be accessed with `std::get()`} * \cgalParamDefault{facets are not written} * \cgalParamNEnd * - * \cgalParamNBegin{edges_with_curve_index} + * \cgalParamNBegin{edges} * \cgalParamDescription{a const reference wrapper of a container of triples of integers that will be written by this function. * Each element corresponds to an edge with vertices corresponding to the two first integers, and the last integer being the curve index of the edge.} * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the triples can be accessed with `std::get()`} * \cgalParamDefault{edges are not written} * \cgalParamNEnd * - * \cgalParamNBegin{vertices_with_corner_index} - * \cgalParamDescription{a const reference wrapper of a container of pair of integers that will be written by this function. - * Each element corresponds to a corner at the vertex corresponding to the first integer, the second integer being the corner index. - * For vertices not in the container, the corner index is set to `0`.} + * \cgalParamNBegin{corners} + * \cgalParamDescription{a const reference wrapper of a container of pairs of integers that will be written by this function. + * Each element corresponds to a corner at the vertex corresponding to the first integer, the second integer being the corner index.} * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the pairs can be accessed with `std::get()`} * \cgalParamDefault{corners are not written} * \cgalParamNEnd @@ -562,13 +577,12 @@ bool read_MEDIT(std::istream& is, * * \see \ref IOStreamMedit */ -template +template bool write_MEDIT(std::ostream& os, const PointRange& points, - const CellRange& cells, const CGAL_NP_CLASS& np = parameters::default_values() #ifndef DOXYGEN_RUNNING - , std::enable_if_t>* = nullptr + , std::enable_if_t>* = nullptr #endif ) @@ -583,38 +597,36 @@ bool write_MEDIT(std::ostream& os, if(!os) return false; - // subdomain_indices - std::vector default_subdomain_indices; - std::vector> default_vertices; + + std::vector default_ridges; + std::vector default_corners; std::vector> default_edges; std::vector> default_facets; + std::vector> default_cells; - using Subdomains = typename internal_np::Lookup_named_param_def>::reference; - Subdomains subdomain_indices = choose_parameter(get_parameter_reference(np, internal_np::subdomain_indices), default_subdomain_indices); + using Cells = typename internal_np::Lookup_named_param_def>>::reference; + Cells cells = choose_parameter(get_parameter_reference(np, internal_np::tetrahedra), default_cells); - using Vertices_with_corner_index = typename internal_np::Lookup_named_param_def>>::reference; - Vertices_with_corner_index vertices = choose_parameter(get_parameter_reference(np, internal_np::vertices_with_corner_index), default_vertices); + using Facets = typename internal_np::Lookup_named_param_def>>::reference; + Facets facets = choose_parameter(get_parameter_reference(np, internal_np::triangles), default_facets); - using Edges_with_curve_index = typename internal_np::Lookup_named_param_def>>::reference; - Edges_with_curve_index edges = choose_parameter(get_parameter_reference(np, internal_np::edges_with_curve_index), default_edges); + using Edges = typename internal_np::Lookup_named_param_def>>::reference; + Edges edges = choose_parameter(get_parameter_reference(np, internal_np::edges), default_edges); - using Facets_with_patch_index = typename internal_np::Lookup_named_param_def>>::reference; - Facets_with_patch_index facets = choose_parameter(get_parameter_reference(np, internal_np::facets_with_patch_index), default_facets); + using Ridges = typename internal_np::Lookup_named_param_def>::reference; + Ridges ridges = choose_parameter(get_parameter_reference(np, internal_np::ridges), default_ridges); + + using corners = typename internal_np::Lookup_named_param_def>>::reference; + corners vertices = choose_parameter(get_parameter_reference(np, internal_np::corners), default_corners); - std::map vertex_corner_index_map; - for(const auto& c : vertices){ - vertex_corner_index_map[internal::get_zero(c) + 1] = internal::get_one(c); - } os << "MeshVersionFormatted 1\nDimension 3\n"; os << "Vertices\n"; os << points.size() << "\n"; - for (int i = 0; i < static_cast(points.size()); ++i){ - const Point_3& p = points[i]; - std::map::iterator it = vertex_corner_index_map.find(i + 1); - int corner_index = (it != vertex_corner_index_map.end()) ? it->second : 0; - os << p << " " << corner_index << "\n"; + for (const auto& p : points){ + + os << p.first << " " << p.second << "\n"; } os << "Tetrahedra\n"; @@ -624,17 +636,8 @@ bool write_MEDIT(std::ostream& os, os << cells[k][0]+1 << " " << cells[k][1]+1 << " " << cells[k][2]+1 << " " - << cells[k][3]+1 << " "; - if constexpr (is_default_parameter::value) - os << 1 << "\n"; - else - os << subdomain_indices[k] << "\n"; - } - - if(!vertices.empty()){ - os << "Corners\n" << vertices.size() << "\n"; - for(const auto& c : vertices) - os << internal::get_zero(c) + 1 << "\n"; + << cells[k][3]+1 << " " + << cells[k][4] << "\n"; } if(!edges.empty()){ @@ -652,6 +655,19 @@ bool write_MEDIT(std::ostream& os, for(const auto& f : facets) os << std::get<0>(f) +1 << " " << std::get<1>(f) + 1 << " " << std::get<2>(f) + 1 << " " << std::get<3>(f) << "\n"; } + + if(!vertices.empty()){ + os << "Corners\n" << vertices.size() << "\n"; + for(const auto& c : vertices) + os << c + 1 << "\n"; + } + + if(!ridges.empty()){ + os << "Ridges\n" << ridges.size() << "\n"; + for(const auto& r : ridges) + os << r + 1 << "\n"; + } + os <<"End\n"; return true; } diff --git a/Stream_support/test/Stream_support/test_MEDIT.cpp b/Stream_support/test/Stream_support/test_MEDIT.cpp index ae814c58316c..e104f03f0dfd 100644 --- a/Stream_support/test/Stream_support/test_MEDIT.cpp +++ b/Stream_support/test/Stream_support/test_MEDIT.cpp @@ -14,46 +14,48 @@ typedef Kernel::Point_3 Point_3; int main() { const std::string filename = "./data/polyhedral_complex.mesh"; std::ifstream input(filename); - std::vector points; - std::vector> cells; - std::vector subdomains; - std::vector> edges; - std::vector> facets; - std::deque> corners; - bool verbose = false; - bool success = CGAL::IO::read_MEDIT(input, points, cells, CGAL::parameters::subdomain_indices(std::ref(subdomains)) - .facets_with_patch_index(std::ref(facets)) - .edges_with_curve_index(std::ref(edges)) - .vertices_with_corner_index(std::ref(corners)) - .verbose(verbose)); + std::vector> points_with_ref; + std::vector> cells_with_ref; + std::vector> edges_with_ref; + std::vector> facets_with_ref; + std::vector ridges; + std::deque corners; + bool success = CGAL::IO::read_MEDIT(input, points_with_ref, CGAL::parameters::tetrahedra(std::ref(cells_with_ref)) + .triangles(std::ref(facets_with_ref)) + .edges(std::ref(edges_with_ref)) + .ridges(std::ref(ridges)) + .corners(std::ref(corners)) + .verbose(false)); assert(success); std::ostringstream output; output.precision(17); - CGAL::IO::write_MEDIT(output, points, cells, CGAL::parameters::subdomain_indices(std::cref(subdomains)) - .facets_with_patch_index(std::cref(facets)) - .edges_with_curve_index(std::cref(edges)) - .vertices_with_corner_index(std::cref(corners))); + CGAL::IO::write_MEDIT(output, points_with_ref, CGAL::parameters::tetrahedra(std::cref(cells_with_ref)) + .triangles(std::cref(facets_with_ref)) + .edges(std::cref(edges_with_ref)) + .ridges(std::cref(ridges)) + .corners(std::cref(corners))); - std::istringstream input2(output.str()); - std::vector points2; - std::vector> cells2; - std::vector subdomains2; - std::vector> edges2; - std::vector> facets2; - std::deque> corners2; - success = CGAL::IO::read_MEDIT(input2, points2, cells2, CGAL::parameters::subdomain_indices(std::ref(subdomains2)) - .facets_with_patch_index(std::ref(facets2)) - .edges_with_curve_index(std::ref(edges2)) - .vertices_with_corner_index(std::ref(corners2)) - .verbose(verbose)); + std::istringstream input_bis(output.str()); + std::vector> points_with_ref_bis; + std::vector> cells_with_ref_bis; + std::vector> edges_with_ref_bis; + std::vector> facets_with_ref_bis; + std::vector ridges_bis; + std::deque corners_bis; + success = CGAL::IO::read_MEDIT(input_bis, points_with_ref_bis, CGAL::parameters::tetrahedra(std::ref(cells_with_ref_bis)) + .triangles(std::ref(facets_with_ref_bis)) + .edges(std::ref(edges_with_ref_bis)) + .ridges(std::ref(ridges_bis)) + .corners(std::ref(corners_bis)) + .verbose(false)); - assert(points == points2); - assert(cells == cells2); - assert(subdomains == subdomains2); - assert(corners == corners2); - assert(edges == edges2); - assert(facets == facets2); + assert(points_with_ref== points_with_ref_bis); + assert(cells_with_ref == cells_with_ref_bis); + assert(facets_with_ref == facets_with_ref_bis); + assert(edges_with_ref == edges_with_ref_bis); + assert(corners == corners_bis); + assert(ridges == ridges_bis); assert(success); std::cout << "done" << std::endl; return 0; From c923d46ccb5f3410a9823b2457936faedc1c0a4e Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 9 Oct 2026 14:18:27 +0100 Subject: [PATCH 56/72] Put IO of ref in its own named parameters --- .../internal/parameters_interface.h | 5 +- Stream_support/include/CGAL/IO/MEDIT.h | 244 +++++++++++------- .../test/Stream_support/test_MEDIT.cpp | 68 +++-- 3 files changed, 206 insertions(+), 111 deletions(-) diff --git a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h index 6f58d44aad14..f74a75b6f7b7 100644 --- a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h +++ b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h @@ -73,7 +73,10 @@ CGAL_add_named_parameter(tetrahedra_t, tetrahedra, tetrahedra) CGAL_add_named_parameter(edges_t, edges, edges) CGAL_add_named_parameter(ridges_t, ridges, ridges) CGAL_add_named_parameter(corners_t, corners, corners) - +CGAL_add_named_parameter(tetrahedra_ref_t, tetrahedra_ref, tetrahedra_ref) +CGAL_add_named_parameter(triangles_ref_t, triangles_ref, triangles_ref) +CGAL_add_named_parameter(edges_ref_t, edges_ref, edges_ref) +CGAL_add_named_parameter(vertices_ref_t, vertices_ref, vertices_ref) // List of named parameters that we use in the package 'Mesh_3' CGAL_add_named_parameter(vertex_feature_degree_t, vertex_feature_degree, vertex_feature_degree_map) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 84eefaf6f669..57044d9e8b88 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -133,30 +133,42 @@ CurveIndex get_two(const Edge& t) return t.curve_index; } -template // either Vertex_with_corner_index or a tuple/pair/array + class CornerRange, + class PointRefRange, + class CellRefRange, + class FacetRefRange, + class EdgeRefRange> // either Vertex_with_corner_index or a tuple/pair/array bool read_MEDIT(std::istream& is, - PointWithIndexRange& points, - CellWithIndexRange& cells, - FacetWithIndexRange& facets, + PointRange& points, + CellRange& cells, + FacetRange& facets, bool read_facets, - EdgeWithIndexRange& edges, + EdgeRange& edges, bool read_edges, RidgeRange& ridges, bool read_ridges, CornerRange& corners, bool read_corners, + PointRefRange& point_refs, + bool read_point_refs, + CellRefRange& cell_refs, + bool read_cell_refs, + FacetRefRange& facet_refs, + bool read_facet_refs, + EdgeRefRange& edge_refs, + bool read_edge_refs, bool verbose, bool& is_CGAL_mesh) { - using Point_3 = typename PointWithIndexRange::value_type::first_type; + using Point_3 = typename PointRange::value_type; using FT = typename Kernel_traits::Kernel::FT; using Facet = std::array; - using Cell_with_ref = typename std::iterator_traits::value_type; + using Cell_with_ref = typename std::iterator_traits::value_type; if(!is) return false; @@ -217,7 +229,9 @@ bool read_MEDIT(std::istream& is, std::cerr << "Issue while reading vertices" << std::endl; return false; } - points.emplace_back(std::make_pair(Point_3(x,y,z),ref)); + points.push_back(Point_3(x,y,z)); + if(read_point_refs) + point_refs.emplace_back(ref); } } @@ -233,7 +247,7 @@ bool read_MEDIT(std::istream& is, for(int i=0; i::value_type>::type surface_patch_id; + typename get_surface_path_index_type::value_type>::type surface_patch_id; if(!(is >> n[0] >> n[1] >> n[2] >> surface_patch_id)) { if(verbose) @@ -261,7 +275,9 @@ bool read_MEDIT(std::istream& is, { std::rotate(std::begin(facet), std::next(std::begin(facet)), std::end(facet)); } - facets.push_back({facet[0], facet[1], facet[2], surface_patch_id}); + facets.emplace_back(facet); // AF: why does that not compile?? {facet[0], facet[1], facet[2]}); + if(read_facet_refs) + facet_refs.emplace_back(surface_patch_id); } }else{ is >> nf; @@ -280,9 +296,9 @@ bool read_MEDIT(std::istream& is, for(int i=0; i> n[0] >> n[1] >> n[2] >> n[3] >> reference)) + if(!(is >> n[0] >> n[1] >> n[2] >> n[3] >> ref)) { if(verbose) std::cerr << "Issue while reading cells" << std::endl; @@ -304,24 +320,13 @@ bool read_MEDIT(std::istream& is, t[1] = offset + n[1] - 1; t[2] = offset + n[2] - 1; t[3] = offset + n[3] - 1; - t[4] = reference; cells.push_back(t); + if(read_cell_refs) + cell_refs.push_back(ref); } } - if(line.find("Corners") != std::string::npos) - { - is >> nvertices; - int ci; - for(int i=0; i> ci; - if(read_corners){ - corners.push_back(offset + i); - } - } - } - if(line.find("Edges") != std::string::npos) { if(read_edges){ @@ -337,14 +342,16 @@ bool read_MEDIT(std::istream& is, for(int i = 0; i < nedges; ++i) { int n[2]; - /* AF: was Curve_index*/ int curve_index = 0; - if(!(is >> n[0] >> n[1] >> curve_index)) + /* AF: was Curve_index*/ int ref = 0; + if(!(is >> n[0] >> n[1] >> ref)) { if(verbose) std::cerr << "Issue while reading edges" << std::endl; return false; } - edges.push_back({offset + n[0] - 1, offset + n[1] - 1, curve_index}); + edges.push_back({offset + n[0] - 1, offset + n[1] - 1}); + if(read_edge_refs) + edge_refs.push_back(ref); CGAL_assertion(edges.size() == static_cast(i + 1)); } } @@ -363,7 +370,19 @@ bool read_MEDIT(std::istream& is, for(int i=0; i> ci; if(read_ridges){ - ridges.push_back(offset + i); + ridges.push_back(offset + i); + } + } + } + + if(line.find("Corners") != std::string::npos) + { + is >> nvertices; + int ci; + for(int i=0; i> ci; + if(read_corners){ + corners.push_back(offset + i); } } } @@ -404,7 +423,7 @@ bool read_MEDIT(std::istream& is, * \note Currently, only tetrahedral cells are supported. * \note The cell soup is not cleared, and the data from the stream are appended. * - * \tparam PointRange a model of the concept `BackInsertionSequence` whose value type is the point type + * \tparam PointRange a model of `BackInsertionSequence` whose value type is the point type * * \param is the input stream * \param points points of the soup of cells @@ -421,9 +440,9 @@ bool read_MEDIT(std::istream& is, * \cgalParamDefault{facets are ignored} * \cgalParamNEnd * - * \cgalParamNBegin{facets} + * \cgalParamNBegin{triangles} * \cgalParamDescription{a non-const reference wrapper of a container of quadruples of integers that will be filled by this function. - * Each element represents a facet with vertices corresponding to the first three integers, and the last integer being the surface patch index of the facet.} + * Each element represents a triangle with vertices corresponding to the first three integers, and the last integer being the surface patch index of the triangle.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of four integers.} * \cgalParamDefault{facets are ignored} * \cgalParamNEnd @@ -437,16 +456,16 @@ bool read_MEDIT(std::istream& is, * * \cgalParamNBegin{ridges} * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. - * Each element in the container indicates the subdomain index of the corresponding cell at the same position.} - * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` able to store `int`.} + * Each element in the container is an index in the sequence of edges.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible from an integer.} * \cgalParamDefault{ridges are ignored} * \cgalParamNEnd * * \cgalParamNBegin{corners} - * \cgalParamDescription{a non-const reference wrapper of a container of pairs of integers that will be filled by this function. - * Each element represents a corner at the vertex corresponding to the first integer, and the last integer being the corner index.} - * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of two integers.} - * \cgalParamDefault{vertices are ignored} + * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. + * Each element in the container is an index in the sequence of points} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible from an integer.} + * \cgalParamDefault{corners are ignored/} * \cgalParamNEnd * * \cgalParamNBegin{verbose} @@ -474,18 +493,18 @@ bool read_MEDIT(std::istream& is, const bool verbose = choose_parameter(get_parameter(np, internal_np::verbose), false); // cells - std::vector> default_tetrahedra; - using Tetrahedra = typename internal_np::Lookup_named_param_def>>::reference; + std::vector> default_tetrahedra; + using Tetrahedra = typename internal_np::Lookup_named_param_def>>::reference; Tetrahedra tetrahedra = choose_parameter(get_parameter_reference(np, internal_np::tetrahedra), default_tetrahedra); // triangles - std::vector> default_triangles; - using Triangles = typename internal_np::Lookup_named_param_def>>::reference; + std::vector> default_triangles; + using Triangles = typename internal_np::Lookup_named_param_def>>::reference; Triangles triangles = choose_parameter(get_parameter_reference(np, internal_np::triangles), default_triangles); // edges - std::vector> default_edges; - using Edges = typename internal_np::Lookup_named_param_def>>::reference; + std::vector> default_edges; + using Edges = typename internal_np::Lookup_named_param_def>>::reference; Edges edges = choose_parameter(get_parameter_reference(np, internal_np::edges), default_edges); // ridges @@ -494,19 +513,36 @@ bool read_MEDIT(std::istream& is, Ridges ridges = choose_parameter(get_parameter_reference(np, internal_np::ridges), default_ridges); // corners - std::vector> default_corners; - using Corners = typename internal_np::Lookup_named_param_def>>::reference; + std::vector default_corners; + using Corners = typename internal_np::Lookup_named_param_def>::reference; Corners corners = choose_parameter(get_parameter_reference(np, internal_np::corners), default_corners); + // tetrahedra_ref + std::vector default_tetrahedra_ref; + using Tetrahedra_ref = typename internal_np::Lookup_named_param_def>::reference; + Tetrahedra_ref tetrahedra_ref = choose_parameter(get_parameter_reference(np, internal_np::tetrahedra_ref), default_tetrahedra_ref); - constexpr bool is_triangles_map = !parameters::is_default_parameter::value; + std::vector default_triangles_ref; + using Triangles_ref = typename internal_np::Lookup_named_param_def>::reference; + Triangles_ref triangles_ref = choose_parameter(get_parameter_reference(np, internal_np::triangles_ref), default_triangles_ref); - constexpr bool is_edges_map = !parameters::is_default_parameter::value; + std::vector default_edges_ref; + using Edges_ref = typename internal_np::Lookup_named_param_def>::reference; + Edges_ref edges_ref = choose_parameter(get_parameter_reference(np, internal_np::edges_ref), default_edges_ref); - constexpr bool is_ridges_map = !parameters::is_default_parameter::value; + std::vector default_vertices_ref; + using Vertices_ref = typename internal_np::Lookup_named_param_def>::reference; + Vertices_ref vertices_ref = choose_parameter(get_parameter_reference(np, internal_np::vertices_ref), default_vertices_ref); + constexpr bool is_triangles_map = !parameters::is_default_parameter::value; + constexpr bool is_edges_map = !parameters::is_default_parameter::value; + constexpr bool is_ridges_map = !parameters::is_default_parameter::value; constexpr bool is_corners_map = !parameters::is_default_parameter::value; + constexpr bool is_tetrahedra_ref_map = !parameters::is_default_parameter::value; + constexpr bool is_triangles_ref_map = !parameters::is_default_parameter::value; + constexpr bool is_edges_ref_map = !parameters::is_default_parameter::value; + constexpr bool is_vertices_ref_map = !parameters::is_default_parameter::value; bool is_CGAL_mesh; @@ -515,6 +551,10 @@ bool read_MEDIT(std::istream& is, edges, is_edges_map, ridges, is_ridges_map, corners, is_corners_map, + vertices_ref, is_vertices_ref_map, + tetrahedra_ref, is_tetrahedra_ref_map, + triangles_ref, is_triangles_ref_map, + edges_ref, is_edges_ref_map, verbose, is_CGAL_mesh); } @@ -531,43 +571,48 @@ bool read_MEDIT(std::istream& is, * \note Currently only tetrahedral cells are supported. * - * \tparam PointRange a model of the concept `ConstRange` whose value type is the point type - * \tparam CellRange a model of the concept `ConstRange` - * whose `value_type` is a model of the concept `RandomAccessContainer` - * whose `value_type` is `std::size_t`. + * \tparam PointRange a model of `ConstRange` whose value type is the point type * * \param os the output stream * \param points points of the soup of cells - * \param cells a range where each element is a cell described by indices into `points` * * \param np optional \ref bgl_namedparameters "Named Parameters" described below * * \cgalNamedParamsBegin - * \cgalParamNBegin{ridges} - * \cgalParamDescription{a const reference wrapper of a container of integers of the same size as `cells`. - * Each element in the container indicates the subdomain index of the corresponding cell at the same position.} - * \cgalParamType{a `std::reference_wrapper` to a model of the concept `SequenceContainer` of integer.} - * \cgalParamDefault{all cells will be given the subdomain index `1`.} + * + * + * \cgalParamNBegin{tetrahedra} + * \cgalParamDescription{a const reference wrapper of a container of quintuples of integers that will be written by this function. + * Each element corresponds to a tetrahedron with vertices corresponding to the first four integers, and the last integer being the subdomain index.} + * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the quintuples can be accessed with `std::get()`} + * \cgalParamDefault{tetrahedra are not written} * \cgalParamNEnd * - * \cgalParamNBegin{facets} + * \cgalParamNBegin{triangles} * \cgalParamDescription{a const reference wrapper of a container of quadruples of integers that will be written by this function. - * Each element corresponds to a facet with vertices corresponding to the three first integers, and the last integer being the surface patch index of the facet.} + * Each element corresponds to a triangle with vertices corresponding to the first three integers, and the last integer being the surface patch index of the triangle.} * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the quadruples can be accessed with `std::get()`} - * \cgalParamDefault{facets are not written} + * \cgalParamDefault{triangles are not written} * \cgalParamNEnd * * \cgalParamNBegin{edges} * \cgalParamDescription{a const reference wrapper of a container of triples of integers that will be written by this function. - * Each element corresponds to an edge with vertices corresponding to the two first integers, and the last integer being the curve index of the edge.} + * Each element corresponds to an edge with vertices corresponding to the first two integers, and the last integer being the curve index of the edge.} * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the triples can be accessed with `std::get()`} * \cgalParamDefault{edges are not written} * \cgalParamNEnd * + * \cgalParamNBegin{ridges} + * \cgalParamDescription{a const reference wrapper of a container of integers that will be written by this function. + * Each element in the container is an index in the sequence of edges.} + * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with an integer type as value type..} + * \cgalParamDefault{ridges are not written} + * \cgalParamNEnd + * * \cgalParamNBegin{corners} - * \cgalParamDescription{a const reference wrapper of a container of pairs of integers that will be written by this function. - * Each element corresponds to a corner at the vertex corresponding to the first integer, the second integer being the corner index.} - * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the pairs can be accessed with `std::get()`} + * \cgalParamDescription{a const reference wrapper of a container of integers that will be written by this function. + * Each element in the container is an index in the sequence of points.} + * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with an integer type as value type.} * \cgalParamDefault{corners are not written} * \cgalParamNEnd * @@ -598,19 +643,19 @@ bool write_MEDIT(std::ostream& os, return false; - std::vector default_ridges; - std::vector default_corners; - std::vector> default_edges; - std::vector> default_facets; - std::vector> default_cells; + std::vector default_ridges, default_corners; + std::vector default_tetrahedra_ref, default_triangles_ref, default_edges_ref, default_vertices_ref; + std::vector> default_edges; + std::vector> default_facets; + std::vector> default_cells; - using Cells = typename internal_np::Lookup_named_param_def>>::reference; + using Cells = typename internal_np::Lookup_named_param_def>>::reference; Cells cells = choose_parameter(get_parameter_reference(np, internal_np::tetrahedra), default_cells); - using Facets = typename internal_np::Lookup_named_param_def>>::reference; + using Facets = typename internal_np::Lookup_named_param_def>>::reference; Facets facets = choose_parameter(get_parameter_reference(np, internal_np::triangles), default_facets); - using Edges = typename internal_np::Lookup_named_param_def>>::reference; + using Edges = typename internal_np::Lookup_named_param_def>>::reference; Edges edges = choose_parameter(get_parameter_reference(np, internal_np::edges), default_edges); using Ridges = typename internal_np::Lookup_named_param_def>::reference; @@ -619,31 +664,53 @@ bool write_MEDIT(std::ostream& os, using corners = typename internal_np::Lookup_named_param_def>>::reference; corners vertices = choose_parameter(get_parameter_reference(np, internal_np::corners), default_corners); + using Tetrahedra_ref = typename internal_np::Lookup_named_param_def>::reference; + Tetrahedra_ref tetrahedra_ref = choose_parameter(get_parameter_reference(np, internal_np::tetrahedra_ref), default_tetrahedra_ref); + + using Triangles_ref = typename internal_np::Lookup_named_param_def>::reference; + Triangles_ref triangles_ref = choose_parameter(get_parameter_reference(np, internal_np::triangles_ref), default_triangles_ref); + + using Edges_ref = typename internal_np::Lookup_named_param_def>::reference; + Edges_ref edges_ref = choose_parameter(get_parameter_reference(np, internal_np::edges_ref), default_edges_ref); + + using Vertices_ref = typename internal_np::Lookup_named_param_def>::reference; + Vertices_ref vertices_ref = choose_parameter(get_parameter_reference(np, internal_np::vertices_ref), default_vertices_ref); + + + constexpr bool is_tetrahedra_ref_map = !parameters::is_default_parameter::value; + constexpr bool is_triangles_ref_map = !parameters::is_default_parameter::value; + constexpr bool is_edges_ref_map = !parameters::is_default_parameter::value; + constexpr bool is_vertices_ref_map = !parameters::is_default_parameter::value; os << "MeshVersionFormatted 1\nDimension 3\n"; os << "Vertices\n"; os << points.size() << "\n"; - for (const auto& p : points){ - - os << p.first << " " << p.second << "\n"; + for (std::size_t k = 0; k < points.size(); ++k){ + const auto& p = points[k]; + int ref = is_vertices_ref_map ? vertices_ref[k] : 0; + os << p << " " << ref << "\n"; } os << "Tetrahedra\n"; os << cells.size() << "\n"; - for (std::size_t k=0; k(f) +1 << " " << std::get<1>(f) + 1 << " " << std::get<2>(f) + 1 << " " << std::get<3>(f) << "\n"; + for(std::size_t k = 0; k < facets.size(); ++k){ + const auto& f = facets[k]; + int ref = is_triangles_ref_map ? triangles_ref[k]: 0; + os << std::get<0>(f) +1 << " " << std::get<1>(f) + 1 << " " << std::get<2>(f) + 1 << " " << ref << "\n"; + } } if(!vertices.empty()){ diff --git a/Stream_support/test/Stream_support/test_MEDIT.cpp b/Stream_support/test/Stream_support/test_MEDIT.cpp index e104f03f0dfd..a83b1ba82461 100644 --- a/Stream_support/test/Stream_support/test_MEDIT.cpp +++ b/Stream_support/test/Stream_support/test_MEDIT.cpp @@ -14,48 +14,70 @@ typedef Kernel::Point_3 Point_3; int main() { const std::string filename = "./data/polyhedral_complex.mesh"; std::ifstream input(filename); - std::vector> points_with_ref; - std::vector> cells_with_ref; - std::vector> edges_with_ref; - std::vector> facets_with_ref; + std::vector points; + std::vector> cells; + std::vector> facets; + std::vector> edges; std::vector ridges; std::deque corners; - bool success = CGAL::IO::read_MEDIT(input, points_with_ref, CGAL::parameters::tetrahedra(std::ref(cells_with_ref)) - .triangles(std::ref(facets_with_ref)) - .edges(std::ref(edges_with_ref)) + std::vector point_refs, cell_refs, facet_refs, edge_refs; + + std::cout << "A " << & cell_refs << std::endl; + + bool success = CGAL::IO::read_MEDIT(input, points, CGAL::parameters::tetrahedra(std::ref(cells)) + .triangles(std::ref(facets)) + .edges(std::ref(edges)) .ridges(std::ref(ridges)) .corners(std::ref(corners)) + .tetrahedra_ref(std::ref(cell_refs)) + .triangles_ref(std::ref(facet_refs)) + .edges_ref(std::ref(edge_refs)) + .vertices_ref(std::ref(point_refs)) .verbose(false)); assert(success); std::ostringstream output; output.precision(17); - CGAL::IO::write_MEDIT(output, points_with_ref, CGAL::parameters::tetrahedra(std::cref(cells_with_ref)) - .triangles(std::cref(facets_with_ref)) - .edges(std::cref(edges_with_ref)) + CGAL::IO::write_MEDIT(output, points, CGAL::parameters::tetrahedra(std::cref(cells)) + .triangles(std::cref(facets)) + .edges(std::cref(edges)) .ridges(std::cref(ridges)) - .corners(std::cref(corners))); + .corners(std::cref(corners)) + .tetrahedra_ref(std::cref(cell_refs)) + .triangles_ref(std::cref(facet_refs)) + .edges_ref(std::cref(edge_refs)) + .vertices_ref(std::cref(point_refs))); std::istringstream input_bis(output.str()); - std::vector> points_with_ref_bis; - std::vector> cells_with_ref_bis; - std::vector> edges_with_ref_bis; - std::vector> facets_with_ref_bis; + std::vector points_bis; + std::vector> cells_bis; + std::vector> facets_bis; + std::vector> edges_bis; std::vector ridges_bis; std::deque corners_bis; - success = CGAL::IO::read_MEDIT(input_bis, points_with_ref_bis, CGAL::parameters::tetrahedra(std::ref(cells_with_ref_bis)) - .triangles(std::ref(facets_with_ref_bis)) - .edges(std::ref(edges_with_ref_bis)) + std::vector point_refs_bis, cell_refs_bis, facet_refs_bis, edge_refs_bis; + + success = CGAL::IO::read_MEDIT(input_bis, points_bis, CGAL::parameters::tetrahedra(std::ref(cells_bis)) + .triangles(std::ref(facets_bis)) + .edges(std::ref(edges_bis)) .ridges(std::ref(ridges_bis)) .corners(std::ref(corners_bis)) + .tetrahedra_ref(std::ref(cell_refs_bis)) + .triangles_ref(std::ref(facet_refs_bis)) + .edges_ref(std::ref(edge_refs_bis)) + .vertices_ref(std::ref(point_refs_bis)) .verbose(false)); - assert(points_with_ref== points_with_ref_bis); - assert(cells_with_ref == cells_with_ref_bis); - assert(facets_with_ref == facets_with_ref_bis); - assert(edges_with_ref == edges_with_ref_bis); - assert(corners == corners_bis); + assert(points== points_bis); + assert(cells == cells_bis); + assert(facets == facets_bis); + assert(edges == edges_bis); assert(ridges == ridges_bis); + assert(corners == corners_bis); + assert(cell_refs == cell_refs_bis); + assert(facet_refs == facet_refs_bis); + assert(edge_refs == edge_refs_bis); + assert(point_refs == point_refs_bis); assert(success); std::cout << "done" << std::endl; return 0; From 28ee8edebcd3417032e96149e6cb78a6faff131c Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 9 Oct 2026 18:21:15 +0100 Subject: [PATCH 57/72] Make SMDS and Mesh_smoothing work. WIP as ambiguity for read_MEDIT --- ...ndary_aware_mesh_smoothing_integration.cpp | 2 +- SMDS_3/include/CGAL/IO/File_medit.h | 61 +++++++++++++++---- SMDS_3/test/SMDS_3/test_c3t3.cpp | 2 +- SMDS_3/test/SMDS_3/test_c3t3_io_MEDIT.cpp | 22 +++---- Stream_support/include/CGAL/IO/MEDIT.h | 15 +++-- 5 files changed, 68 insertions(+), 34 deletions(-) diff --git a/Mesh_smoothing_3/test/Mesh_smoothing_3/test_boundary_aware_mesh_smoothing_integration.cpp b/Mesh_smoothing_3/test/Mesh_smoothing_3/test_boundary_aware_mesh_smoothing_integration.cpp index e6d97ca51211..39c5f1d7992b 100644 --- a/Mesh_smoothing_3/test/Mesh_smoothing_3/test_boundary_aware_mesh_smoothing_integration.cpp +++ b/Mesh_smoothing_3/test/Mesh_smoothing_3/test_boundary_aware_mesh_smoothing_integration.cpp @@ -30,7 +30,7 @@ C3t3 load_example_mesh() C3t3 c3t3; std::ifstream is(MS3_EXAMPLE_MESH_FILE, std::ios::in); assert(is); - const bool read_ok = CGAL::IO::read_MEDIT(is, c3t3.triangulation()); + const bool read_ok = CGAL::IO::Xread_MEDIT(is, c3t3.triangulation()); assert(read_ok); c3t3.rescan_after_load_of_triangulation(); return c3t3; diff --git a/SMDS_3/include/CGAL/IO/File_medit.h b/SMDS_3/include/CGAL/IO/File_medit.h index c6a129e1e866..4c75d48f60c7 100644 --- a/SMDS_3/include/CGAL/IO/File_medit.h +++ b/SMDS_3/include/CGAL/IO/File_medit.h @@ -456,20 +456,22 @@ bool build_triangulation_from_file(std::istream& is, using Subdomain_index = typename Tr::Cell::Subdomain_index; using Surface_patch_index = typename Tr::Cell::Surface_patch_index; + using Edge = std::array; using Facet = std::array; // 3 = id - using Tet_with_ref = std::array; // 4 = id + using Tet = std::array; // 4 = id using Facet_with_index = CGAL::IO::internal::Facet_with_patch_index; using Edge_with_index = CGAL::IO::internal::Edge_with_curve_index; using Corner_with_index = CGAL::IO::internal::Vertex_with_corner_index; - std::vector finite_cells; + std::vector finite_cells; std::vector subdomains; std::vector points; - std::vector facet_indices; - std::vector edge_indices; - std::vector corner_indices; + std::vector facets; + std::vector edges; + std::vector corners, facet_refs, edge_refs, point_refs; + std::vector ignored_ridges; bool is_CGAL_mesh = false; @@ -479,16 +481,48 @@ bool build_triangulation_from_file(std::istream& is, std::cout << "Allow non-manifoldness = " << allow_non_manifold << std::endl; } - bool ok = CGAL::IO::internal::read_MEDIT(is, points, finite_cells, subdomains, - facet_indices, true, - edge_indices, true, - corner_indices, true, + bool ok = CGAL::IO::internal::read_MEDIT(is, points, finite_cells, + facets, true, + edges, true, + ignored_ridges, false, + corners, true, + point_refs, true, + subdomains, true, + facet_refs, true, + edge_refs, true, verbose, is_CGAL_mesh); if(!ok){ return false; } + std::vector edge_indices; + for(int i = 0; i < edges.size(); ++i){ + Edge_with_index ewi; + ewi.v0 = edges[i][0]; + ewi.v1 = edges[i][1]; + ewi.curve_index = edge_refs[i]; + edge_indices.emplace_back(ewi); + } + + std::vector facet_indices; + for(int i = 0; i < facets.size(); ++i){ + Facet_with_index fwi; + fwi.v0 = facets[i][0]; + fwi.v1 = facets[i][1]; + fwi.v2 = facets[i][2]; + fwi.surface_patch_index = facet_refs[i]; + facet_indices.emplace_back(fwi); + } + + std::vector corner_indices; + for(int i = 0; i < corners.size(); ++i){ + Corner_with_index cwi; + cwi.v = corners[i]; + cwi.corner_index = point_refs[i]; + corner_indices.emplace_back(cwi); + } + boost::unordered_map border_facets; border_facets.reserve(facet_indices.size()); @@ -525,6 +559,7 @@ bool build_triangulation_from_file(std::istream& is, replace_domain_0 && !is_CGAL_mesh, allow_non_manifold, allow_negative_orientation); +return true; } template -void write_MEDIT(std::ostream& os, +void Xwrite_MEDIT(std::ostream& os, const T3& t3, const NamedParameters& np = parameters::default_values()) { @@ -1022,7 +1057,7 @@ template -void write_MEDIT(std::ostream& os, +void Xwrite_MEDIT(std::ostream& os, const CGAL::Mesh_complex_3_in_triangulation_3& c3t3, const NamedParameters& np = parameters::default_values()) { @@ -1082,7 +1117,7 @@ void write_MEDIT(std::ostream& os, * \see \ref IOStreamMedit */ template -bool read_MEDIT(std::istream& in, +bool Xread_MEDIT(std::istream& in, T3& t3, const CGAL_NP_CLASS& np = parameters::default_values()) { @@ -1160,7 +1195,7 @@ template -bool read_MEDIT(std::istream& in, +bool Xread_MEDIT(std::istream& in, CGAL::Mesh_complex_3_in_triangulation_3& c3t3, const CGAL_NP_CLASS& np = parameters::default_values()) { diff --git a/SMDS_3/test/SMDS_3/test_c3t3.cpp b/SMDS_3/test/SMDS_3/test_c3t3.cpp index 9fe7b744aae2..2fdf51403ed6 100644 --- a/SMDS_3/test/SMDS_3/test_c3t3.cpp +++ b/SMDS_3/test/SMDS_3/test_c3t3.cpp @@ -401,7 +401,7 @@ struct Tester assert ( c3t3.surface_patch_index(*patch_fit_bis) == surface_patch_index_bis ); std::ofstream out_medit("test-medit.mesh"); - CGAL::IO::write_MEDIT(out_medit, c3t3); + CGAL::IO::Xwrite_MEDIT(out_medit, c3t3); out_medit.close(); CGAL::IO::output_to_tetgen("test-tetgen", c3t3); } diff --git a/SMDS_3/test/SMDS_3/test_c3t3_io_MEDIT.cpp b/SMDS_3/test/SMDS_3/test_c3t3_io_MEDIT.cpp index 7f0ff4ee718f..5ec3711c2524 100644 --- a/SMDS_3/test/SMDS_3/test_c3t3_io_MEDIT.cpp +++ b/SMDS_3/test/SMDS_3/test_c3t3_io_MEDIT.cpp @@ -53,13 +53,13 @@ int test_MEDIT_with_features() const std::size_t nb_corners = c3t3.number_of_corners(); std::ofstream os("fandisk_out.mesh"); - CGAL::IO::write_MEDIT(os, c3t3, + CGAL::IO::Xwrite_MEDIT(os, c3t3, CGAL::parameters::all_vertices(true).all_cells(true)); os.close(); std::ifstream is("fandisk_out.mesh"); C3t3 c3t3_in; - CGAL::IO::read_MEDIT(is, c3t3_in); + CGAL::IO::Xread_MEDIT(is, c3t3_in); is.close(); std::cout << "Read " << c3t3_in.number_of_facets() << " facets, " << c3t3_in.number_of_edges() << " edges, " @@ -88,16 +88,16 @@ int test_MEDIT_negative_cells() } Tr tr; - CGAL::IO::read_MEDIT(in, tr, CGAL::parameters::allow_negative_orientation(true)); + CGAL::IO::Xread_MEDIT(in, tr, CGAL::parameters::allow_negative_orientation(true)); assert(tr.is_valid()); std::ofstream os("negative_cells_out.mesh"); - CGAL::IO::write_MEDIT(os, tr, + CGAL::IO::Xwrite_MEDIT(os, tr, CGAL::parameters::all_vertices(false).all_cells(true)); os.close(); Tr tr2; std::ifstream is2("negative_cells_out.mesh"); - CGAL::IO::read_MEDIT(is2, tr2, CGAL::parameters::allow_negative_orientation(true)); + CGAL::IO::Xread_MEDIT(is2, tr2, CGAL::parameters::allow_negative_orientation(true)); is2.close(); assert(tr2.is_valid()); @@ -117,11 +117,11 @@ int test() return 1; } Tr tr; - CGAL::IO::read_MEDIT(in, tr); + CGAL::IO::Xread_MEDIT(in, tr); assert(tr.is_valid()); std::ofstream os("elephant_out.mesh"); - CGAL::IO::write_MEDIT(os, tr, + CGAL::IO::Xwrite_MEDIT(os, tr, CGAL::parameters::all_vertices(false).all_cells(true)); os.close(); @@ -134,24 +134,24 @@ int test() tr.insert(isocuboid.vertex(i)); std::ofstream os2("elephant_out_not_all_vertices.mesh"); - CGAL::IO::write_MEDIT(os2, tr, + CGAL::IO::Xwrite_MEDIT(os2, tr, CGAL::parameters::all_vertices(false)); os2.close(); Tr tr2; std::ifstream is2("elephant_out_not_all_vertices.mesh"); - CGAL::IO::read_MEDIT(is2, tr2);; + CGAL::IO::Xread_MEDIT(is2, tr2);; is2.close(); assert(tr2.is_valid()); // non convex std::ofstream os3("elephant_out_not_all_cells.mesh"); - CGAL::IO::write_MEDIT(os3, tr, CGAL::parameters::all_cells(false)); + CGAL::IO::Xwrite_MEDIT(os3, tr, CGAL::parameters::all_cells(false)); os3.close(); Tr tr3; std::ifstream is3("elephant_out_not_all_cells.mesh"); - CGAL::IO::read_MEDIT(is3, tr3); + CGAL::IO::Xread_MEDIT(is3, tr3); is3.close(); assert(tr3.is_valid()); diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 57044d9e8b88..43b59b3f17af 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -36,7 +36,7 @@ namespace IO { namespace internal { template -struct Facet +struct Facet_with_patch_index { int v0, v1, v2; SurfacePatchIndex surface_patch_index; @@ -49,7 +49,7 @@ struct get_surface_path_index_type }; template -struct get_surface_path_index_type> +struct get_surface_path_index_type> { using type = SurfacePatchIndex; }; @@ -67,7 +67,7 @@ struct get_surface_path_index_type> }; template -struct Edge +struct Edge_with_curve_index { int v0, v1; CurveIndex curve_index; @@ -116,19 +116,19 @@ CornerIndex get_one(const Vertex_with_corner_index& t) } template -int get_zero(const Edge& t) +int get_zero(const Edge_with_curve_index& t) { return t.v0; } template -int get_one(const Edge& t) +int get_one(const Edge_with_curve_index& t) { return t.v1; } template -CurveIndex get_two(const Edge& t) +CurveIndex get_two(const Edge_with_curve_index& t) { return t.curve_index; } @@ -362,7 +362,7 @@ bool read_MEDIT(std::istream& is, for(int i=0; i> nridges; @@ -388,7 +388,6 @@ bool read_MEDIT(std::istream& is, } } - } if (verbose) { From 0b1882cb8d6f6839f78975ca9d041772da844f72 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 9 Oct 2026 18:52:47 +0100 Subject: [PATCH 58/72] Use internal::is_Range to disambiguate --- ...ndary_aware_mesh_smoothing_integration.cpp | 2 +- SMDS_3/include/CGAL/IO/File_medit.h | 8 +++---- SMDS_3/test/SMDS_3/test_c3t3.cpp | 8 +++---- SMDS_3/test/SMDS_3/test_c3t3_io_MEDIT.cpp | 22 +++++++++---------- Stream_support/include/CGAL/IO/MEDIT.h | 9 ++++++-- 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/Mesh_smoothing_3/test/Mesh_smoothing_3/test_boundary_aware_mesh_smoothing_integration.cpp b/Mesh_smoothing_3/test/Mesh_smoothing_3/test_boundary_aware_mesh_smoothing_integration.cpp index 39c5f1d7992b..e6d97ca51211 100644 --- a/Mesh_smoothing_3/test/Mesh_smoothing_3/test_boundary_aware_mesh_smoothing_integration.cpp +++ b/Mesh_smoothing_3/test/Mesh_smoothing_3/test_boundary_aware_mesh_smoothing_integration.cpp @@ -30,7 +30,7 @@ C3t3 load_example_mesh() C3t3 c3t3; std::ifstream is(MS3_EXAMPLE_MESH_FILE, std::ios::in); assert(is); - const bool read_ok = CGAL::IO::Xread_MEDIT(is, c3t3.triangulation()); + const bool read_ok = CGAL::IO::read_MEDIT(is, c3t3.triangulation()); assert(read_ok); c3t3.rescan_after_load_of_triangulation(); return c3t3; diff --git a/SMDS_3/include/CGAL/IO/File_medit.h b/SMDS_3/include/CGAL/IO/File_medit.h index 4c75d48f60c7..8418619e4399 100644 --- a/SMDS_3/include/CGAL/IO/File_medit.h +++ b/SMDS_3/include/CGAL/IO/File_medit.h @@ -977,7 +977,7 @@ output_to_medit(std::ostream& os, * \see \ref IOStreamMedit */ template -void Xwrite_MEDIT(std::ostream& os, +void write_MEDIT(std::ostream& os, const T3& t3, const NamedParameters& np = parameters::default_values()) { @@ -1057,7 +1057,7 @@ template -void Xwrite_MEDIT(std::ostream& os, +void write_MEDIT(std::ostream& os, const CGAL::Mesh_complex_3_in_triangulation_3& c3t3, const NamedParameters& np = parameters::default_values()) { @@ -1117,7 +1117,7 @@ void Xwrite_MEDIT(std::ostream& os, * \see \ref IOStreamMedit */ template -bool Xread_MEDIT(std::istream& in, +bool read_MEDIT(std::istream& in, T3& t3, const CGAL_NP_CLASS& np = parameters::default_values()) { @@ -1195,7 +1195,7 @@ template -bool Xread_MEDIT(std::istream& in, +bool read_MEDIT(std::istream& in, CGAL::Mesh_complex_3_in_triangulation_3& c3t3, const CGAL_NP_CLASS& np = parameters::default_values()) { diff --git a/SMDS_3/test/SMDS_3/test_c3t3.cpp b/SMDS_3/test/SMDS_3/test_c3t3.cpp index 2fdf51403ed6..8c3b5ee11e0c 100644 --- a/SMDS_3/test/SMDS_3/test_c3t3.cpp +++ b/SMDS_3/test/SMDS_3/test_c3t3.cpp @@ -5,7 +5,7 @@ // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// SPD-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Stephane Tayeb @@ -335,7 +335,7 @@ struct Tester c3t3.set_subdomain_index(ch, subdomain_index_bis); c3t3.set_surface_patch_index(f2, surface_patch_index_bis); -#ifndef CGAL_MESH_3_NO_DEPRECATED_SURFACE_INDEX +#ifndef CGAL_MESH_3_NO_DEPRECATED_SURFACE_INDE c3t3.set_surface_index(f2, surface_patch_index_bis); c3t3.set_surface_index(f2.first, f2.second, surface_patch_index_bis); #endif @@ -344,7 +344,7 @@ struct Tester assert(c3t3.subdomain_index(ch) == subdomain_index_bis); assert(c3t3.surface_patch_index(f2) == surface_patch_index_bis); -#ifndef CGAL_MESH_3_NO_DEPRECATED_SURFACE_INDEX +#ifndef CGAL_MESH_3_NO_DEPRECATED_SURFACE_INDE assert(c3t3.surface_index(f2) == surface_patch_index_bis); assert(c3t3.surface_index(f2.first, f2.second) == surface_patch_index_bis); #endif @@ -401,7 +401,7 @@ struct Tester assert ( c3t3.surface_patch_index(*patch_fit_bis) == surface_patch_index_bis ); std::ofstream out_medit("test-medit.mesh"); - CGAL::IO::Xwrite_MEDIT(out_medit, c3t3); + CGAL::IO::write_MEDIT(out_medit, c3t3); out_medit.close(); CGAL::IO::output_to_tetgen("test-tetgen", c3t3); } diff --git a/SMDS_3/test/SMDS_3/test_c3t3_io_MEDIT.cpp b/SMDS_3/test/SMDS_3/test_c3t3_io_MEDIT.cpp index 5ec3711c2524..7f0ff4ee718f 100644 --- a/SMDS_3/test/SMDS_3/test_c3t3_io_MEDIT.cpp +++ b/SMDS_3/test/SMDS_3/test_c3t3_io_MEDIT.cpp @@ -53,13 +53,13 @@ int test_MEDIT_with_features() const std::size_t nb_corners = c3t3.number_of_corners(); std::ofstream os("fandisk_out.mesh"); - CGAL::IO::Xwrite_MEDIT(os, c3t3, + CGAL::IO::write_MEDIT(os, c3t3, CGAL::parameters::all_vertices(true).all_cells(true)); os.close(); std::ifstream is("fandisk_out.mesh"); C3t3 c3t3_in; - CGAL::IO::Xread_MEDIT(is, c3t3_in); + CGAL::IO::read_MEDIT(is, c3t3_in); is.close(); std::cout << "Read " << c3t3_in.number_of_facets() << " facets, " << c3t3_in.number_of_edges() << " edges, " @@ -88,16 +88,16 @@ int test_MEDIT_negative_cells() } Tr tr; - CGAL::IO::Xread_MEDIT(in, tr, CGAL::parameters::allow_negative_orientation(true)); + CGAL::IO::read_MEDIT(in, tr, CGAL::parameters::allow_negative_orientation(true)); assert(tr.is_valid()); std::ofstream os("negative_cells_out.mesh"); - CGAL::IO::Xwrite_MEDIT(os, tr, + CGAL::IO::write_MEDIT(os, tr, CGAL::parameters::all_vertices(false).all_cells(true)); os.close(); Tr tr2; std::ifstream is2("negative_cells_out.mesh"); - CGAL::IO::Xread_MEDIT(is2, tr2, CGAL::parameters::allow_negative_orientation(true)); + CGAL::IO::read_MEDIT(is2, tr2, CGAL::parameters::allow_negative_orientation(true)); is2.close(); assert(tr2.is_valid()); @@ -117,11 +117,11 @@ int test() return 1; } Tr tr; - CGAL::IO::Xread_MEDIT(in, tr); + CGAL::IO::read_MEDIT(in, tr); assert(tr.is_valid()); std::ofstream os("elephant_out.mesh"); - CGAL::IO::Xwrite_MEDIT(os, tr, + CGAL::IO::write_MEDIT(os, tr, CGAL::parameters::all_vertices(false).all_cells(true)); os.close(); @@ -134,24 +134,24 @@ int test() tr.insert(isocuboid.vertex(i)); std::ofstream os2("elephant_out_not_all_vertices.mesh"); - CGAL::IO::Xwrite_MEDIT(os2, tr, + CGAL::IO::write_MEDIT(os2, tr, CGAL::parameters::all_vertices(false)); os2.close(); Tr tr2; std::ifstream is2("elephant_out_not_all_vertices.mesh"); - CGAL::IO::Xread_MEDIT(is2, tr2);; + CGAL::IO::read_MEDIT(is2, tr2);; is2.close(); assert(tr2.is_valid()); // non convex std::ofstream os3("elephant_out_not_all_cells.mesh"); - CGAL::IO::Xwrite_MEDIT(os3, tr, CGAL::parameters::all_cells(false)); + CGAL::IO::write_MEDIT(os3, tr, CGAL::parameters::all_cells(false)); os3.close(); Tr tr3; std::ifstream is3("elephant_out_not_all_cells.mesh"); - CGAL::IO::Xread_MEDIT(is3, tr3); + CGAL::IO::read_MEDIT(is3, tr3); is3.close(); assert(tr3.is_valid()); diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 43b59b3f17af..662db4547a06 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -13,6 +13,7 @@ #define CGAL_IO_MEDIT_H #include +#include #include #include #include @@ -483,7 +484,11 @@ bool read_MEDIT(std::istream& is, template bool read_MEDIT(std::istream& is, PointRange& points, - const CGAL_NP_CLASS& np = parameters::default_values()) + const CGAL_NP_CLASS& np = parameters::default_values() +#ifndef DOXYGEN_RUNNING + , std::enable_if_t::value>* = nullptr +#endif + ) { using parameters::choose_parameter; using parameters::get_parameter; @@ -626,7 +631,7 @@ bool write_MEDIT(std::ostream& os, const PointRange& points, const CGAL_NP_CLASS& np = parameters::default_values() #ifndef DOXYGEN_RUNNING - , std::enable_if_t>* = nullptr + , std::enable_if_t::value>* = nullptr #endif ) From 78e8d419ebb36fb3771649cccb8ae912cc840a16 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 9 Oct 2026 19:16:26 +0100 Subject: [PATCH 59/72] Update documentation. For review only document one of the _ref named parameters --- Stream_support/include/CGAL/IO/MEDIT.h | 56 ++++++++++++++++---------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 662db4547a06..32852269dbac 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -432,25 +432,24 @@ bool read_MEDIT(std::istream& is, * * \cgalNamedParamsBegin * - * * \cgalParamNBegin{tetrahedra} - * \cgalParamDescription{a non-const reference wrapper of a container of quintuples of integers that will be filled by this function. - * Each element represents a tetrahedron with vertices corresponding to the first four integers, and the last integer being the subdomin index of the tetrahedron.} - * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of five integers.} + * \cgalParamDescription{a non-const reference wrapper of a container of quadruples of integers that will be filled by this function. + * Each element represents a tetrahedron with vertices corresponding to the four integers.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of four integers.} * \cgalParamDefault{facets are ignored} * \cgalParamNEnd * * \cgalParamNBegin{triangles} - * \cgalParamDescription{a non-const reference wrapper of a container of quadruples of integers that will be filled by this function. - * Each element represents a triangle with vertices corresponding to the first three integers, and the last integer being the surface patch index of the triangle.} - * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of four integers.} + * \cgalParamDescription{a non-const reference wrapper of a container of triples of integers that will be filled by this function. + * Each element represents a triangle with vertices corresponding to the three integers.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of three integers.} * \cgalParamDefault{facets are ignored} * \cgalParamNEnd * * \cgalParamNBegin{edges} - * \cgalParamDescription{a non-const reference wrapper of a container of triples of integers that will be filled by this function. - * Each element represents an edge with vertices corresponding to the first two integers, and the last integer being the curve index of the edge.} - * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of three integers.} + * \cgalParamDescription{a non-const reference wrapper of a container of pairs of integers that will be filled by this function. + * Each element represents an edge with vertices corresponding to the two integers.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of two integers.} * \cgalParamDefault{edges are ignored} * \cgalParamNEnd * @@ -463,11 +462,18 @@ bool read_MEDIT(std::istream& is, * * \cgalParamNBegin{corners} * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. - * Each element in the container is an index in the sequence of points} + * Each element in the container is an index in the sequence of points.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible from an integer.} * \cgalParamDefault{corners are ignored/} * \cgalParamNEnd * + * \cgalParamNBegin{terahedra_ref} + * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. + * Each element in the container corresponds to an element in `tetrahedra`.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible from an integer.} + * \cgalParamDefault{elements are ignored/} + * \cgalParamNEnd + * * \cgalParamNBegin{verbose} * \cgalParamDescription{if `true`, prints information about the reading process.} * \cgalParamType{Boolean} @@ -584,32 +590,31 @@ bool read_MEDIT(std::istream& is, * * \cgalNamedParamsBegin * - * * \cgalParamNBegin{tetrahedra} - * \cgalParamDescription{a const reference wrapper of a container of quintuples of integers that will be written by this function. - * Each element corresponds to a tetrahedron with vertices corresponding to the first four integers, and the last integer being the subdomain index.} - * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the quintuples can be accessed with `std::get()`} + * \cgalParamDescription{a const reference wrapper of a container of quadruples of integers that will be written by this function. + * Each element corresponds to a tetrahedron with vertices corresponding to the four integers.} + * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the quadruples can be accessed with `std::get()`} * \cgalParamDefault{tetrahedra are not written} * \cgalParamNEnd * * \cgalParamNBegin{triangles} - * \cgalParamDescription{a const reference wrapper of a container of quadruples of integers that will be written by this function. - * Each element corresponds to a triangle with vertices corresponding to the first three integers, and the last integer being the surface patch index of the triangle.} - * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the quadruples can be accessed with `std::get()`} + * \cgalParamDescription{a const reference wrapper of a container of triples of integers that will be written by this function. + * Each element corresponds to a triangle with vertices corresponding to the three integers.} + * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the triples can be accessed with `std::get()`} * \cgalParamDefault{triangles are not written} * \cgalParamNEnd * * \cgalParamNBegin{edges} - * \cgalParamDescription{a const reference wrapper of a container of triples of integers that will be written by this function. - * Each element corresponds to an edge with vertices corresponding to the first two integers, and the last integer being the curve index of the edge.} - * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the triples can be accessed with `std::get()`} + * \cgalParamDescription{a const reference wrapper of a container of pairs of integers that will be written by this function. + * Each element corresponds to an edge with vertices corresponding to the two integers.} + * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with a value type where the elements of the pairs can be accessed with `std::get()`} * \cgalParamDefault{edges are not written} * \cgalParamNEnd * * \cgalParamNBegin{ridges} * \cgalParamDescription{a const reference wrapper of a container of integers that will be written by this function. * Each element in the container is an index in the sequence of edges.} - * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with an integer type as value type..} + * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with an integer type as value type.} * \cgalParamDefault{ridges are not written} * \cgalParamNEnd * @@ -620,6 +625,13 @@ bool read_MEDIT(std::istream& is, * \cgalParamDefault{corners are not written} * \cgalParamNEnd * + * \cgalParamNBegin{tetrahedra_ref} + * \cgalParamDescription{a const reference wrapper of a container of integers that will be written by this function. + * It must have the same size as `tetrahedra`, and each element in the container is a value associated to the tetrahedron at the same position.} + * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with an integer type as value type.} + * \cgalParamDefault{corners are not written} + * \cgalParamNEnd + * * \cgalNamedParamsEnd * * \returns `true` if the writing was successful, `false` otherwise. From 9ef41118974eb8ed3ae15d2425781feceba55509 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 9 Oct 2026 20:42:34 +0100 Subject: [PATCH 60/72] X --- SMDS_3/test/SMDS_3/test_c3t3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SMDS_3/test/SMDS_3/test_c3t3.cpp b/SMDS_3/test/SMDS_3/test_c3t3.cpp index 8c3b5ee11e0c..0a555613a016 100644 --- a/SMDS_3/test/SMDS_3/test_c3t3.cpp +++ b/SMDS_3/test/SMDS_3/test_c3t3.cpp @@ -5,7 +5,7 @@ // // $URL$ // $Id$ -// SPD-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Stephane Tayeb From 81d3ae0c79ed04dd3494473877a7400d74f28831 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 12 Oct 2026 07:44:21 +0100 Subject: [PATCH 61/72] Write the default for a ref --- Stream_support/include/CGAL/IO/MEDIT.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 32852269dbac..022e15f63fdb 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -629,7 +629,7 @@ bool read_MEDIT(std::istream& is, * \cgalParamDescription{a const reference wrapper of a container of integers that will be written by this function. * It must have the same size as `tetrahedra`, and each element in the container is a value associated to the tetrahedron at the same position.} * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with an integer type as value type.} - * \cgalParamDefault{corners are not written} + * \cgalParamDefault{The value `0` is written for each tetrahedron} * \cgalParamNEnd * * \cgalNamedParamsEnd From 6564c732b6342fd53298802718f76dcf9a08bed9 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 12 Oct 2026 12:52:44 +0100 Subject: [PATCH 62/72] simplify code --- SMDS_3/include/CGAL/IO/File_medit.h | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/SMDS_3/include/CGAL/IO/File_medit.h b/SMDS_3/include/CGAL/IO/File_medit.h index 8418619e4399..e5706a5e15a1 100644 --- a/SMDS_3/include/CGAL/IO/File_medit.h +++ b/SMDS_3/include/CGAL/IO/File_medit.h @@ -497,6 +497,7 @@ bool build_triangulation_from_file(std::istream& is, } std::vector edge_indices; + edge_indices.reserve(edges.size()); for(int i = 0; i < edges.size(); ++i){ Edge_with_index ewi; ewi.v0 = edges[i][0]; @@ -505,17 +506,8 @@ bool build_triangulation_from_file(std::istream& is, edge_indices.emplace_back(ewi); } - std::vector facet_indices; - for(int i = 0; i < facets.size(); ++i){ - Facet_with_index fwi; - fwi.v0 = facets[i][0]; - fwi.v1 = facets[i][1]; - fwi.v2 = facets[i][2]; - fwi.surface_patch_index = facet_refs[i]; - facet_indices.emplace_back(fwi); - } - std::vector corner_indices; + corner_indices.reserve(corners.size()); for(int i = 0; i < corners.size(); ++i){ Corner_with_index cwi; cwi.v = corners[i]; @@ -529,12 +521,12 @@ bool build_triangulation_from_file(std::istream& is, bool has_negative_surface_patch_ids = false; Surface_patch_index max_surface_patch_id{0}; - for (const Facet_with_index& fi : facet_indices) + for (int i = 0; i < facets.size(); ++i) { - if (fi.surface_patch_index<0) + if (facet_refs[i] < 0) has_negative_surface_patch_ids=true; - max_surface_patch_id=(std::max)(max_surface_patch_id, fi.surface_patch_index); - border_facets.emplace(CGAL::make_array(fi.v0, fi.v1, fi.v2), fi.surface_patch_index); + max_surface_patch_id=(std::max)(max_surface_patch_id, facet_refs[i]); + border_facets.emplace(facet[i], facet_refs[i]); } if(has_negative_surface_patch_ids) From 011901bb04195dccd9e65059de4995bb6cd55f3b Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 12 Oct 2026 13:28:16 +0100 Subject: [PATCH 63/72] fix error and warning --- SMDS_3/include/CGAL/IO/File_medit.h | 4 ++-- Stream_support/include/CGAL/IO/MEDIT.h | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/SMDS_3/include/CGAL/IO/File_medit.h b/SMDS_3/include/CGAL/IO/File_medit.h index e5706a5e15a1..2ad5c3e55134 100644 --- a/SMDS_3/include/CGAL/IO/File_medit.h +++ b/SMDS_3/include/CGAL/IO/File_medit.h @@ -516,7 +516,7 @@ bool build_triangulation_from_file(std::istream& is, } boost::unordered_map border_facets; - border_facets.reserve(facet_indices.size()); + border_facets.reserve(facets.size()); bool has_negative_surface_patch_ids = false; Surface_patch_index max_surface_patch_id{0}; @@ -526,7 +526,7 @@ bool build_triangulation_from_file(std::istream& is, if (facet_refs[i] < 0) has_negative_surface_patch_ids=true; max_surface_patch_id=(std::max)(max_surface_patch_id, facet_refs[i]); - border_facets.emplace(facet[i], facet_refs[i]); + border_facets.emplace(facets[i], facet_refs[i]); } if(has_negative_surface_patch_ids) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 022e15f63fdb..372a3f2cfc99 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -653,12 +653,9 @@ bool write_MEDIT(std::ostream& os, using parameters::get_parameter_reference; using parameters::is_default_parameter; - using Point_3 = typename PointRange::value_type; - if(!os) return false; - std::vector default_ridges, default_corners; std::vector default_tetrahedra_ref, default_triangles_ref, default_edges_ref, default_vertices_ref; std::vector> default_edges; @@ -692,7 +689,6 @@ bool write_MEDIT(std::ostream& os, using Vertices_ref = typename internal_np::Lookup_named_param_def>::reference; Vertices_ref vertices_ref = choose_parameter(get_parameter_reference(np, internal_np::vertices_ref), default_vertices_ref); - constexpr bool is_tetrahedra_ref_map = !parameters::is_default_parameter::value; constexpr bool is_triangles_ref_map = !parameters::is_default_parameter::value; constexpr bool is_edges_ref_map = !parameters::is_default_parameter::value; From 82e5dbb0124929508da8e13fa9d1be8c31952dda Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 12 Oct 2026 15:22:37 +0100 Subject: [PATCH 64/72] Changes after Mael's review --- .../internal/parameters_interface.h | 8 +- Stream_support/include/CGAL/IO/MEDIT.h | 149 +++++++++++------- .../test/Stream_support/test_MEDIT.cpp | 63 ++++---- 3 files changed, 130 insertions(+), 90 deletions(-) diff --git a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h index f74a75b6f7b7..186708fefe58 100644 --- a/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h +++ b/STL_Extension/include/CGAL/STL_Extension/internal/parameters_interface.h @@ -73,10 +73,10 @@ CGAL_add_named_parameter(tetrahedra_t, tetrahedra, tetrahedra) CGAL_add_named_parameter(edges_t, edges, edges) CGAL_add_named_parameter(ridges_t, ridges, ridges) CGAL_add_named_parameter(corners_t, corners, corners) -CGAL_add_named_parameter(tetrahedra_ref_t, tetrahedra_ref, tetrahedra_ref) -CGAL_add_named_parameter(triangles_ref_t, triangles_ref, triangles_ref) -CGAL_add_named_parameter(edges_ref_t, edges_ref, edges_ref) -CGAL_add_named_parameter(vertices_ref_t, vertices_ref, vertices_ref) +CGAL_add_named_parameter(tetrahedron_refs_t, tetrahedron_refs, tetrahedron_refs) +CGAL_add_named_parameter(triangle_refs_t, triangle_refs, triangle_refs) +CGAL_add_named_parameter(edge_refs_t, edge_refs, edge_refs) +CGAL_add_named_parameter(point_refs_t, point_refs, point_refs) // List of named parameters that we use in the package 'Mesh_3' CGAL_add_named_parameter(vertex_feature_degree_t, vertex_feature_degree, vertex_feature_degree_map) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 372a3f2cfc99..9f8c5eda443b 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -432,6 +432,13 @@ bool read_MEDIT(std::istream& is, * * \cgalNamedParamsBegin * + * \cgalParamNBegin{point_refs} + * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. + * Each element in the container corresponds to an element in `points`.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible from an integer.} + * \cgalParamDefault{entries are ignored} + * \cgalParamNEnd + * * \cgalParamNBegin{tetrahedra} * \cgalParamDescription{a non-const reference wrapper of a container of quadruples of integers that will be filled by this function. * Each element represents a tetrahedron with vertices corresponding to the four integers.} @@ -439,6 +446,13 @@ bool read_MEDIT(std::istream& is, * \cgalParamDefault{facets are ignored} * \cgalParamNEnd * + * \cgalParamNBegin{tetrahedron_refs} + * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. + * Each element in the container corresponds to an element in `tetrahedra`.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible from an integer.} + * \cgalParamDefault{entries are ignored} + * \cgalParamNEnd + * * \cgalParamNBegin{triangles} * \cgalParamDescription{a non-const reference wrapper of a container of triples of integers that will be filled by this function. * Each element represents a triangle with vertices corresponding to the three integers.} @@ -446,6 +460,13 @@ bool read_MEDIT(std::istream& is, * \cgalParamDefault{facets are ignored} * \cgalParamNEnd * + * \cgalParamNBegin{triangle_refs} + * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. + * Each element in the container corresponds to an element in `triangles`.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible from an integer.} + * \cgalParamDefault{entries are ignored} + * \cgalParamNEnd + * * \cgalParamNBegin{edges} * \cgalParamDescription{a non-const reference wrapper of a container of pairs of integers that will be filled by this function. * Each element represents an edge with vertices corresponding to the two integers.} @@ -453,6 +474,13 @@ bool read_MEDIT(std::istream& is, * \cgalParamDefault{edges are ignored} * \cgalParamNEnd * + * \cgalParamNBegin{edge_refs} + * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. + * Each element in the container corresponds to an element in `edges`.} + * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible from an integer.} + * \cgalParamDefault{entries are ignored} + * \cgalParamNEnd + * * \cgalParamNBegin{ridges} * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. * Each element in the container is an index in the sequence of edges.} @@ -467,13 +495,6 @@ bool read_MEDIT(std::istream& is, * \cgalParamDefault{corners are ignored/} * \cgalParamNEnd * - * \cgalParamNBegin{terahedra_ref} - * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. - * Each element in the container corresponds to an element in `tetrahedra`.} - * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible from an integer.} - * \cgalParamDefault{elements are ignored/} - * \cgalParamNEnd - * * \cgalParamNBegin{verbose} * \cgalParamDescription{if `true`, prints information about the reading process.} * \cgalParamType{Boolean} @@ -527,32 +548,32 @@ bool read_MEDIT(std::istream& is, using Corners = typename internal_np::Lookup_named_param_def>::reference; Corners corners = choose_parameter(get_parameter_reference(np, internal_np::corners), default_corners); - // tetrahedra_ref - std::vector default_tetrahedra_ref; - using Tetrahedra_ref = typename internal_np::Lookup_named_param_def>::reference; - Tetrahedra_ref tetrahedra_ref = choose_parameter(get_parameter_reference(np, internal_np::tetrahedra_ref), default_tetrahedra_ref); + // tetrahedron_refs + std::vector default_tetrahedron_refs; + using Tetrahedron_refs = typename internal_np::Lookup_named_param_def>::reference; + Tetrahedron_refs tetrahedron_refs = choose_parameter(get_parameter_reference(np, internal_np::tetrahedron_refs), default_tetrahedron_refs); - std::vector default_triangles_ref; - using Triangles_ref = typename internal_np::Lookup_named_param_def>::reference; - Triangles_ref triangles_ref = choose_parameter(get_parameter_reference(np, internal_np::triangles_ref), default_triangles_ref); + std::vector default_triangle_refs; + using Triangle_refs = typename internal_np::Lookup_named_param_def>::reference; + Triangle_refs triangle_refs = choose_parameter(get_parameter_reference(np, internal_np::triangle_refs), default_triangle_refs); - std::vector default_edges_ref; - using Edges_ref = typename internal_np::Lookup_named_param_def>::reference; - Edges_ref edges_ref = choose_parameter(get_parameter_reference(np, internal_np::edges_ref), default_edges_ref); + std::vector default_edge_refs; + using Edge_refs = typename internal_np::Lookup_named_param_def>::reference; + Edge_refs edge_refs = choose_parameter(get_parameter_reference(np, internal_np::edge_refs), default_edge_refs); - std::vector default_vertices_ref; - using Vertices_ref = typename internal_np::Lookup_named_param_def>::reference; - Vertices_ref vertices_ref = choose_parameter(get_parameter_reference(np, internal_np::vertices_ref), default_vertices_ref); + std::vector default_point_refs; + using Point_refs = typename internal_np::Lookup_named_param_def>::reference; + Point_refs point_refs = choose_parameter(get_parameter_reference(np, internal_np::point_refs), default_point_refs); constexpr bool is_triangles_map = !parameters::is_default_parameter::value; constexpr bool is_edges_map = !parameters::is_default_parameter::value; constexpr bool is_ridges_map = !parameters::is_default_parameter::value; constexpr bool is_corners_map = !parameters::is_default_parameter::value; - constexpr bool is_tetrahedra_ref_map = !parameters::is_default_parameter::value; - constexpr bool is_triangles_ref_map = !parameters::is_default_parameter::value; - constexpr bool is_edges_ref_map = !parameters::is_default_parameter::value; - constexpr bool is_vertices_ref_map = !parameters::is_default_parameter::value; + constexpr bool is_tetrahedron_refs_map = !parameters::is_default_parameter::value; + constexpr bool is_triangle_refs_map = !parameters::is_default_parameter::value; + constexpr bool is_edge_refs_map = !parameters::is_default_parameter::value; + constexpr bool is_point_refs_map = !parameters::is_default_parameter::value; bool is_CGAL_mesh; @@ -561,10 +582,10 @@ bool read_MEDIT(std::istream& is, edges, is_edges_map, ridges, is_ridges_map, corners, is_corners_map, - vertices_ref, is_vertices_ref_map, - tetrahedra_ref, is_tetrahedra_ref_map, - triangles_ref, is_triangles_ref_map, - edges_ref, is_edges_ref_map, + point_refs, is_point_refs_map, + tetrahedron_refs, is_tetrahedron_refs_map, + triangle_refs, is_triangle_refs_map, + edge_refs, is_edge_refs_map, verbose, is_CGAL_mesh); } @@ -590,6 +611,13 @@ bool read_MEDIT(std::istream& is, * * \cgalNamedParamsBegin * + * \cgalParamNBegin{point_refs} + * \cgalParamDescription{a const reference wrapper of a container of integers that will be written by this function. + * It must have the same size as `points`, and each element in the container is a value associated to the point at the same position.} + * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with an integer type as value type.} + * \cgalParamDefault{The value `0` is written for each point} + * \cgalParamNEnd + * * \cgalParamNBegin{tetrahedra} * \cgalParamDescription{a const reference wrapper of a container of quadruples of integers that will be written by this function. * Each element corresponds to a tetrahedron with vertices corresponding to the four integers.} @@ -597,6 +625,13 @@ bool read_MEDIT(std::istream& is, * \cgalParamDefault{tetrahedra are not written} * \cgalParamNEnd * + * \cgalParamNBegin{tetrahedron_refs} + * \cgalParamDescription{a const reference wrapper of a container of integers that will be written by this function. + * It must have the same size as `tetrahedra`, and each element in the container is a value associated to the tetrahedron at the same position.} + * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with an integer type as value type.} + * \cgalParamDefault{The value `0` is written for each tetrahedron} + * \cgalParamNEnd + * * \cgalParamNBegin{triangles} * \cgalParamDescription{a const reference wrapper of a container of triples of integers that will be written by this function. * Each element corresponds to a triangle with vertices corresponding to the three integers.} @@ -604,6 +639,13 @@ bool read_MEDIT(std::istream& is, * \cgalParamDefault{triangles are not written} * \cgalParamNEnd * + * \cgalParamNBegin{triangle_refs} + * \cgalParamDescription{a const reference wrapper of a container of integers that will be written by this function. + * It must have the same size as `triangles`, and each element in the container is a value associated to the triangle at the same position.} + * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with an integer type as value type.} + * \cgalParamDefault{The value `0` is written for each triangle} + * \cgalParamNEnd + * * \cgalParamNBegin{edges} * \cgalParamDescription{a const reference wrapper of a container of pairs of integers that will be written by this function. * Each element corresponds to an edge with vertices corresponding to the two integers.} @@ -611,6 +653,13 @@ bool read_MEDIT(std::istream& is, * \cgalParamDefault{edges are not written} * \cgalParamNEnd * + * \cgalParamNBegin{edge_refs} + * \cgalParamDescription{a const reference wrapper of a container of integers that will be written by this function. + * It must have the same size as `edges`, and each element in the container is a value associated to the edge at the same position.} + * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with an integer type as value type.} + * \cgalParamDefault{The value `0` is written for each edge} + * \cgalParamNEnd + * * \cgalParamNBegin{ridges} * \cgalParamDescription{a const reference wrapper of a container of integers that will be written by this function. * Each element in the container is an index in the sequence of edges.} @@ -625,12 +674,6 @@ bool read_MEDIT(std::istream& is, * \cgalParamDefault{corners are not written} * \cgalParamNEnd * - * \cgalParamNBegin{tetrahedra_ref} - * \cgalParamDescription{a const reference wrapper of a container of integers that will be written by this function. - * It must have the same size as `tetrahedra`, and each element in the container is a value associated to the tetrahedron at the same position.} - * \cgalParamType{a `std::reference_wrapper` to a model of `SequenceContainer` with an integer type as value type.} - * \cgalParamDefault{The value `0` is written for each tetrahedron} - * \cgalParamNEnd * * \cgalNamedParamsEnd * @@ -657,7 +700,7 @@ bool write_MEDIT(std::ostream& os, return false; std::vector default_ridges, default_corners; - std::vector default_tetrahedra_ref, default_triangles_ref, default_edges_ref, default_vertices_ref; + std::vector default_tetrahedron_refs, default_triangle_refs, default_edge_refs, default_point_refs; std::vector> default_edges; std::vector> default_facets; std::vector> default_cells; @@ -677,22 +720,22 @@ bool write_MEDIT(std::ostream& os, using corners = typename internal_np::Lookup_named_param_def>>::reference; corners vertices = choose_parameter(get_parameter_reference(np, internal_np::corners), default_corners); - using Tetrahedra_ref = typename internal_np::Lookup_named_param_def>::reference; - Tetrahedra_ref tetrahedra_ref = choose_parameter(get_parameter_reference(np, internal_np::tetrahedra_ref), default_tetrahedra_ref); + using Tetrahedron_refs = typename internal_np::Lookup_named_param_def>::reference; + Tetrahedron_refs tetrahedron_refs = choose_parameter(get_parameter_reference(np, internal_np::tetrahedron_refs), default_tetrahedron_refs); - using Triangles_ref = typename internal_np::Lookup_named_param_def>::reference; - Triangles_ref triangles_ref = choose_parameter(get_parameter_reference(np, internal_np::triangles_ref), default_triangles_ref); + using Triangle_refs = typename internal_np::Lookup_named_param_def>::reference; + Triangle_refs triangle_refs = choose_parameter(get_parameter_reference(np, internal_np::triangle_refs), default_triangle_refs); - using Edges_ref = typename internal_np::Lookup_named_param_def>::reference; - Edges_ref edges_ref = choose_parameter(get_parameter_reference(np, internal_np::edges_ref), default_edges_ref); + using Edge_refs = typename internal_np::Lookup_named_param_def>::reference; + Edge_refs edge_refs = choose_parameter(get_parameter_reference(np, internal_np::edge_refs), default_edge_refs); - using Vertices_ref = typename internal_np::Lookup_named_param_def>::reference; - Vertices_ref vertices_ref = choose_parameter(get_parameter_reference(np, internal_np::vertices_ref), default_vertices_ref); + using Point_refs = typename internal_np::Lookup_named_param_def>::reference; + Point_refs point_refs = choose_parameter(get_parameter_reference(np, internal_np::point_refs), default_point_refs); - constexpr bool is_tetrahedra_ref_map = !parameters::is_default_parameter::value; - constexpr bool is_triangles_ref_map = !parameters::is_default_parameter::value; - constexpr bool is_edges_ref_map = !parameters::is_default_parameter::value; - constexpr bool is_vertices_ref_map = !parameters::is_default_parameter::value; + constexpr bool is_tetrahedron_refs_map = !parameters::is_default_parameter::value; + constexpr bool is_triangle_refs_map = !parameters::is_default_parameter::value; + constexpr bool is_edge_refs_map = !parameters::is_default_parameter::value; + constexpr bool is_point_refs_map = !parameters::is_default_parameter::value; os << "MeshVersionFormatted 1\nDimension 3\n"; @@ -700,7 +743,7 @@ bool write_MEDIT(std::ostream& os, os << points.size() << "\n"; for (std::size_t k = 0; k < points.size(); ++k){ const auto& p = points[k]; - int ref = is_vertices_ref_map ? vertices_ref[k] : 0; + int ref = is_point_refs_map ? point_refs[k] : 0; os << p << " " << ref << "\n"; } @@ -708,7 +751,7 @@ bool write_MEDIT(std::ostream& os, os << cells.size() << "\n"; for (std::size_t k=0; k < cells.size(); ++k) { - int ref = is_tetrahedra_ref_map ? tetrahedra_ref[k] : 0; + int ref = is_tetrahedron_refs_map ? tetrahedron_refs[k] : 0; os << cells[k][0]+1 << " " << cells[k][1]+1 << " " << cells[k][2]+1 << " " @@ -720,20 +763,16 @@ bool write_MEDIT(std::ostream& os, os << "Edges\n" << edges.size() << "\n"; for(std::size_t k = 0; k < edges.size(); ++k){ const auto& e = edges[k]; - int ref = is_edges_ref_map ? edges_ref[k] : 0; + int ref = is_edge_refs_map ? edge_refs[k] : 0; os << internal::get_zero(e) +1 << " " << internal::get_one(e) + 1 << " " << ref << "\n"; } - - os << "Ridges\n" << edges.size() << "\n"; - for(std::size_t i = 1; i <= edges.size(); ++i) - os << i << "\n"; } if(!facets.empty()){ os << "Triangles\n" << facets.size() << "\n"; for(std::size_t k = 0; k < facets.size(); ++k){ const auto& f = facets[k]; - int ref = is_triangles_ref_map ? triangles_ref[k]: 0; + int ref = is_triangle_refs_map ? triangle_refs[k]: 0; os << std::get<0>(f) +1 << " " << std::get<1>(f) + 1 << " " << std::get<2>(f) + 1 << " " << ref << "\n"; } } diff --git a/Stream_support/test/Stream_support/test_MEDIT.cpp b/Stream_support/test/Stream_support/test_MEDIT.cpp index a83b1ba82461..fdc726b00ef1 100644 --- a/Stream_support/test/Stream_support/test_MEDIT.cpp +++ b/Stream_support/test/Stream_support/test_MEDIT.cpp @@ -22,31 +22,32 @@ int main() { std::deque corners; std::vector point_refs, cell_refs, facet_refs, edge_refs; - std::cout << "A " << & cell_refs << std::endl; - - bool success = CGAL::IO::read_MEDIT(input, points, CGAL::parameters::tetrahedra(std::ref(cells)) - .triangles(std::ref(facets)) - .edges(std::ref(edges)) - .ridges(std::ref(ridges)) - .corners(std::ref(corners)) - .tetrahedra_ref(std::ref(cell_refs)) - .triangles_ref(std::ref(facet_refs)) - .edges_ref(std::ref(edge_refs)) - .vertices_ref(std::ref(point_refs)) - .verbose(false)); + bool success = CGAL::IO::read_MEDIT(input, points, CGAL::parameters::point_refs(std::ref(point_refs)) + .tetrahedra(std::ref(cells)) + .tetrahedron_refs(std::ref(cell_refs)) + .triangles(std::ref(facets)) + .triangle_refs(std::ref(facet_refs)) + .edges(std::ref(edges)) + .edge_refs(std::ref(edge_refs)) + .ridges(std::ref(ridges)) + .corners(std::ref(corners)) + .verbose(false)); assert(success); std::ostringstream output; output.precision(17); - CGAL::IO::write_MEDIT(output, points, CGAL::parameters::tetrahedra(std::cref(cells)) - .triangles(std::cref(facets)) - .edges(std::cref(edges)) - .ridges(std::cref(ridges)) - .corners(std::cref(corners)) - .tetrahedra_ref(std::cref(cell_refs)) - .triangles_ref(std::cref(facet_refs)) - .edges_ref(std::cref(edge_refs)) - .vertices_ref(std::cref(point_refs))); + CGAL::IO::write_MEDIT(output, points, CGAL::parameters::point_refs(std::cref(point_refs)) + .tetrahedra(std::cref(cells)) + .tetrahedron_refs(std::cref(cell_refs)) + .triangles(std::cref(facets)) + .triangle_refs(std::cref(facet_refs)) + .edges(std::cref(edges)) + .edge_refs(std::cref(edge_refs)) + .ridges(std::cref(ridges)) + .corners(std::cref(corners)) + + + ); std::istringstream input_bis(output.str()); std::vector points_bis; @@ -57,16 +58,16 @@ int main() { std::deque corners_bis; std::vector point_refs_bis, cell_refs_bis, facet_refs_bis, edge_refs_bis; - success = CGAL::IO::read_MEDIT(input_bis, points_bis, CGAL::parameters::tetrahedra(std::ref(cells_bis)) - .triangles(std::ref(facets_bis)) - .edges(std::ref(edges_bis)) - .ridges(std::ref(ridges_bis)) - .corners(std::ref(corners_bis)) - .tetrahedra_ref(std::ref(cell_refs_bis)) - .triangles_ref(std::ref(facet_refs_bis)) - .edges_ref(std::ref(edge_refs_bis)) - .vertices_ref(std::ref(point_refs_bis)) - .verbose(false)); + success = CGAL::IO::read_MEDIT(input_bis, points_bis, CGAL::parameters::point_refs(std::ref(point_refs_bis)) + .tetrahedra(std::ref(cells_bis)) + .tetrahedron_refs(std::ref(cell_refs_bis)) + .triangles(std::ref(facets_bis)) + .triangle_refs(std::ref(facet_refs_bis)) + .edges(std::ref(edges_bis)) + .edge_refs(std::ref(edge_refs_bis)) + .ridges(std::ref(ridges_bis)) + .corners(std::ref(corners_bis)) + .verbose(false)); assert(points== points_bis); assert(cells == cells_bis); From 45d564e5aa8153a35d5ed6944387a23e18879722 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 12 Oct 2026 16:36:16 +0100 Subject: [PATCH 65/72] warnings --- SMDS_3/include/CGAL/IO/File_medit.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/SMDS_3/include/CGAL/IO/File_medit.h b/SMDS_3/include/CGAL/IO/File_medit.h index 2ad5c3e55134..ffbc2cb2ad4c 100644 --- a/SMDS_3/include/CGAL/IO/File_medit.h +++ b/SMDS_3/include/CGAL/IO/File_medit.h @@ -460,7 +460,6 @@ bool build_triangulation_from_file(std::istream& is, using Facet = std::array; // 3 = id using Tet = std::array; // 4 = id - using Facet_with_index = CGAL::IO::internal::Facet_with_patch_index; using Edge_with_index = CGAL::IO::internal::Edge_with_curve_index; using Corner_with_index = CGAL::IO::internal::Vertex_with_corner_index; @@ -498,7 +497,7 @@ bool build_triangulation_from_file(std::istream& is, std::vector edge_indices; edge_indices.reserve(edges.size()); - for(int i = 0; i < edges.size(); ++i){ + for(std::size_t i = 0; i < edges.size(); ++i){ Edge_with_index ewi; ewi.v0 = edges[i][0]; ewi.v1 = edges[i][1]; @@ -508,7 +507,7 @@ bool build_triangulation_from_file(std::istream& is, std::vector corner_indices; corner_indices.reserve(corners.size()); - for(int i = 0; i < corners.size(); ++i){ + for(std::size_t i = 0; i < corners.size(); ++i){ Corner_with_index cwi; cwi.v = corners[i]; cwi.corner_index = point_refs[i]; @@ -521,7 +520,7 @@ bool build_triangulation_from_file(std::istream& is, bool has_negative_surface_patch_ids = false; Surface_patch_index max_surface_patch_id{0}; - for (int i = 0; i < facets.size(); ++i) + for (std::size_t i = 0; i < facets.size(); ++i) { if (facet_refs[i] < 0) has_negative_surface_patch_ids=true; From a1c58c0378890dab6f6c49d832031c9dffddf9b3 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 12 Oct 2026 16:43:21 +0100 Subject: [PATCH 66/72] error --- SMDS_3/include/CGAL/IO/File_medit.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SMDS_3/include/CGAL/IO/File_medit.h b/SMDS_3/include/CGAL/IO/File_medit.h index ffbc2cb2ad4c..a3334db14e60 100644 --- a/SMDS_3/include/CGAL/IO/File_medit.h +++ b/SMDS_3/include/CGAL/IO/File_medit.h @@ -524,7 +524,8 @@ bool build_triangulation_from_file(std::istream& is, { if (facet_refs[i] < 0) has_negative_surface_patch_ids=true; - max_surface_patch_id=(std::max)(max_surface_patch_id, facet_refs[i]); + if(facet_refs[i] > max_surface_patch_id) + max_surface_patch_id= facet_refs[i]; border_facets.emplace(facets[i], facet_refs[i]); } From 263a48217a80fd4818ec72936d62c09350c69aab Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 12 Oct 2026 16:48:44 +0100 Subject: [PATCH 67/72] warnings --- SMDS_3/include/CGAL/IO/File_medit.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SMDS_3/include/CGAL/IO/File_medit.h b/SMDS_3/include/CGAL/IO/File_medit.h index a3334db14e60..9bfbb7ca07e9 100644 --- a/SMDS_3/include/CGAL/IO/File_medit.h +++ b/SMDS_3/include/CGAL/IO/File_medit.h @@ -518,14 +518,14 @@ bool build_triangulation_from_file(std::istream& is, border_facets.reserve(facets.size()); bool has_negative_surface_patch_ids = false; - Surface_patch_index max_surface_patch_id{0}; + int max_surface_patch_id{0}; for (std::size_t i = 0; i < facets.size(); ++i) { if (facet_refs[i] < 0) has_negative_surface_patch_ids=true; - if(facet_refs[i] > max_surface_patch_id) - max_surface_patch_id= facet_refs[i]; + else if(facet_refs[i] > max_surface_patch_id) + max_surface_patch_id= facet_refs[i]; border_facets.emplace(facets[i], facet_refs[i]); } From 54aabccd42113a01d739fb785210992e0ee1b4a6 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 13 Oct 2026 10:25:10 +0100 Subject: [PATCH 68/72] Fix for LCC example --- .../examples/Linear_cell_complex/tetsoup_to_lcc.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Linear_cell_complex/examples/Linear_cell_complex/tetsoup_to_lcc.cpp b/Linear_cell_complex/examples/Linear_cell_complex/tetsoup_to_lcc.cpp index a29ec0714ce6..cde3eff5bec4 100644 --- a/Linear_cell_complex/examples/Linear_cell_complex/tetsoup_to_lcc.cpp +++ b/Linear_cell_complex/examples/Linear_cell_complex/tetsoup_to_lcc.cpp @@ -2,10 +2,11 @@ #include #include #include +#include + #include #include -#include using LCC = CGAL::Linear_cell_complex_for_combinatorial_map<3, 3>; using Point_3 = CGAL::Exact_predicates_inexact_constructions_kernel::Point_3; @@ -23,8 +24,7 @@ int main(int argc, char** argv) std::cerr << "Cannot open " << filename << std::endl; return 1; } - - CGAL::IO::read_MEDIT(in, points, tetras, CGAL::parameters::subdomain_indices(std::ref(subdomains))); + CGAL::IO::read_MEDIT(in, points, CGAL::parameters::tetrahedra(std::ref(tetras)).tetrahedron_refs(std::ref(subdomains))); //filter out subdomain 0 std::vector> filtered_tetras; @@ -32,8 +32,10 @@ int main(int argc, char** argv) if (subdomains[i]!=0) filtered_tetras.push_back(tetras[i]); + std::cout << points.size() << " " << filtered_tetras.size() << std::endl; LCC lcc; CGAL::tetrahedron_soup_to_lcc(lcc, points, filtered_tetras); CGAL::draw(lcc); + return 0; } From 7efa907be763c4ef2759085c8646e439025059ff Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 15 Oct 2026 10:14:55 +0200 Subject: [PATCH 69/72] Apply batched suggestions from code review Co-authored-by: Mael --- Stream_support/include/CGAL/IO/MEDIT.h | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 9f8c5eda443b..4096cdeb4c6b 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -415,10 +415,6 @@ bool read_MEDIT(std::istream& is, * * \brief reads the content of `is` into `points` and the named parameters using the \ref IOStreamMedit. * - * The subdomain index corresponds to what \medit calls cell reference, - * facet patch index corresponds to triangle reference, - * edge curve index to edge reference, - * and vertex corner index to vertex reference. * * \note Currently, only tetrahedral cells are supported. * \note The cell soup is not cleared, and the data from the stream are appended. @@ -436,63 +432,63 @@ bool read_MEDIT(std::istream& is, * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. * Each element in the container corresponds to an element in `points`.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible from an integer.} - * \cgalParamDefault{entries are ignored} + * \cgalParamDefault{point references are ignored.} * \cgalParamNEnd * * \cgalParamNBegin{tetrahedra} * \cgalParamDescription{a non-const reference wrapper of a container of quadruples of integers that will be filled by this function. * Each element represents a tetrahedron with vertices corresponding to the four integers.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of four integers.} - * \cgalParamDefault{facets are ignored} + * \cgalParamDefault{tetrahedra are ignored.} * \cgalParamNEnd * * \cgalParamNBegin{tetrahedron_refs} * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. * Each element in the container corresponds to an element in `tetrahedra`.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible from an integer.} - * \cgalParamDefault{entries are ignored} + * \cgalParamDefault{tetrahedron references are ignored.} * \cgalParamNEnd * * \cgalParamNBegin{triangles} * \cgalParamDescription{a non-const reference wrapper of a container of triples of integers that will be filled by this function. * Each element represents a triangle with vertices corresponding to the three integers.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of three integers.} - * \cgalParamDefault{facets are ignored} + * \cgalParamDefault{triangles are ignored.} * \cgalParamNEnd * * \cgalParamNBegin{triangle_refs} * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. * Each element in the container corresponds to an element in `triangles`.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible from an integer.} - * \cgalParamDefault{entries are ignored} + * \cgalParamDefault{triangle references are ignored} * \cgalParamNEnd * * \cgalParamNBegin{edges} * \cgalParamDescription{a non-const reference wrapper of a container of pairs of integers that will be filled by this function. * Each element represents an edge with vertices corresponding to the two integers.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible using a braced initializer list of two integers.} - * \cgalParamDefault{edges are ignored} + * \cgalParamDefault{edges are ignored.} * \cgalParamNEnd * * \cgalParamNBegin{edge_refs} * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. * Each element in the container corresponds to an element in `edges`.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible from an integer.} - * \cgalParamDefault{entries are ignored} + * \cgalParamDefault{edge references are ignored} * \cgalParamNEnd * * \cgalParamNBegin{ridges} * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. * Each element in the container is an index in the sequence of edges.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible from an integer.} - * \cgalParamDefault{ridges are ignored} + * \cgalParamDefault{ridges are ignored.} * \cgalParamNEnd * * \cgalParamNBegin{corners} * \cgalParamDescription{a non-const reference wrapper of a container of integers that will be filled by this function. * Each element in the container is an index in the sequence of points.} * \cgalParamType{a `std::reference_wrapper` to a model of `BackInsertionSequence` with a value type constructible from an integer.} - * \cgalParamDefault{corners are ignored/} + * \cgalParamDefault{corners are ignored.} * \cgalParamNEnd * * \cgalParamNBegin{verbose} From 91f19f97dd9139f337109153a4a110e6bea4d412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 15 Oct 2026 10:44:35 +0200 Subject: [PATCH 70/72] try to better detect curve index type --- Stream_support/include/CGAL/IO/MEDIT.h | 44 ++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 4096cdeb4c6b..4d24a0647257 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -44,29 +44,33 @@ struct Facet_with_patch_index }; template -struct get_surface_path_index_type +struct Get_surface_path_index_type { using type = int; }; template -struct get_surface_path_index_type> +struct Get_surface_path_index_type> { using type = SurfacePatchIndex; }; template -struct get_surface_path_index_type> +struct Get_surface_path_index_type> { using type = I; }; template -struct get_surface_path_index_type> +struct Get_surface_path_index_type> { using type = I; }; +template +using Surface_path_index_t = + typename Get_surface_path_index_type::value_type>::type; + template struct Edge_with_curve_index { @@ -74,6 +78,34 @@ struct Edge_with_curve_index CurveIndex curve_index; }; +template +struct Get_curve_index_type +{ + using type = int; +}; + +template +struct Get_curve_index_type> +{ + using type = CurveIndex; +}; + +template +struct Get_curve_index_type> +{ + using type = I; +}; + +template +struct Get_curve_index_type> +{ + using type = I; +}; + +template +using Curve_index_t = + typename Get_curve_index_type::value_type>::type; + template struct Vertex_with_corner_index { @@ -248,7 +280,7 @@ bool read_MEDIT(std::istream& is, for(int i=0; i::value_type>::type surface_patch_id; + Surface_path_index_t surface_patch_id; if(!(is >> n[0] >> n[1] >> n[2] >> surface_patch_id)) { if(verbose) @@ -343,7 +375,7 @@ bool read_MEDIT(std::istream& is, for(int i = 0; i < nedges; ++i) { int n[2]; - /* AF: was Curve_index*/ int ref = 0; + Curve_index_t ref = 0; if(!(is >> n[0] >> n[1] >> ref)) { if(verbose) From 4749c37d70dc66e35e40279e13ad9d4e09d6d682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 15 Oct 2026 10:57:41 +0200 Subject: [PATCH 71/72] static_assert to make sure containers passed are reference wrappers --- Stream_support/include/CGAL/IO/MEDIT.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index 4d24a0647257..c64797118f95 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -554,43 +554,52 @@ bool read_MEDIT(std::istream& is, // cells std::vector> default_tetrahedra; using Tetrahedra = typename internal_np::Lookup_named_param_def>>::reference; + static_assert(std::is_reference_v || !"tetrahedra named parameter must be a reference_wrapper"); Tetrahedra tetrahedra = choose_parameter(get_parameter_reference(np, internal_np::tetrahedra), default_tetrahedra); // triangles std::vector> default_triangles; using Triangles = typename internal_np::Lookup_named_param_def>>::reference; + static_assert(std::is_reference_v || !"triangles named parameter must be a reference_wrapper"); Triangles triangles = choose_parameter(get_parameter_reference(np, internal_np::triangles), default_triangles); // edges std::vector> default_edges; using Edges = typename internal_np::Lookup_named_param_def>>::reference; + static_assert(std::is_reference_v || !"edges named parameter must be a reference_wrapper"); Edges edges = choose_parameter(get_parameter_reference(np, internal_np::edges), default_edges); // ridges std::vector default_ridges; using Ridges = typename internal_np::Lookup_named_param_def>::reference; + static_assert(std::is_reference_v || !"ridges named parameter must be a reference_wrapper"); Ridges ridges = choose_parameter(get_parameter_reference(np, internal_np::ridges), default_ridges); // corners std::vector default_corners; using Corners = typename internal_np::Lookup_named_param_def>::reference; + static_assert(std::is_reference_v || !"corners named parameter must be a reference_wrapper"); Corners corners = choose_parameter(get_parameter_reference(np, internal_np::corners), default_corners); // tetrahedron_refs std::vector default_tetrahedron_refs; using Tetrahedron_refs = typename internal_np::Lookup_named_param_def>::reference; + static_assert(std::is_reference_v || !"tetrahedron_refs named parameter must be a reference_wrapper"); Tetrahedron_refs tetrahedron_refs = choose_parameter(get_parameter_reference(np, internal_np::tetrahedron_refs), default_tetrahedron_refs); std::vector default_triangle_refs; using Triangle_refs = typename internal_np::Lookup_named_param_def>::reference; + static_assert(std::is_reference_v || !"triangle_refs named parameter must be a reference_wrapper"); Triangle_refs triangle_refs = choose_parameter(get_parameter_reference(np, internal_np::triangle_refs), default_triangle_refs); std::vector default_edge_refs; using Edge_refs = typename internal_np::Lookup_named_param_def>::reference; + static_assert(std::is_reference_v || !"edge_refs named parameter must be a reference_wrapper"); Edge_refs edge_refs = choose_parameter(get_parameter_reference(np, internal_np::edge_refs), default_edge_refs); std::vector default_point_refs; using Point_refs = typename internal_np::Lookup_named_param_def>::reference; + static_assert(std::is_reference_v || !"point_refs named parameter must be a reference_wrapper"); Point_refs point_refs = choose_parameter(get_parameter_reference(np, internal_np::point_refs), default_point_refs); constexpr bool is_triangles_map = !parameters::is_default_parameter::value; From 83a26f183ec84e0abb1ef75cd4cd6c25b9f0806c Mon Sep 17 00:00:00 2001 From: Sebastien Loriot Date: Fri, 16 Oct 2026 11:29:25 +0200 Subject: [PATCH 72/72] Cleanup from Mael's review Co-authored-by: Mael --- Stream_support/include/CGAL/IO/MEDIT.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Stream_support/include/CGAL/IO/MEDIT.h b/Stream_support/include/CGAL/IO/MEDIT.h index c64797118f95..f830b56313c0 100644 --- a/Stream_support/include/CGAL/IO/MEDIT.h +++ b/Stream_support/include/CGAL/IO/MEDIT.h @@ -632,12 +632,8 @@ bool read_MEDIT(std::istream& is, * * \brief writes a soup of indexed cells using the \ref IOStreamMedit. * - * The subdomain index corresponds to what \medit calls cell reference, - * facet patch index corresponds to triangle reference, - * edge curve index to edge reference, - * and vertex corner index to vertex reference. - * \note Currently only tetrahedral cells are supported. + * \note Currently, only tetrahedral cells are supported. * * \tparam PointRange a model of `ConstRange` whose value type is the point type *