Point Cloud Library (PCL)  1.11.1-dev
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 <string>
45 #include <sstream>
46 #include <iostream>
47 
48 namespace pcl
49 {
50  namespace geometry
51  {
52  /** \brief Read / write the half-edge mesh from / to a file.
53  * \tparam MeshT e.g. pcl::geometry::TriangleMesh or pcl::geometry::PolygonMesh
54  * \author Martin Saelzle
55  * \ingroup geometry
56  * \todo
57  * - Only writes the topology (not the mesh data).
58  * - Supports only ascii.
59  * - Does not consider the mesh traits (e.g. manifold or not)
60  */
61  template <class MeshT>
62  class MeshIO
63  {
64  public:
65 
66  using Mesh = MeshT;
67 
68  using Vertex = typename Mesh::Vertex;
69  using HalfEdge = typename Mesh::HalfEdge;
70  using Face = typename Mesh::Face;
71 
72  using Vertices = typename Mesh::Vertices;
73  using HalfEdges = typename Mesh::HalfEdges;
74  using Faces = typename Mesh::Faces;
75 
76  using VertexIndex = typename Mesh::VertexIndex;
77  using HalfEdgeIndex = typename Mesh::HalfEdgeIndex;
78  using FaceIndex = typename Mesh::FaceIndex;
79 
80  /** \brief Constructor. */
81  MeshIO ()
82  {
83  }
84 
85  /** \brief Read the mesh from a file with the given filename.
86  * \param[in] filename Path to the file.
87  * \param[out] mesh The loaded mesh.
88  * \return true if success.
89  */
90  bool
91  read (const std::string& filename, Mesh& mesh) const
92  {
93  std::ifstream file (filename.c_str ());
94 
95  if (!file.is_open ())
96  {
97  std::cerr << "Error in MeshIO::read: Could not open the file '" << filename << "'\n";
98  return (false);
99  }
100 
101  // Read the header
102  std::string line;
103  unsigned int line_number = 1;
104  int n_v = -1, n_he = -1, n_f = -1;
105 
106  if (!std::getline (file, line) || line != "PCL half-edge mesh")
107  {
108  std::cerr << "Error loading '" << filename << "' (line " << line_number << "): Wrong file format.\n";
109  return (false);
110  }
111  ++line_number;
112 
113  if (!std::getline (file, line))
114  {
115  std::cerr << "Error loading '" << filename << "'' (line " << line_number << "): Number of vertices / half-edges / faces not found.\n";
116  return (false);
117  }
118  {
119  std::istringstream iss (line);
120  if (!(iss >> n_v >> n_he >> n_f) || iss.good ()) // Don't allow more than 3 en
121  {
122  std::cerr << "Error loading '" << filename << "'' (line " << line_number << "): Could not read the number of vertices / half-edges / faces.\n";
123  return (false);
124  }
125  }
126  if (n_v < 0 || n_he < 0 || n_f < 0)
127  {
128  std::cerr << "Error loading '" << filename << "'' (line " << line_number << "): Invalid number of vertices / half-edges / faces.\n";
129  return (false);
130  }
131  ++line_number;
132 
133  // Read the vertices.
134  {
135  mesh.vertices_.reserve (n_v);
136  HalfEdgeIndex idx_ohe; // Outgoing half-edge;
137 
138  for (int i=0; i<n_v; ++i, ++line_number)
139  {
140  if (!std::getline (file, line))
141  {
142  std::cerr << "Error loading '" << filename << "'' (line " << line_number << "): Could not read the line.\n";
143  return (false);
144  }
145 
146  std::istringstream iss (line);
147  if (!(iss >> idx_ohe) || iss.good ())
148  {
149  std::cerr << "Error loading '" << filename << "'' (line " << line_number << "): Could not read the vertex.\n";
150  return (false);
151  }
152  mesh.vertices_.push_back (Vertex (idx_ohe));
153  }
154  }
155 
156  // Read the half-edges.
157  {
158  mesh.half_edges_.reserve (n_he);
159  VertexIndex idx_tv; // Terminating vertex.
160  HalfEdgeIndex idx_nhe; // Next half-edge;
161  HalfEdgeIndex idx_phe; // Previous half-edge.
162  FaceIndex idx_f; // Face.
163 
164  for (int i=0; i<n_he; ++i, ++line_number)
165  {
166  if (!std::getline (file, line))
167  {
168  std::cerr << "Error loading '" << filename << "'' (line " << line_number << "): Could not read the line.\n";
169  return (false);
170  }
171 
172  std::istringstream iss (line);
173  if (!(iss >> idx_tv >> idx_nhe >> idx_phe >> idx_f) || iss.good ())
174  {
175  std::cerr << "Error loading '" << filename << "'' (line " << line_number << "): Could not read the half-edge.\n";
176  return (false);
177  }
178  mesh.half_edges_.push_back (HalfEdge (idx_tv, idx_nhe, idx_phe, idx_f));
179  }
180  }
181 
182  // Read the faces.
183  {
184  mesh.faces_.reserve (n_f);
185  HalfEdgeIndex idx_ihe; // Inner half-edge.
186 
187  for (int i=0; i<n_f; ++i, ++line_number)
188  {
189  if (!std::getline (file, line))
190  {
191  std::cerr << "Error loading '" << filename << "'' (line " << line_number << "): Could not read the line.\n";
192  return (false);
193  }
194 
195  std::istringstream iss (line);
196  if (!(iss >> idx_ihe) || iss.good ())
197  {
198  std::cerr << "Error loading '" << filename << "'' (line " << line_number << "): Could not read the face.\n";
199  return (false);
200  }
201  mesh.faces_.push_back (Face (idx_ihe));
202  }
203  }
204 
205  // Set the data
206  if (Mesh::HasVertexData::value) mesh.vertex_data_cloud_. resize (n_v);
207  if (Mesh::HasHalfEdgeData::value) mesh.half_edge_data_cloud_.resize (n_he);
208  if (Mesh::HasEdgeData::value) mesh.edge_data_cloud_. resize (n_he / 2);
209  if (Mesh::HasFaceData::value) mesh.face_data_cloud_. resize (n_f);
210 
211  return (true);
212  }
213 
214  /** \brief Write the mesh to a file with the given filename.
215  * \param[in] filename Path to the file.
216  * \param[in] mesh The saved mesh.
217  * \return true if success
218  */
219  bool
220  write (const std::string& filename, const Mesh& mesh) const
221  {
222  std::ofstream file (filename.c_str ());
223 
224  // Write the header
225  if (!file.is_open ())
226  {
227  std::cerr << "Error in MeshIO::write: Could not open the file '" << filename << "'\n";
228  return (false);
229  }
230 
231  file << "PCL half-edge mesh\n";
232  file << mesh.sizeVertices () << " "
233  << mesh.sizeHalfEdges () << " "
234  << mesh.sizeFaces () << "\n";
235 
236  // Write the vertices
237  for (typename Vertices::const_iterator it=mesh.vertices_.begin (); it!=mesh.vertices_.end (); ++it)
238  {
239  file << it->idx_outgoing_half_edge_ << "\n";
240  }
241 
242  // Write the half-edges
243  for (typename HalfEdges::const_iterator it=mesh.half_edges_.begin (); it!=mesh.half_edges_.end (); ++it)
244  {
245  file << it->idx_terminating_vertex_ << " "
246  << it->idx_next_half_edge_ << " "
247  << it->idx_prev_half_edge_ << " "
248  << it->idx_face_ << "\n";
249  }
250 
251  // Write the faces
252  for (typename Faces::const_iterator it=mesh.faces_.begin (); it!=mesh.faces_.end (); ++it)
253  {
254  file << it->idx_inner_half_edge_ << "\n";
255  }
256 
257  return (true);
258  }
259  };
260 
261  } // End namespace geometry
262 } // End namespace pcl
pcl
Definition: convolution.h:46
pcl::geometry::MeshIO::VertexIndex
typename Mesh::VertexIndex VertexIndex
Definition: mesh_io.h:76
pcl::geometry::MeshIO::Vertices
typename Mesh::Vertices Vertices
Definition: mesh_io.h:72
pcl::geometry::MeshIO::Faces
typename Mesh::Faces Faces
Definition: mesh_io.h:74
Mesh
Definition: surface.h:13
pcl::geometry::MeshIO::Face
typename Mesh::Face Face
Definition: mesh_io.h:70
pcl::geometry::MeshIO::read
bool read(const std::string &filename, Mesh &mesh) const
Read the mesh from a file with the given filename.
Definition: mesh_io.h:91
pcl::geometry::MeshIO::MeshIO
MeshIO()
Constructor.
Definition: mesh_io.h:81
pcl::geometry::MeshIO::FaceIndex
typename Mesh::FaceIndex FaceIndex
Definition: mesh_io.h:78
pcl::geometry::MeshIO::HalfEdgeIndex
typename Mesh::HalfEdgeIndex HalfEdgeIndex
Definition: mesh_io.h:77
pcl::geometry::MeshIO::Vertex
typename Mesh::Vertex Vertex
Definition: mesh_io.h:68
pcl::geometry::MeshIO::HalfEdge
typename Mesh::HalfEdge HalfEdge
Definition: mesh_io.h:69
pcl::geometry::MeshIO::HalfEdges
typename Mesh::HalfEdges HalfEdges
Definition: mesh_io.h:73
pcl::geometry::MeshIO::write
bool write(const std::string &filename, const Mesh &mesh) const
Write the mesh to a file with the given filename.
Definition: mesh_io.h:220