Point Cloud Library (PCL) 1.15.0
Loading...
Searching...
No Matches
mesh_io.h
1/*
2 * Software License Agreement (BSD License)
3 *
4 * Point Cloud Library (PCL) - www.pointclouds.org
5 * Copyright (c) 2009-2012, Willow Garage, Inc.
6 * Copyright (c) 2012-, Open Perception, Inc.
7 *
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * * Redistributions in binary form must reproduce the above
17 * copyright notice, this list of conditions and the following
18 * disclaimer in the documentation and/or other materials provided
19 * with the distribution.
20 * * Neither the name of the copyright holder(s) nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 *
37 * $Id$
38 *
39 */
40
41#pragma once
42
43#include <fstream>
44#include <iostream>
45#include <sstream>
46#include <string>
47
48namespace pcl {
49namespace geometry {
50/** \brief Read / write the half-edge mesh from / to a file.
51 * \tparam MeshT e.g. pcl::geometry::TriangleMesh or pcl::geometry::PolygonMesh
52 * \author Martin Saelzle
53 * \ingroup geometry
54 * \todo
55 * - Only writes the topology (not the mesh data).
56 * - Supports only ascii.
57 * - Does not consider the mesh traits (e.g. manifold or not)
58 */
59template <class MeshT>
60class MeshIO {
61public:
62 using Mesh = MeshT;
63
64 using Vertex = typename Mesh::Vertex;
65 using HalfEdge = typename Mesh::HalfEdge;
66 using Face = typename Mesh::Face;
67
68 using Vertices = typename Mesh::Vertices;
69 using HalfEdges = typename Mesh::HalfEdges;
70 using Faces = typename Mesh::Faces;
71
72 using VertexIndex = typename Mesh::VertexIndex;
73 using HalfEdgeIndex = typename Mesh::HalfEdgeIndex;
74 using FaceIndex = typename Mesh::FaceIndex;
75
76 /** \brief Constructor. */
77 MeshIO() = default;
78
79 /** \brief Read the mesh from a file with the given filename.
80 * \param[in] filename Path to the file.
81 * \param[out] mesh The loaded mesh.
82 * \return true if success.
83 */
84 bool
85 read(const std::string& filename, Mesh& mesh) const
86 {
87 std::ifstream file(filename.c_str());
88
89 if (!file.is_open()) {
90 std::cerr << "Error in MeshIO::read: Could not open the file '" << filename
91 << "'\n";
92 return (false);
93 }
94
95 // Read the header
96 std::string line;
97 unsigned int line_number = 1;
98 int n_v = -1, n_he = -1, n_f = -1;
99
100 if (!std::getline(file, line) || line != "PCL half-edge mesh") {
101 std::cerr << "Error loading '" << filename << "' (line " << line_number
102 << "): Wrong file format.\n";
103 return (false);
104 }
105 ++line_number;
106
107 if (!std::getline(file, line)) {
108 std::cerr << "Error loading '" << filename << "'' (line " << line_number
109 << "): Number of vertices / half-edges / faces not found.\n";
110 return (false);
111 }
112 {
113 std::istringstream iss(line);
114 if (!(iss >> n_v >> n_he >> n_f) || iss.good()) // Don't allow more than 3 en
115 {
116 std::cerr << "Error loading '" << filename << "'' (line " << line_number
117 << "): Could not read the number of vertices / half-edges / faces.\n";
118 return (false);
119 }
120 }
121 if (n_v < 0 || n_he < 0 || n_f < 0) {
122 std::cerr << "Error loading '" << filename << "'' (line " << line_number
123 << "): Invalid number of vertices / half-edges / faces.\n";
124 return (false);
125 }
126 ++line_number;
127
128 // Read the vertices.
129 {
130 mesh.vertices_.reserve(n_v);
131 HalfEdgeIndex idx_ohe; // Outgoing half-edge;
132
133 for (int i = 0; i < n_v; ++i, ++line_number) {
134 if (!std::getline(file, line)) {
135 std::cerr << "Error loading '" << filename << "'' (line " << line_number
136 << "): Could not read the line.\n";
137 return (false);
138 }
139
140 std::istringstream iss(line);
141 if (!(iss >> idx_ohe) || iss.good()) {
142 std::cerr << "Error loading '" << filename << "'' (line " << line_number
143 << "): Could not read the vertex.\n";
144 return (false);
145 }
146 mesh.vertices_.push_back(Vertex(idx_ohe));
147 }
148 }
149
150 // Read the half-edges.
151 {
152 mesh.half_edges_.reserve(n_he);
153 VertexIndex idx_tv; // Terminating vertex.
154 HalfEdgeIndex idx_nhe; // Next half-edge;
155 HalfEdgeIndex idx_phe; // Previous half-edge.
156 FaceIndex idx_f; // Face.
157
158 for (int i = 0; i < n_he; ++i, ++line_number) {
159 if (!std::getline(file, line)) {
160 std::cerr << "Error loading '" << filename << "'' (line " << line_number
161 << "): Could not read the line.\n";
162 return (false);
163 }
164
165 std::istringstream iss(line);
166 if (!(iss >> idx_tv >> idx_nhe >> idx_phe >> idx_f) || iss.good()) {
167 std::cerr << "Error loading '" << filename << "'' (line " << line_number
168 << "): Could not read the half-edge.\n";
169 return (false);
170 }
171 mesh.half_edges_.push_back(HalfEdge(idx_tv, idx_nhe, idx_phe, idx_f));
172 }
173 }
174
175 // Read the faces.
176 {
177 mesh.faces_.reserve(n_f);
178 HalfEdgeIndex idx_ihe; // Inner half-edge.
179
180 for (int i = 0; i < n_f; ++i, ++line_number) {
181 if (!std::getline(file, line)) {
182 std::cerr << "Error loading '" << filename << "'' (line " << line_number
183 << "): Could not read the line.\n";
184 return (false);
185 }
186
187 std::istringstream iss(line);
188 if (!(iss >> idx_ihe) || iss.good()) {
189 std::cerr << "Error loading '" << filename << "'' (line " << line_number
190 << "): Could not read the face.\n";
191 return (false);
192 }
193 mesh.faces_.push_back(Face(idx_ihe));
194 }
195 }
196
197 // Set the data
198 if (Mesh::HasVertexData::value)
199 mesh.vertex_data_cloud_.resize(n_v);
200 if (Mesh::HasHalfEdgeData::value)
201 mesh.half_edge_data_cloud_.resize(n_he);
202 if (Mesh::HasEdgeData::value)
203 mesh.edge_data_cloud_.resize(n_he / 2);
204 if (Mesh::HasFaceData::value)
205 mesh.face_data_cloud_.resize(n_f);
206
207 return (true);
208 }
209
210 /** \brief Write the mesh to a file with the given filename.
211 * \param[in] filename Path to the file.
212 * \param[in] mesh The saved mesh.
213 * \return true if success
214 */
215 bool
216 write(const std::string& filename, const Mesh& mesh) const
217 {
218 std::ofstream file(filename.c_str());
219
220 // Write the header
221 if (!file.is_open()) {
222 std::cerr << "Error in MeshIO::write: Could not open the file '" << filename
223 << "'\n";
224 return (false);
225 }
226
227 file << "PCL half-edge mesh\n";
228 file << mesh.sizeVertices() << " " << mesh.sizeHalfEdges() << " "
229 << mesh.sizeFaces() << "\n";
230
231 // Write the vertices
232 for (const auto& vertex : mesh.vertices_) {
233 file << vertex.idx_outgoing_half_edge_ << "\n";
234 }
235
236 // Write the half-edges
237 for (const auto& edge : mesh.half_edges_) {
238 file << edge.idx_terminating_vertex_ << " " << edge.idx_next_half_edge_ << " "
239 << edge.idx_prev_half_edge_ << " " << edge.idx_face_ << "\n";
240 }
241
242 // Write the faces
243 for (const auto& face : mesh.faces_) {
244 file << face.idx_inner_half_edge_ << "\n";
245 }
246
247 return (true);
248 }
249};
250
251} // End namespace geometry
252} // End namespace pcl
Read / write the half-edge mesh from / to a file.
Definition mesh_io.h:60
typename Mesh::Face Face
Definition mesh_io.h:66
typename Mesh::VertexIndex VertexIndex
Definition mesh_io.h:72
typename Mesh::FaceIndex FaceIndex
Definition mesh_io.h:74
typename Mesh::HalfEdges HalfEdges
Definition mesh_io.h:69
typename Mesh::HalfEdgeIndex HalfEdgeIndex
Definition mesh_io.h:73
bool read(const std::string &filename, Mesh &mesh) const
Read the mesh from a file with the given filename.
Definition mesh_io.h:85
typename Mesh::Faces Faces
Definition mesh_io.h:70
MeshIO()=default
Constructor.
typename Mesh::Vertex Vertex
Definition mesh_io.h:64
typename Mesh::Vertices Vertices
Definition mesh_io.h:68
bool write(const std::string &filename, const Mesh &mesh) const
Write the mesh to a file with the given filename.
Definition mesh_io.h:216
typename Mesh::HalfEdge HalfEdge
Definition mesh_io.h:65