Point Cloud Library (PCL)  1.5.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
ply.h
Go to the documentation of this file.
00001 /*
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2009, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage, Inc. nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  * $Id: ply.h 4702 2012-02-23 09:39:33Z gedikli $
00035  *
00036  */
00037 
00038 #ifndef PCL_IO_PLY_H_
00039 #define PCL_IO_PLY_H_
00040 
00041 #include "pcl/point_types.h"
00042 #include "pcl/common/io.h"
00043 #include <functional>
00044 #include <algorithm>
00045 #include <boost/algorithm/string.hpp>
00046 #include <fstream>
00047 
00048 namespace pcl
00049 {
00050   namespace io
00051   {
00052     namespace ply
00053     {
00055       enum Format
00056       {
00057         ASCII_FORMAT = 0,
00058         BIG_ENDIAN_FORMAT = 1,
00059         LITTLE_ENDIAN_FORMAT = 2
00060       };
00061 
00062 #if (defined(__powerpc) || defined(__powerpc__) || defined(__POWERPC__) || defined(__ppc__) || defined(_M_PPC) || defined(__ARCH_PPC))
00063 #  define PCL_BIG_ENDIAN
00064 #elif (defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86) || defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || defined(__INTEL__)) \
00065   || (defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64)) \
00066   || (defined(__ANDROID__))
00067 #  define PCL_LITTLE_ENDIAN
00068 #else
00069 #  error
00070 #endif
00071 
00072       inline Format getEndianess()
00073       {
00074 #ifdef PCL_LITTLE_ENDIAN
00075         return LITTLE_ENDIAN_FORMAT;
00076 #elif defined PCL_BIG_ENDIAN
00077         return BIG_ENDIAN_FORMAT;
00078 #else
00079 #error
00080 #endif
00081       }
00082 #undef PCL_BIG_ENDIAN
00083 #undef PCL_LITTLE_ENDIAN
00084       
00086       enum Flags
00087       {
00088         NONE              = 0x0000000,
00089         //vertex properties
00090         VERTEX_XYZ        = 0x0000001,
00091         VERTEX_NORMAL     = 0x0000002,
00092         VERTEX_COLOR      = 0x0000004,
00093         VERTEX_INTENSITY  = 0x0000008,
00094         VERTEX_NORNAL     = 0x0000010,
00095         VERTEX_RADIUS     = 0x0000020,
00096         VERTEX_CONFIDENCE = 0x0000040,
00097         VERTEX_VIEWPOINT  = 0x0000080,
00098         VERTEX_RANGE      = 0x0000100,
00099         VERTEX_STRENGTH   = 0x0000200,
00100         VERTEX_XY         = 0x0000400,
00101         //face properties
00102         FACE_VERTICES     = 0x0010000,
00103         //camera properties
00104         CAMERA            = 0x8000000,
00105         //all properties are set
00106         ALL               = 0xFFFFFFF
00107       };
00109       inline int getTypeFromTypeName(const std::string& type_name) 
00110       {
00111         if(!strcmp(type_name.c_str(), "char"))
00112           return sensor_msgs::PointField::INT8;
00113         if(!strcmp(type_name.c_str(), "uchar"))
00114           return sensor_msgs::PointField::UINT8;
00115         if(!strcmp(type_name.c_str(), "short"))
00116           return sensor_msgs::PointField::INT16;
00117         if(!strcmp(type_name.c_str(), "ushort"))
00118           return sensor_msgs::PointField::UINT16;
00119         if(!strcmp(type_name.c_str(), "int"))
00120           return sensor_msgs::PointField::INT32;
00121         if(!strcmp(type_name.c_str(), "uint"))
00122           return sensor_msgs::PointField::UINT32;
00123         if(!strcmp(type_name.c_str(), "float"))
00124           return sensor_msgs::PointField::FLOAT32;
00125         if(!strcmp(type_name.c_str(), "double"))
00126           return sensor_msgs::PointField::FLOAT64;
00127         if(!strcmp(type_name.c_str(), "list"))
00128           return -1;
00129         return -2;
00130       };
00131       
00132       inline size_t getMaximumCapacity(int size_type)
00133       {
00134         switch(size_type)
00135         {
00136         case sensor_msgs::PointField::UINT8 : 
00137           return std::numeric_limits<unsigned char>::max();
00138         case sensor_msgs::PointField::UINT16 : 
00139           return std::numeric_limits<unsigned short>::max();
00140         case sensor_msgs::PointField::UINT32 : 
00141           return std::numeric_limits<unsigned int>::max();
00142         default:
00143           return 0;
00144         }
00145       };
00146 
00147       struct property
00148       {
00149         std::string name_;
00150         int data_type_;
00151         size_t offset_;
00152         property(const std::string& name) : name_(name), offset_(0) {}
00153         property(const std::string& name, int data_type)
00154           : name_(name), data_type_(data_type)
00155         {
00156           offset_ = pcl::getFieldSize(data_type_);
00157         }
00158       };
00159 
00160       struct list_property : public property
00161       {
00162         int size_type_;
00163         list_property(const std::string& name, int size_type, int data_type)
00164           : property(name, data_type), size_type_(size_type) 
00165         {
00166           offset_ = pcl::getFieldSize(size_type_) + 
00167             getMaximumCapacity(size_type_) * pcl::getFieldSize(data_type_);
00168         }
00169         
00170         void set_size(const void* size)
00171         {
00172           offset_ = pcl::getFieldSize(size_type_);
00173           switch(size_type_)
00174           {
00175           case sensor_msgs::PointField::UINT8 : 
00176           {
00177             const unsigned char *size_; size_ = (unsigned char*) size;
00178             offset_ += (*size_) * pcl::getFieldSize(size_type_);
00179           }
00180           break;
00181           case sensor_msgs::PointField::UINT16 : 
00182           {
00183             const unsigned short *size_; size_ = (unsigned short*) size;
00184             offset_ += (*size_) * pcl::getFieldSize(size_type_);
00185           }
00186           break;
00187           case sensor_msgs::PointField::UINT32 : 
00188           {
00189             const unsigned int *size_; size_ = (unsigned int*) size;
00190             offset_ += (*size_) * pcl::getFieldSize(size_type_);
00191           }
00192           break;
00193           }
00194         }
00195       };
00196 
00197       class element
00198       {
00199       public:
00200         std::string name_;
00201         size_t count_;
00202         size_t offset_;
00203         element(const std::string& name, size_t count)
00204           : name_(name)
00205           , count_(count)
00206           , offset_(0)
00207           , properties_(0)
00208           , list_properties_(0) 
00209         {}
00210 
00211         typedef std::vector<property*>::iterator iterator;
00212         typedef std::vector<property*>::const_iterator const_iterator;
00213         typedef std::vector<iterator>::iterator iterator_iterator;
00214         typedef std::vector<iterator>::const_iterator const_iterator_iterator;
00215         size_t properties_size() { return properties_.size(); }
00216         property* operator[](const std::string &prop_name)
00217         {
00218           std::vector<property*>::iterator properties_it = properties_.begin();
00219           for(; properties_it != properties_.end(); ++properties_it)
00220             if((*properties_it)->name_ == prop_name) break;
00221           if (properties_it == properties_.end())
00222             return NULL;
00223           else
00224             return *properties_it;
00225         }
00226           
00227         const property* operator[](const std::string &prop_name) const 
00228         {
00229           std::vector<property*>::const_iterator properties_it = properties_.begin ();
00230           for(; properties_it != properties_.end (); ++properties_it)
00231             if((*properties_it)->name_ == prop_name) break;
00232           if (properties_it == properties_.end ())
00233             return NULL;
00234           else
00235             return *properties_it;
00236         }
00237 
00238         int push_property(const std::string& name, int data_type)
00239         {
00240           property* p = new property (name, data_type);
00241           properties_.push_back (p);
00242           offset_+= p->offset_;
00243           return int (properties_.size ());
00244         }
00245           
00246         int push_property(const std::string& name, int size_type, int data_type)
00247         {
00248           property *lp = new list_property (name, size_type, data_type);
00249           properties_.push_back (lp);
00250           list_properties_.push_back (properties_.end() - 1);
00251           offset_+= lp->offset_;
00252           return int (properties_.size ());
00253         }
00254 
00255         bool has_list_properties() const { return (!list_properties_.empty()); }
00256           
00257         size_t offset_before(const std::string& prop_name)
00258         {
00259           size_t offset = 0;
00260           std::vector<property*>::const_iterator properties_it = properties_.begin();
00261           for(; properties_it != properties_.end(); ++properties_it)
00262             if((*properties_it)->name_ == prop_name) 
00263               break;
00264             else
00265               offset+= (*properties_it)->offset_;
00266           if (properties_it == properties_.end())
00267             return -1;
00268           return offset;
00269         }
00270 
00271         void update_offset() 
00272         {
00273           offset_ = 0;
00274           std::vector<property*>::const_iterator properties_it = properties_.begin();
00275           for(; properties_it != properties_.end(); ++properties_it)
00276             offset_+= (*properties_it)->offset_;
00277         }
00278 
00279         bool is_list_property(const_iterator property_pos)
00280         {
00281           return std::find_if(list_properties_.begin(),
00282                               list_properties_.end(),
00283                               std::bind1st(std::equal_to<const_iterator>(),property_pos)) != list_properties_.end();
00284         }
00285         std::vector<property*> properties_;
00286         std::vector<iterator> list_properties_;
00287       };
00288 
00289       struct obj_info 
00290       {
00291         std::string name_;
00292         union
00293         {
00294           float float_data_;
00295           int int_data_;
00296         };
00297         obj_info (std::string name, float data)
00298           : name_(name), float_data_(data) {}
00299         obj_info (std::string name, int data)
00300           : name_(name), int_data_(data) {}        
00301       };
00302 
00303       class parser
00304       {
00305       public:
00306       parser() : elements_(0), last_element_(0), infos_(0) {}
00307 
00308         typedef std::vector<element*>::iterator iterator;
00309         typedef std::vector<element*>::const_iterator const_iterator;
00310         iterator begin() { return elements_.begin(); }
00311         iterator end() { return elements_.end(); }
00312 
00313         element* operator[](const std::string &element_name)
00314         {
00315           std::vector<element*>::iterator elements_it = elements_.begin();
00316           for(; elements_it != elements_.end(); ++elements_it)
00317             if((*elements_it)->name_ == element_name) break;
00318           if (elements_it == elements_.end())
00319             return NULL;
00320           else
00321             return *elements_it;
00322         }
00323 
00324         const element* operator[](const std::string &element_name) const
00325         {
00326           std::vector<element*>::const_iterator elements_it = elements_.begin();
00327           for(; elements_it != elements_.end(); ++elements_it)
00328             if((*elements_it)->name_ == element_name) break;
00329           if (elements_it == elements_.end())
00330             return NULL;
00331           else
00332             return *elements_it;
00333         }
00334           
00335         int push_element(const std::string& name, size_t count)
00336         {
00337           last_element_ = new element(name, count);
00338           elements_.push_back(last_element_);
00339           return int (elements_.size());
00340         }
00341 
00342         int push_property(const std::string& name, int data_type)
00343         {
00344           return last_element_->push_property(name, data_type);
00345         }
00346 
00347         int push_property(const std::string& name, int size_type, int data_type)
00348         {
00349           return last_element_->push_property(name, size_type, data_type);
00350         }
00351 
00352         void push_obj_info(const std::string& name, const std::string& data)
00353         {
00354           if (data.find ('.') != std::string::npos || 
00355               data.find ('e') != std::string::npos ||
00356               data.find ('E') != std::string::npos ||
00357               data.find ('f') != std::string::npos)
00358             infos_.push_back (new obj_info (name, float (atof (data.c_str ()))));
00359           else
00360             infos_.push_back (new obj_info (name, atoi (data.c_str ())));
00361         }
00362         
00363         obj_info*
00364         get_obj_info(const std::string& name) const
00365         {
00366           std::vector <obj_info*>::const_iterator info = infos_.begin ();
00367           for ( ;info!=infos_.end (); ++info)
00368             if ( (*info)->name_ == name ) break;
00369           return *info;
00370         }
00371 
00372         size_t offset_before(const std::string& element_name)
00373         {
00374           size_t offset = 0;
00375           std::vector<element*>::const_iterator elements_it = elements_.begin();
00376           for(; elements_it != elements_.end(); ++elements_it)
00377             if((*elements_it)->name_ == element_name) 
00378               break;
00379             else
00380               offset+= (*elements_it)->offset_ * (*elements_it)->count_;
00381           if (elements_it == this->end())
00382             return -1;
00383           return offset;
00384         }
00385 
00386 
00387         int parse_header(const std::string& file_name, int& data_type, int& data_idx, bool& is_swap_required)
00388         {
00389           std::ifstream fs;
00390           std::string line;
00391 
00392           // Open file in binary mode to avoid problem of 
00393           // std::getline() corrupting the result of ifstream::tellg()
00394           fs.open (file_name.c_str (), std::ios::binary);
00395           if (!fs.is_open () || fs.fail ())
00396           {
00397             PCL_ERROR ("[pcl::io::ply::parser::parse_header] Could not open file %s.\n", file_name.c_str ());
00398             return (-1);
00399           }
00400 
00401           std::vector<std::string> st;
00402           // Read the header and fill it in with wonderful values
00403           try
00404           {
00405             getline (fs, line);
00406             boost::trim (line);
00407             boost::split (st, line, boost::is_any_of ( std::string ("\t\r ")), boost::token_compress_on);
00408 
00409             // PLY file always start with magic line "ply"
00410             if (st.at (0) !=  "ply")
00411             {
00412               PCL_ERROR ("[pcl::io::ply::parser::parse_header] %s is not a valid ply file\n", st[0].c_str());
00413               return(-1);
00414             }
00415 
00416             while (!fs.eof ())
00417             {
00418               getline (fs, line);
00419               // Ignore empty lines
00420               if (line == "")
00421                 continue;
00422 
00423               // Tokenize the line
00424               boost::trim (line);
00425               boost::split (st, line, boost::is_any_of (std::string ( "\t\r ")), boost::token_compress_on);
00426 
00427               std::string line_type = st.at (0);
00428 
00429               // read format
00430               if (line_type.substr (0, 6) == "format")
00431               {
00432                 float version =  atof(st.at(2).c_str());
00433                 //check version number
00434                 if (version != 1.0)
00435                 {
00436                   PCL_ERROR ("[pcl::io::ply::parser::parse_header] can't handle this PLY format version %f\n", version);
00437                   return (-1);
00438                 }
00439                 //check format
00440                 if ("ascii" == st.at (1))
00441                   data_type = 0;
00442                 else
00443                 {
00444                   if ("binary_big_endian" == st.at (1) || "binary_little_endian" == st.at (1))
00445                   {
00446                     data_type = 1;
00447                     pcl::io::ply::Format format = pcl::io::ply::getEndianess();
00448                     if ((("binary_big_endian" == st.at(1)) && 
00449                          (format == pcl::io::ply::LITTLE_ENDIAN_FORMAT)) ||
00450                         (("binary_little_endian" == st.at(1)) && 
00451                          (format == pcl::io::ply::BIG_ENDIAN_FORMAT)))
00452                       is_swap_required = true;
00453                   }
00454                   else
00455                   {
00456                     PCL_ERROR ("[pcl::io::ply::parser::parse_header] unknown format %f\n", st[1].c_str());
00457                     return (-1);
00458                   }
00459                 }
00460                 continue;
00461               }
00462               // ignore comments
00463               if (line_type.substr (0, 7) == "comment")
00464                 continue;
00465               // read obj_info
00466               if (line_type.substr (0, 8) == "obj_info") 
00467               {
00468                 if(st.size() == 3)
00469                   push_obj_info(st.at(1), st.at(2));
00470                 else
00471                   PCL_ERROR ("[pcl::io::ply::parser::parse_header] parse error obj_info %s\n",
00472                              st.at(2).c_str ());
00473                 continue;
00474               }
00475               // read element
00476               if (line_type.substr (0, 7) == "element") 
00477               {
00478                 if(st.size() == 3)
00479                   push_element(st.at(1), atoi(st.at(2).c_str()));
00480                 else
00481                   push_element(st.at(1), 1);
00482                 continue;
00483               }
00484               // read property
00485               if (line_type.substr (0, 8) == "property")
00486               {
00487                 // list property
00488                 if(st.at(1) == "list")
00489                 {
00490                   int size_type = pcl::io::ply::getTypeFromTypeName(st.at(2));
00491                   int data_type = pcl::io::ply::getTypeFromTypeName(st.at(3));
00492                   if(data_type < -1 || size_type < -1)
00493                   {
00494                     PCL_ERROR ("[pcl::io::ply::parser::parse_header] parse error property list %s %s %s.\n", 
00495                                st[2].c_str(), st[3].c_str (), st[4].c_str ());
00496                     return -1;
00497                   }
00498                   else
00499                   {
00500                     size_t capacity = pcl::io::ply::getMaximumCapacity(size_type);
00501                     if(capacity == 0)
00502                     {
00503                       PCL_ERROR ("[pcl::io::ply::parser::parse_header] unhandled size type for property list %s %s %s.\n", st[2].c_str(), st[3].c_str (), st[4].c_str ());
00504                       return -1;
00505                     }
00506                     push_property(st.at(4), size_type, data_type);
00507                   }
00508                 }
00509                 // scalar property
00510                 else
00511                 {
00512                   int type = pcl::io::ply::getTypeFromTypeName(st.at(1));
00513                   if(type < -1)
00514                   {
00515                     PCL_ERROR ("[pcl::io::ply::parser::parse_header] parse error property %s %s.\n", st[1].c_str (), st[2].c_str ());
00516                     return -1;
00517                   }
00518                   else
00519                     push_property (st.at(2), type);
00520                 }
00521                 continue;
00522               }
00523               // end of header
00524               if (line_type.substr (0, 10) == "end_header") 
00525                 data_idx = fs.tellg ();
00526               break;
00527             }
00528           }
00529           catch (const char *exception)
00530           {
00531             PCL_ERROR ("[pcl::io::ply::parser::parse_header] %s\n", exception);
00532             return (-1);
00533           }
00534           
00535           fs.close();
00536           return (0);
00537         }
00538 
00539       private:
00540         std::vector<element*> elements_;
00541         element* last_element_;
00542         std::vector <obj_info*> infos_;
00543       };
00544 
00546       struct camera
00547       {
00548         float view_px; float view_py; float view_pz;
00549         float x_axisx; float x_axisy; float x_axisz;
00550         float y_axisx; float y_axisy; float y_axisz;
00551         float z_axisx; float z_axisy; float z_axisz;
00552         float focal; float scalex; float scaley; float centerx; float centery;
00553         int viewportx; int viewporty; float k1; float k2;
00554 
00558         camera () :
00559           view_px(0), view_py(0), view_pz(0),
00560             x_axisx(0), x_axisy(0), x_axisz(0),
00561             y_axisx(0), y_axisy(0), y_axisz(0),
00562             z_axisx(0), z_axisy(0), z_axisz(0),
00563             focal(0), scalex(0), centerx(0), centery(0), viewportx(0), viewporty(0),
00564             k1(0), k2(0) {}
00565 
00571          camera(const Eigen::Vector4f &origin, const Eigen::Quaternionf &orientation) :
00572           view_px(origin[0]), view_py(origin[1]), view_pz(origin[2]),
00573             focal(0), scalex(0), centerx(0), centery(0), viewportx(0), viewporty(0),
00574             k1(0), k2(0)
00575           {
00576             Eigen::Matrix3f R = orientation.toRotationMatrix ();
00577             x_axisx = R(0,0); x_axisy = R(0,1); x_axisz = R(0,2);
00578             y_axisx = R(1,0); y_axisy = R(1,1); y_axisz = R(1,2);
00579             z_axisx = R(2,0); z_axisy = R(2,1); z_axisz = R(2,2);
00580           }
00581           
00583           void 
00584           ext_to_eigen (Eigen::Vector4f &origin, Eigen::Quaternionf &orientation)
00585           {
00586             origin[0] = view_px; origin[1] = view_py;  origin[2] = view_pz; origin[3] = 1.0;
00587             Eigen::Matrix3f R;
00588             R << x_axisx, x_axisy, x_axisz,
00589               y_axisx, y_axisy, y_axisz,
00590               z_axisx, z_axisy, z_axisz;
00591             orientation = Eigen::Quaternionf(R);
00592           }
00593       };
00594       
00596       inline void write(const pcl::io::ply::camera& c, std::ostream& out, bool binary)
00597       {
00598         if(!binary)
00599         {
00600           out << c.view_px << " " << c.view_py << " " << c.view_pz << " ";
00601           out << c.x_axisx << " " << c.x_axisy << " " << c.x_axisz << " ";
00602           out << c.y_axisx << " " << c.y_axisy << " " << c.y_axisz << " ";
00603           out << c.z_axisx << " " << c.z_axisy << " " << c.z_axisz << " ";
00604           out << c.focal << " ";
00605           out << c.scalex << " " << c.scaley << " ";
00606           out << c.centerx << " " << c.centery << " ";
00607           out << c.viewportx << " " << c.viewporty << " ";
00608           out << c.k1 << " " << c.k2;
00609         }
00610         else {
00611           out.write ((const char*) &c, sizeof(camera));
00612         }
00613       };
00614 
00615       struct range_grid
00616       {
00617         std::vector<int> indices_;
00618         void resize (const std::string&, size_t size)
00619         {
00620           indices_.resize (size);
00621         }
00622       };
00623     } //namespace ply
00624   } //namespace io
00625 }//namespace pcl
00626 
00627 #endif