1 // Copyright (c) 2019 Geometry Factory
2 // All rights reserved.
3 //
4 // This file is part of CGAL (www.cgal.org)
5 //
6 // $URL: https://github.com/CGAL/cgal/blob/v5.3/Surface_mesh/include/CGAL/Surface_mesh/IO/3MF.h $
7 // $Id: 3MF.h 56025fb 2021-05-04T14:38:47+02:00 Sébastien Loriot
8 // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
9 //
10 // Author(s) : Maxime Gimeno
11
12 #ifndef CGAL_SURFACE_MESH_IO_3MF_H
13 #define CGAL_SURFACE_MESH_IO_3MF_H
14
15 #include <CGAL/license/Surface_mesh.h>
16
17 #include <CGAL/Surface_mesh/Surface_mesh_fwd.h>
18
19 #include <CGAL/IO/3MF.h>
20
21 #include <iostream>
22 #include <string>
23 #include <vector>
24
25 #if defined(CGAL_LINKED_WITH_3MF) || defined(DOXYGEN_RUNNING)
26
27 #ifdef DOXYGEN_RUNNING
28 #define CGAL_DEPRECATED
29 #endif
30
31 namespace CGAL {
32
33 namespace IO {
34
35 // @todo generalize it to any model of `FaceGraph` and put it in BGL/IO (see read_OFF for the face color map)
36
37 /*!
38 * \ingroup PkgSurfaceMeshIOFunc3MF
39 *
40 * \brief extracts the surface meshes from an input 3mf file and appends it to `output`.
41 *
42 * \tparam Point The type of the \em point property of a vertex. There is no requirement on `P`,
43 * besides being default constructible and assignable.
44 * In typical use cases it will be a 2D or 3D point type.
45 *
46 * \param filename the path to the 3mf file
47 * \param output a `std::vector` containing the `CGAL::Surface_mesh`s that will be filled by this function
48 *
49 * \returns `true` if reading was successful, `false` otherwise.
50 */
51 template<typename Point>
read_3MF(const std::string & filename,std::vector<CGAL::Surface_mesh<Point>> & output)52 bool read_3MF(const std::string& filename,
53 std::vector<CGAL::Surface_mesh<Point> >& output)
54 {
55 typedef std::vector<Point> PointRange;
56 typedef std::vector<std::size_t> Triangle;
57 typedef std::vector<Triangle> TriangleRange;
58 typedef CGAL::Surface_mesh<Point> SMesh;
59 typedef typename SMesh::Vertex_index Vertex_index;
60 typedef typename SMesh::Face_index Face_index;
61
62 std::vector<PointRange> all_points;
63 std::vector<TriangleRange> all_triangles;
64 std::vector<std::string> names;
65 std::vector<std::vector<CGAL::IO::Color> > all_colors;
66
67 const bool success = CGAL::IO::read_3MF(filename, all_points, all_triangles, all_colors, names);
68 if(!success)
69 {
70 std::cerr << "Error in reading meshes." << std::endl;
71 return false;
72 }
73
74 const std::size_t nb_meshes = all_points.size();
75 int result = 0;
76 output.reserve(nb_meshes);
77
78 for(std::size_t i=0; i<nb_meshes; ++i)
79 {
80 bool skip = false;
81 SMesh sm;
82 TriangleRange triangles = all_triangles[i];
83 PointRange points = all_points[i];
84 std::vector<CGAL::IO::Color> colors = all_colors[i];
85
86 // Create the surface mesh from scratch
87 std::size_t n(points.size());
88 sm.reserve(n, 0, triangles.size());
89 for(const Point& p : points)
90 sm.add_vertex(p);
91
92 for(Triangle& triangle : triangles)
93 {
94 std::vector<Vertex_index> face;
95 face.reserve(triangle.size());
96 for(std::size_t index : triangle)
97 face.push_back(Vertex_index(index));
98
99 Face_index fi = sm.add_face(face);
100 if(fi == sm.null_face())
101 {
102 skip = true;
103 sm.clear();
104 break;
105 }
106 }
107
108 if(skip)
109 continue;
110
111 const Color& first = colors.front();
112 bool need_pmap = false;
113 for(const Color& color : colors)
114 {
115 if(color != first)
116 {
117 need_pmap = true;
118 break;
119 }
120 }
121
122 if(need_pmap)
123 {
124 typename SMesh::template Property_map<Face_index, CGAL::IO::Color> fcolor =
125 sm.template add_property_map<Face_index,CGAL::IO::Color>("f:color", first).first;
126
127 for(std::size_t pid=0, cs=colors.size(); pid<cs; ++pid)
128 put(fcolor, Face_index(pid), colors[pid]); // there can't have any deleted face yet
129 }
130
131 output.push_back(sm);
132 ++result;
133 }
134
135 return true;
136 }
137
138 } // namespace IO
139
140 #ifndef CGAL_NO_DEPRECATED_CODE
141
142 /*!
143 \ingroup PkgSurfaceMeshIOFuncDeprecated
144 \deprecated This function is deprecated since \cgal 5.3, `CGAL::IO::read_3MF()` should be used instead.
145 */
146 template<typename Point>
read_3mf(const std::string & filename,std::vector<CGAL::Surface_mesh<Point>> & output)147 CGAL_DEPRECATED int read_3mf(const std::string& filename, std::vector<CGAL::Surface_mesh<Point> >& output)
148 {
149 return IO::read_3MF(filename, output);
150 }
151
152 #endif // CGAL_NO_DEPRECATED_CODE
153
154 } // namespace CGAL
155
156 #endif // defined(CGAL_LINKED_WITH_3MF) || defined(DOXYGEN_RUNNING)
157
158 #endif // CGAL_SURFACE_MESH_IO_3MF_H
159