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