00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include <cstdlib>
00041 #include <cstring>
00042 #include <fstream>
00043 #include <iostream>
00044
00045 #include <boost/bind.hpp>
00046
00047 #include <pcl/io/ply/ply_parser.h>
00048
00062 class ply_to_raw_converter
00063 {
00064 public:
00065 ply_to_raw_converter () :
00066 ostream_ (), vertex_x_ (0), vertex_y_ (0), vertex_z_ (0),
00067 face_vertex_indices_element_index_ (),
00068 face_vertex_indices_first_element_ (),
00069 face_vertex_indices_previous_element_ (),
00070 vertices_ ()
00071 {}
00072
00073 ply_to_raw_converter (const ply_to_raw_converter &f) :
00074 ostream_ (), vertex_x_ (0), vertex_y_ (0), vertex_z_ (0),
00075 face_vertex_indices_element_index_ (),
00076 face_vertex_indices_first_element_ (),
00077 face_vertex_indices_previous_element_ (),
00078 vertices_ ()
00079 {
00080 *this = f;
00081 }
00082
00083 ply_to_raw_converter&
00084 operator = (const ply_to_raw_converter &f)
00085 {
00086 ostream_ = f.ostream_;
00087 vertex_x_ = f.vertex_x_;
00088 vertex_y_ = f.vertex_y_;
00089 vertex_z_ = f.vertex_z_;
00090 face_vertex_indices_element_index_ = f.face_vertex_indices_element_index_;
00091 face_vertex_indices_first_element_ = f.face_vertex_indices_first_element_;
00092 face_vertex_indices_previous_element_ = f.face_vertex_indices_previous_element_;
00093 return (*this);
00094 }
00095
00096 bool
00097 convert (std::istream& istream, const std::string& istream_filename, std::ostream& ostream, const std::string& ostream_filename);
00098
00099 private:
00100 void
00101 info_callback (const std::string& filename, std::size_t line_number, const std::string& message);
00102
00103 void
00104 warning_callback (const std::string& filename, std::size_t line_number, const std::string& message);
00105
00106 void
00107 error_callback (const std::string& filename, std::size_t line_number, const std::string& message);
00108
00109 boost::tuple<boost::function<void ()>, boost::function<void ()> >
00110 element_definition_callback (const std::string& element_name, std::size_t count);
00111
00112 template <typename ScalarType> boost::function<void (ScalarType)>
00113 scalar_property_definition_callback (const std::string& element_name, const std::string& property_name);
00114
00115 template <typename SizeType, typename ScalarType> boost::tuple<boost::function<void (SizeType)>,
00116 boost::function<void (ScalarType)>,
00117 boost::function<void ()> >
00118 list_property_definition_callback (const std::string& element_name, const std::string& property_name);
00119
00120 void
00121 vertex_begin ();
00122
00123 void
00124 vertex_x (pcl::io::ply::float32 x);
00125
00126 void
00127 vertex_y (pcl::io::ply::float32 y);
00128
00129 void
00130 vertex_z (pcl::io::ply::float32 z);
00131
00132 void
00133 vertex_end ();
00134
00135 void
00136 face_begin ();
00137
00138 void
00139 face_vertex_indices_begin (pcl::io::ply::uint8 size);
00140
00141 void
00142 face_vertex_indices_element (pcl::io::ply::int32 vertex_index);
00143
00144 void
00145 face_vertex_indices_end ();
00146
00147 void
00148 face_end ();
00149
00150 std::ostream* ostream_;
00151 pcl::io::ply::float32 vertex_x_, vertex_y_, vertex_z_;
00152 pcl::io::ply::int32 face_vertex_indices_element_index_, face_vertex_indices_first_element_, face_vertex_indices_previous_element_;
00153 std::vector<boost::tuple<pcl::io::ply::float32, pcl::io::ply::float32, pcl::io::ply::float32> > vertices_;
00154 };
00155
00156 void
00157 ply_to_raw_converter::info_callback (const std::string& filename, std::size_t line_number, const std::string& message)
00158 {
00159 std::cerr << filename << ":" << line_number << ": " << "info: " << message << std::endl;
00160 }
00161
00162 void
00163 ply_to_raw_converter::warning_callback (const std::string& filename, std::size_t line_number, const std::string& message)
00164 {
00165 std::cerr << filename << ":" << line_number << ": " << "warning: " << message << std::endl;
00166 }
00167
00168 void
00169 ply_to_raw_converter::error_callback (const std::string& filename, std::size_t line_number, const std::string& message)
00170 {
00171 std::cerr << filename << ":" << line_number << ": " << "error: " << message << std::endl;
00172 }
00173
00174 boost::tuple<boost::function<void ()>, boost::function<void ()> >
00175 ply_to_raw_converter::element_definition_callback (const std::string& element_name, std::size_t)
00176 {
00177 if (element_name == "vertex") {
00178 return boost::tuple<boost::function<void ()>, boost::function<void ()> > (
00179 boost::bind (&ply_to_raw_converter::vertex_begin, this),
00180 boost::bind (&ply_to_raw_converter::vertex_end, this)
00181 );
00182 }
00183 else if (element_name == "face") {
00184 return boost::tuple<boost::function<void ()>, boost::function<void ()> > (
00185 boost::bind (&ply_to_raw_converter::face_begin, this),
00186 boost::bind (&ply_to_raw_converter::face_end, this)
00187 );
00188 }
00189 else {
00190 return boost::tuple<boost::function<void ()>, boost::function<void ()> > (0, 0);
00191 }
00192 }
00193
00194 template <> boost::function<void (pcl::io::ply::float32)>
00195 ply_to_raw_converter::scalar_property_definition_callback (const std::string& element_name, const std::string& property_name)
00196 {
00197 if (element_name == "vertex") {
00198 if (property_name == "x") {
00199 return boost::bind (&ply_to_raw_converter::vertex_x, this, _1);
00200 }
00201 else if (property_name == "y") {
00202 return boost::bind (&ply_to_raw_converter::vertex_y, this, _1);
00203 }
00204 else if (property_name == "z") {
00205 return boost::bind (&ply_to_raw_converter::vertex_z, this, _1);
00206 }
00207 else {
00208 return 0;
00209 }
00210 }
00211 else {
00212 return 0;
00213 }
00214 }
00215
00216 template <> boost::tuple<boost::function<void (pcl::io::ply::uint8)>,
00217 boost::function<void (pcl::io::ply::int32)>,
00218 boost::function<void ()> >
00219 ply_to_raw_converter::list_property_definition_callback (const std::string& element_name, const std::string& property_name)
00220 {
00221 if ((element_name == "face") && (property_name == "vertex_indices"))
00222 {
00223 return boost::tuple<boost::function<void (pcl::io::ply::uint8)>,
00224 boost::function<void (pcl::io::ply::int32)>,
00225 boost::function<void ()> > (
00226 boost::bind (&ply_to_raw_converter::face_vertex_indices_begin, this, _1),
00227 boost::bind (&ply_to_raw_converter::face_vertex_indices_element, this, _1),
00228 boost::bind (&ply_to_raw_converter::face_vertex_indices_end, this)
00229 );
00230 }
00231 else {
00232 return boost::tuple<boost::function<void (pcl::io::ply::uint8)>,
00233 boost::function<void (pcl::io::ply::int32)>,
00234 boost::function<void ()> > (0, 0, 0);
00235 }
00236 }
00237
00238 void
00239 ply_to_raw_converter::vertex_begin () {}
00240
00241 void
00242 ply_to_raw_converter::vertex_x (pcl::io::ply::float32 x)
00243 {
00244 vertex_x_ = x;
00245 }
00246
00247 void
00248 ply_to_raw_converter::vertex_y (pcl::io::ply::float32 y)
00249 {
00250 vertex_y_ = y;
00251 }
00252
00253 void
00254 ply_to_raw_converter::vertex_z (pcl::io::ply::float32 z)
00255 {
00256 vertex_z_ = z;
00257 }
00258
00259 void
00260 ply_to_raw_converter::vertex_end ()
00261 {
00262 vertices_.push_back (boost::tuple<pcl::io::ply::float32, pcl::io::ply::float32, pcl::io::ply::float32 > (vertex_x_, vertex_y_, vertex_z_));
00263 }
00264
00265 void
00266 ply_to_raw_converter::face_begin () {}
00267
00268 void
00269 ply_to_raw_converter::face_vertex_indices_begin (pcl::io::ply::uint8)
00270 {
00271 face_vertex_indices_element_index_ = 0;
00272 }
00273
00274 void
00275 ply_to_raw_converter::face_vertex_indices_element (pcl::io::ply::int32 vertex_index)
00276 {
00277 if (face_vertex_indices_element_index_ == 0) {
00278 face_vertex_indices_first_element_ = vertex_index;
00279 }
00280 else if (face_vertex_indices_element_index_ == 1) {
00281 face_vertex_indices_previous_element_ = vertex_index;
00282 }
00283 else {
00284 (*ostream_) << boost::get<0> (vertices_[ face_vertex_indices_first_element_])
00285 << " " << boost::get<1> (vertices_[ face_vertex_indices_first_element_])
00286 << " " << boost::get<2> (vertices_[ face_vertex_indices_first_element_])
00287 << " " << boost::get<0> (vertices_[face_vertex_indices_previous_element_])
00288 << " " << boost::get<1> (vertices_[face_vertex_indices_previous_element_])
00289 << " " << boost::get<2> (vertices_[face_vertex_indices_previous_element_])
00290 << " " << boost::get<0> (vertices_[ vertex_index])
00291 << " " << boost::get<1> (vertices_[ vertex_index])
00292 << " " << boost::get<2> (vertices_[ vertex_index]) << "\n";
00293 face_vertex_indices_previous_element_ = vertex_index;
00294 }
00295 ++face_vertex_indices_element_index_;
00296 }
00297
00298 void
00299 ply_to_raw_converter::face_vertex_indices_end () {}
00300
00301 void
00302 ply_to_raw_converter::face_end () {}
00303
00304 bool
00305 ply_to_raw_converter::convert (std::istream&, const std::string& istream_filename, std::ostream& ostream, const std::string&)
00306 {
00307 pcl::io::ply::ply_parser::flags_type ply_parser_flags = 0;
00308 pcl::io::ply::ply_parser ply_parser (ply_parser_flags);
00309
00310 ply_parser.info_callback (boost::bind (&ply_to_raw_converter::info_callback, this, boost::ref (istream_filename), _1, _2));
00311 ply_parser.warning_callback (boost::bind (&ply_to_raw_converter::warning_callback, this, boost::ref (istream_filename), _1, _2));
00312 ply_parser.error_callback (boost::bind (&ply_to_raw_converter::error_callback, this, boost::ref (istream_filename), _1, _2));
00313
00314 ply_parser.element_definition_callback (boost::bind (&ply_to_raw_converter::element_definition_callback, this, _1, _2));
00315
00316 pcl::io::ply::ply_parser::scalar_property_definition_callbacks_type scalar_property_definition_callbacks;
00317 pcl::io::ply::at<pcl::io::ply::float32> (scalar_property_definition_callbacks) = boost::bind (&ply_to_raw_converter::scalar_property_definition_callback<pcl::io::ply::float32>, this, _1, _2);
00318 ply_parser.scalar_property_definition_callbacks (scalar_property_definition_callbacks);
00319
00320 pcl::io::ply::ply_parser::list_property_definition_callbacks_type list_property_definition_callbacks;
00321 pcl::io::ply::at<pcl::io::ply::uint8, pcl::io::ply::int32> (list_property_definition_callbacks) = boost::bind (&ply_to_raw_converter::list_property_definition_callback<pcl::io::ply::uint8, pcl::io::ply::int32>, this, _1, _2);
00322 ply_parser.list_property_definition_callbacks (list_property_definition_callbacks);
00323
00324 ostream_ = &ostream;
00325
00326 return ply_parser.parse (istream_filename);
00327 }
00328
00329 int main (int argc, char* argv[])
00330 {
00331 int argi;
00332 for (argi = 1; argi < argc; ++argi) {
00333
00334 if (argv[argi][0] != '-') {
00335 break;
00336 }
00337 if (argv[argi][1] == 0) {
00338 ++argi;
00339 break;
00340 }
00341 char short_opt, *long_opt, *opt_arg;
00342 if (argv[argi][1] != '-') {
00343 short_opt = argv[argi][1];
00344 opt_arg = &argv[argi][2];
00345 long_opt = &argv[argi][2];
00346 while (*long_opt != '\0') {
00347 ++long_opt;
00348 }
00349 }
00350 else {
00351 short_opt = 0;
00352 long_opt = &argv[argi][2];
00353 opt_arg = long_opt;
00354 while ((*opt_arg != '=') && (*opt_arg != '\0')) {
00355 ++opt_arg;
00356 }
00357 if (*opt_arg == '=') {
00358 *opt_arg++ = '\0';
00359 }
00360 }
00361
00362 if ((short_opt == 'h') || (std::strcmp (long_opt, "help") == 0)) {
00363 std::cout << "Usage: ply2raw [OPTION] [[INFILE] OUTFILE]\n";
00364 std::cout << "Convert from PLY to POV-Ray RAW triangle format.\n";
00365 std::cout << "\n";
00366 std::cout << " -h, --help display this help and exit\n";
00367 std::cout << " -v, --version output version information and exit\n";
00368 std::cout << "\n";
00369 std::cout << "With no INFILE/OUTFILE, or when INFILE/OUTFILE is -, read standard input/output.\n";
00370 std::cout << "\n";
00371 std::cout << "The following PLY elements and properties are supported.\n";
00372 std::cout << " element vertex\n";
00373 std::cout << " property float32 x\n";
00374 std::cout << " property float32 y\n";
00375 std::cout << " property float32 z\n";
00376 std::cout << " element face\n";
00377 std::cout << " property list uint8 int32 vertex_indices.\n";
00378 std::cout << "\n";
00379 std::cout << "Report bugs to <www.pointclouds.org/issues>.\n";
00380 return EXIT_SUCCESS;
00381 }
00382
00383 else if ((short_opt == 'v') || (std::strcmp (long_opt, "version") == 0)) {
00384 std::cout << "ply2raw \n";
00385 std::cout << " Point Cloud Library (PCL) - www.pointclouds.org\n";
00386 std::cout << " Copyright (c) 2007-2012, Ares Lagae\n";
00387 std::cout << " Copyright (c) 2012, Willow Garage, Inc.\n";
00388 std::cout << " All rights reserved.\n";
00389 std::cout << " Redistribution and use in source and binary forms, with or without\n";
00390 std::cout << " modification, are permitted provided that the following conditions\n";
00391 std::cout << " are met:\n";
00392 std::cout << " * Redistributions of source code must retain the above copyright\n";
00393 std::cout << " notice, this list of conditions and the following disclaimer.\n";
00394 std::cout << " * Redistributions in binary form must reproduce the above\n";
00395 std::cout << " copyright notice, this list of conditions and the following\n";
00396 std::cout << " disclaimer in the documentation and/or other materials provided\n";
00397 std::cout << " with the distribution.\n";
00398 std::cout << " * Neither the name of Willow Garage, Inc. nor the names of its\n";
00399 std::cout << " contributors may be used to endorse or promote products derived\n";
00400 std::cout << " from this software without specific prior written permission.\n";
00401 std::cout << " THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n";
00402 std::cout << " \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n";
00403 std::cout << " LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\n";
00404 std::cout << " FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n";
00405 std::cout << " COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\n";
00406 std::cout << " INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\n";
00407 std::cout << " BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n";
00408 std::cout << " LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n";
00409 std::cout << " CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n";
00410 std::cout << " LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\n";
00411 std::cout << " ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n";
00412 std::cout << " POSSIBILITY OF SUCH DAMAGE.\n";
00413 return EXIT_SUCCESS;
00414 }
00415
00416 else {
00417 std::cerr << "ply2raw: " << "invalid option `" << argv[argi] << "'" << "\n";
00418 std::cerr << "Try `" << argv[0] << " --help' for more information.\n";
00419 return EXIT_FAILURE;
00420 }
00421 }
00422
00423 int parc = argc - argi;
00424 char** parv = argv + argi;
00425 if (parc > 2) {
00426 std::cerr << "ply2raw: " << "too many parameters" << "\n";
00427 std::cerr << "Try `" << argv[0] << " --help' for more information.\n";
00428 return EXIT_FAILURE;
00429 }
00430
00431 std::ifstream ifstream;
00432 const char* istream_filename = "";
00433 if (parc > 0) {
00434 istream_filename = parv[0];
00435 if (std::strcmp (istream_filename, "-") != 0) {
00436 ifstream.open (istream_filename);
00437 if (!ifstream.is_open ()) {
00438 std::cerr << "ply2raw: " << istream_filename << ": " << "no such file or directory" << "\n";
00439 return EXIT_FAILURE;
00440 }
00441 }
00442 }
00443
00444 std::ofstream ofstream;
00445 const char* ostream_filename = "";
00446 if (parc > 1) {
00447 ostream_filename = parv[1];
00448 if (std::strcmp (ostream_filename, "-") != 0) {
00449 ofstream.open (ostream_filename);
00450 if (!ofstream.is_open ()) {
00451 std::cerr << "ply2raw: " << ostream_filename << ": " << "could not open file" << "\n";
00452 return EXIT_FAILURE;
00453 }
00454 }
00455 }
00456
00457 std::istream& istream = ifstream.is_open () ? ifstream : std::cin;
00458 std::ostream& ostream = ofstream.is_open () ? ofstream : std::cout;
00459
00460 class ply_to_raw_converter ply_to_raw_converter;
00461 return ply_to_raw_converter.convert (istream, istream_filename, ostream, ostream_filename);
00462 }