ply_io.cpp
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$
00035  *
00036  */
00037 
00038 #include <fstream>
00039 #include <fcntl.h>
00040 #include <string>
00041 #include <map>
00042 #include <stdlib.h>
00043 #include <pcl/point_types.h>
00044 #include <pcl/common/io.h>
00045 #include <pcl/io/ply_io.h>
00046 #include <pcl/io/boost.h>
00047 #include <sstream>
00048 
00049 boost::tuple<boost::function<void ()>, boost::function<void ()> >
00050 pcl::PLYReader::elementDefinitionCallback (const std::string& element_name, std::size_t count)
00051 {
00052   if (element_name == "vertex")
00053   {
00054     cloud_->data.clear ();
00055     cloud_->fields.clear ();
00056     // Cloud dimensions may have already been set from obj_info fields
00057     if (cloud_->width == 0 || cloud_->height == 0)
00058     {
00059       cloud_->width = static_cast<uint32_t> (count);
00060       cloud_->height = 1;
00061     }
00062     cloud_->is_dense = false;
00063     cloud_->point_step = 0;
00064     cloud_->row_step = 0;
00065     vertex_count_ = 0;
00066     return (boost::tuple<boost::function<void ()>, boost::function<void ()> > (
00067               boost::bind (&pcl::PLYReader::vertexBeginCallback, this),
00068               boost::bind (&pcl::PLYReader::vertexEndCallback, this)));
00069   }
00070   // else if (element_name == "face")
00071   // {
00072   //   return (boost::tuple<boost::function<void ()>, boost::function<void ()> > (
00073   //             boost::bind (&pcl::PLYReader::faceBegin, this),
00074   //             boost::bind (&pcl::PLYReader::faceEnd, this)));
00075   // }
00076   else if (element_name == "camera")
00077   {
00078     cloud_->is_dense = true;
00079     return (boost::tuple<boost::function<void ()>, boost::function<void ()> > (0, 0));
00080   }
00081   else if (element_name == "range_grid")
00082   {
00083     (*range_grid_).resize (count);
00084     range_count_ = 0;
00085     return (boost::tuple<boost::function<void ()>, boost::function<void ()> > (
00086               boost::bind (&pcl::PLYReader::rangeGridBeginCallback, this),
00087               boost::bind (&pcl::PLYReader::rangeGridEndCallback, this)));
00088   }
00089   else
00090   {
00091     return (boost::tuple<boost::function<void ()>, boost::function<void ()> > (0, 0));
00092   }
00093 }
00094 
00095 bool
00096 pcl::PLYReader::endHeaderCallback ()
00097 {
00098   cloud_->data.resize (cloud_->point_step * cloud_->width * cloud_->height);
00099   return (cloud_->data.size () == cloud_->point_step * cloud_->width * cloud_->height);
00100 }
00101 
00102 void
00103 pcl::PLYReader::appendFloatProperty (const std::string& name, const size_t& size)
00104 {
00105   cloud_->fields.push_back (::pcl::PCLPointField ());
00106   ::pcl::PCLPointField &current_field = cloud_->fields.back ();
00107   current_field.name = name;
00108   current_field.offset = cloud_->point_step;
00109   current_field.datatype = ::pcl::PCLPointField::FLOAT32;
00110   current_field.count = static_cast<uint32_t> (size);
00111   cloud_->point_step += static_cast<uint32_t> (pcl::getFieldSize (::pcl::PCLPointField::FLOAT32) * size);
00112 }
00113 
00114 void
00115 pcl::PLYReader::amendProperty (const std::string& old_name, const std::string& new_name, uint8_t new_datatype)
00116 {
00117   std::vector< ::pcl::PCLPointField>::reverse_iterator finder = cloud_->fields.rbegin ();
00118   for (; finder != cloud_->fields.rend (); ++finder)
00119     if (finder->name == old_name)
00120       break;
00121   assert (finder != cloud_->fields.rend ());
00122   finder->name = new_name;
00123   if (new_datatype > 0 && new_datatype != finder->datatype)
00124     finder->datatype = new_datatype;
00125 }
00126 
00127 void
00128 pcl::PLYReader::appendUnsignedIntProperty (const std::string& name, const size_t& size)
00129 {
00130   cloud_->fields.push_back (::pcl::PCLPointField ());
00131   ::pcl::PCLPointField &current_field = cloud_->fields.back ();
00132   current_field.name = name;
00133   current_field.offset = cloud_->point_step;
00134   current_field.datatype = ::pcl::PCLPointField::UINT32;
00135   current_field.count = static_cast<uint32_t> (size);
00136   cloud_->point_step += static_cast<uint32_t> (pcl::getFieldSize (::pcl::PCLPointField::UINT32) * size);
00137 }
00138 
00139 void
00140 pcl::PLYReader::appendIntProperty (const std::string& name, const size_t& size)
00141 {
00142   cloud_->fields.push_back (pcl::PCLPointField ());
00143   pcl::PCLPointField &current_field = cloud_->fields.back ();
00144   current_field.name = name;
00145   current_field.offset = cloud_->point_step;
00146   current_field.datatype = pcl::PCLPointField::INT32;
00147   current_field.count = static_cast<uint32_t> (size);
00148   cloud_->point_step += static_cast<uint32_t> (pcl::getFieldSize (pcl::PCLPointField::INT32) * size);
00149 }
00150 
00151 void
00152 pcl::PLYReader::appendDoubleProperty (const std::string& name, const size_t& size)
00153 {
00154   cloud_->fields.push_back (pcl::PCLPointField ());
00155   pcl::PCLPointField &current_field = cloud_->fields.back ();
00156   current_field.name = name;
00157   current_field.offset = cloud_->point_step;
00158   current_field.datatype = pcl::PCLPointField::FLOAT64;
00159   current_field.count = static_cast<uint32_t> (size);
00160   cloud_->point_step += static_cast<uint32_t> (pcl::getFieldSize (pcl::PCLPointField::FLOAT64) * size);
00161 }
00162 
00163 void
00164 pcl::PLYReader::appendUnsignedCharProperty (const std::string& name, const size_t& size)
00165 {
00166   cloud_->fields.push_back (pcl::PCLPointField ());
00167   pcl::PCLPointField &current_field = cloud_->fields.back ();
00168   current_field.name = name;
00169   current_field.offset = cloud_->point_step;
00170   current_field.datatype = pcl::PCLPointField::UINT8;
00171   current_field.count = static_cast<uint32_t> (size);
00172   cloud_->point_step += static_cast<uint32_t> (pcl::getFieldSize (pcl::PCLPointField::UINT8) * size);
00173 }
00174 
00175 void
00176 pcl::PLYReader::appendCharProperty (const std::string& name, const size_t& size)
00177 {
00178   cloud_->fields.push_back (pcl::PCLPointField ());
00179   pcl::PCLPointField &current_field = cloud_->fields.back ();
00180   current_field.name = name;
00181   current_field.offset = cloud_->point_step;
00182   current_field.datatype = pcl::PCLPointField::INT8;
00183   current_field.count = static_cast<uint32_t> (size);
00184   cloud_->point_step += static_cast<uint32_t> (pcl::getFieldSize (pcl::PCLPointField::INT8) * size);
00185 }
00186 
00187 void
00188 pcl::PLYReader::appendUnsignedShortProperty (const std::string& name, const size_t& size)
00189 {
00190   cloud_->fields.push_back (pcl::PCLPointField ());
00191   pcl::PCLPointField &current_field = cloud_->fields.back ();
00192   current_field.name = name;
00193   current_field.offset = cloud_->point_step;
00194   current_field.datatype = pcl::PCLPointField::UINT16;
00195   current_field.count = static_cast<uint32_t> (size);
00196   cloud_->point_step += static_cast<uint32_t> (pcl::getFieldSize (pcl::PCLPointField::UINT16) * size);
00197 }
00198 
00199 void
00200 pcl::PLYReader::appendShortProperty (const std::string& name, const size_t& size)
00201 {
00202   cloud_->fields.push_back (pcl::PCLPointField ());
00203   pcl::PCLPointField &current_field = cloud_->fields.back ();
00204   current_field.name = name;
00205   current_field.offset = cloud_->point_step;
00206   current_field.datatype = pcl::PCLPointField::INT16;
00207   current_field.count = static_cast<uint32_t> (size);
00208   cloud_->point_step += static_cast<uint32_t> (pcl::getFieldSize (pcl::PCLPointField::INT16) * size);
00209 }
00210 
00211 namespace pcl
00212 {
00213   template <>
00214   boost::function<void (pcl::io::ply::float32)>
00215   PLYReader::scalarPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name)
00216   {
00217     if (element_name == "vertex")
00218     {
00219       appendFloatProperty (property_name, 1);
00220       return (boost::bind (&pcl::PLYReader::vertexFloatPropertyCallback, this, _1));
00221     }
00222     else if (element_name == "camera")
00223     {
00224       if (property_name == "view_px")
00225       {
00226         return boost::bind (&pcl::PLYReader::originXCallback, this, _1);
00227       }
00228       else if (property_name == "view_py")
00229       {
00230         return boost::bind (&pcl::PLYReader::originYCallback, this, _1);
00231       }
00232       else if (property_name == "view_pz")
00233       {
00234         return boost::bind (&pcl::PLYReader::originZCallback, this, _1);
00235       }
00236       else if (property_name == "x_axisx")
00237       {
00238         return boost::bind (&pcl::PLYReader::orientationXaxisXCallback, this, _1);
00239       }
00240       else if (property_name == "x_axisy")
00241       {
00242         return boost::bind (&pcl::PLYReader::orientationXaxisYCallback, this, _1);
00243       }
00244       else if (property_name == "x_axisz")
00245       {
00246         return boost::bind (&pcl::PLYReader::orientationXaxisZCallback, this, _1);
00247       }
00248       else if (property_name == "y_axisx")
00249       {
00250         return boost::bind (&pcl::PLYReader::orientationYaxisXCallback, this, _1);
00251       }
00252       else if (property_name == "y_axisy")
00253       {
00254         return boost::bind (&pcl::PLYReader::orientationYaxisYCallback, this, _1);
00255       }
00256       else if (property_name == "y_axisz")
00257       {
00258         return boost::bind (&pcl::PLYReader::orientationYaxisZCallback, this, _1);
00259       }
00260       else if (property_name == "z_axisx")
00261       {
00262         return boost::bind (&pcl::PLYReader::orientationZaxisXCallback, this, _1);
00263       }
00264       else if (property_name == "z_axisy")
00265       {
00266         return boost::bind (&pcl::PLYReader::orientationZaxisYCallback, this, _1);
00267       }
00268       else if (property_name == "z_axisz")
00269       {
00270         return boost::bind (&pcl::PLYReader::orientationZaxisZCallback, this, _1);
00271       }
00272       else
00273       {
00274         return (0);
00275       }
00276     }
00277     else
00278     {
00279       return (0);
00280     }
00281   }
00282 
00283   template <> boost::function<void (pcl::io::ply::uint8)>
00284   PLYReader::scalarPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name)
00285   {
00286     if (element_name == "vertex")
00287     {
00288       if ((property_name == "red") || (property_name == "green") || (property_name == "blue") ||
00289           (property_name == "diffuse_red") || (property_name == "diffuse_green") || (property_name == "diffuse_blue"))
00290       {
00291         if ((property_name == "red") || (property_name == "diffuse_red"))
00292           appendFloatProperty ("rgb");
00293         return boost::bind (&pcl::PLYReader::vertexColorCallback, this, property_name, _1);
00294       }
00295       else if (property_name == "alpha")
00296       {
00297         amendProperty ("rgb", "rgba", pcl::PCLPointField::UINT32);
00298         return boost::bind (&pcl::PLYReader::vertexAlphaCallback, this, _1);
00299       }
00300       else if (property_name == "intensity")
00301       {
00302         appendFloatProperty (property_name);
00303         return boost::bind (&pcl::PLYReader::vertexIntensityCallback, this, _1);
00304       }
00305       else
00306       {
00307         appendUnsignedCharProperty (property_name);
00308         return boost::bind (&pcl::PLYReader::vertexUnsignedCharPropertyCallback, this, _1);
00309       }
00310     }
00311     else
00312       return (0);
00313   }
00314 
00315   template <> boost::function<void (pcl::io::ply::int32)>
00316   PLYReader::scalarPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name)
00317   {
00318     if (element_name == "vertex")
00319     {
00320       appendIntProperty (property_name, 1);
00321       return (boost::bind (&pcl::PLYReader::vertexIntPropertyCallback, this, _1));
00322     }
00323     if (element_name == "camera")
00324     {
00325       if (property_name == "viewportx")
00326       {
00327         return boost::bind (&pcl::PLYReader::cloudWidthCallback, this, _1);
00328       }
00329       else if (property_name == "viewporty")
00330       {
00331         return boost::bind (&pcl::PLYReader::cloudHeightCallback, this, _1);
00332       }
00333       else
00334       {
00335         appendIntProperty (property_name, 1);
00336         return (boost::bind (&pcl::PLYReader::vertexIntPropertyCallback, this, _1));
00337       }
00338     }
00339     else
00340       return (0);
00341   }
00342 
00343   template <> boost::function<void (pcl::io::ply::uint32)>
00344   PLYReader::scalarPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name)
00345   {
00346     if (element_name == "vertex")
00347     {
00348       appendUnsignedIntProperty (property_name, 1);
00349       return (boost::bind (&pcl::PLYReader::vertexUnsignedIntPropertyCallback, this, _1));
00350     }
00351     return (0);
00352   }
00353 
00354   template <> boost::function<void (pcl::io::ply::float64)>
00355   PLYReader::scalarPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name)
00356   {
00357     if (element_name == "vertex")
00358     {
00359       appendDoubleProperty (property_name, 1);
00360       return (boost::bind (&pcl::PLYReader::vertexDoublePropertyCallback, this, _1));
00361     }
00362     return (0);
00363   }
00364 
00365   template <> boost::function<void (pcl::io::ply::uint16)>
00366   PLYReader::scalarPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name)
00367   {
00368     if (element_name == "vertex")
00369     {
00370       appendUnsignedShortProperty (property_name, 1);
00371       return (boost::bind (&pcl::PLYReader::vertexUnsignedShortPropertyCallback, this, _1));
00372     }
00373     return (0);
00374   }
00375 
00376   template <> boost::function<void (pcl::io::ply::int16)>
00377   PLYReader::scalarPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name)
00378   {
00379     if (element_name == "vertex")
00380     {
00381       appendShortProperty (property_name, 1);
00382       return (boost::bind (&pcl::PLYReader::vertexShortPropertyCallback, this, _1));
00383     }
00384     return (0);
00385   }
00386 
00387 
00388   template <> boost::function<void (pcl::io::ply::int8)>
00389   PLYReader::scalarPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name)
00390   {
00391     if (element_name == "vertex")
00392     {
00393       appendCharProperty (property_name, 1);
00394       return (boost::bind (&pcl::PLYReader::vertexCharPropertyCallback, this, _1));
00395     }
00396     return (0);
00397   }
00398 
00399   template <typename SizeType> void
00400   PLYReader::vertexListPropertyBeginCallback (const std::string& name, SizeType size)
00401   {
00402     // Adjust size only once
00403     if (vertex_count_ == 0)
00404     {
00405       std::vector< pcl::PCLPointField>::reverse_iterator finder = cloud_->fields.rbegin ();
00406       for (; finder != cloud_->fields.rend (); ++finder)
00407         if (finder->name == name)
00408           break;
00409       assert (finder != cloud_->fields.rend ());
00410       finder->count = size;
00411     }
00412   }
00413 
00414   template<typename ContentType> void
00415   PLYReader::vertexListPropertyContentCallback (ContentType value)
00416   {
00417     memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + vertex_offset_before_],
00418             &value,
00419             sizeof (ContentType));
00420     vertex_offset_before_ += static_cast<int> (sizeof (ContentType));
00421   }
00422 
00423   template <>
00424   boost::tuple<boost::function<void (pcl::io::ply::uint8)>, boost::function<void (pcl::io::ply::int32)>, boost::function<void ()> >
00425   pcl::PLYReader::listPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name)
00426   {
00427     if ((element_name == "range_grid") && (property_name == "vertex_indices")) 
00428     {
00429       return boost::tuple<boost::function<void (pcl::io::ply::uint8)>, boost::function<void (pcl::io::ply::int32)>, boost::function<void ()> > (
00430         boost::bind (&pcl::PLYReader::rangeGridVertexIndicesBeginCallback, this, _1),
00431         boost::bind (&pcl::PLYReader::rangeGridVertexIndicesElementCallback, this, _1),
00432         boost::bind (&pcl::PLYReader::rangeGridVertexIndicesEndCallback, this)
00433       );
00434     }
00435     else if (element_name == "vertex")
00436     {
00437       cloud_->fields.push_back (pcl::PCLPointField ());
00438       pcl::PCLPointField &current_field = cloud_->fields.back ();
00439       current_field.name = property_name;
00440       current_field.offset = cloud_->point_step;
00441       current_field.datatype = pcl::traits::asEnum<pcl::io::ply::int32>::value;
00442       current_field.count = std::numeric_limits<pcl::io::ply::uint8>::max ();
00443       if (current_field.count * sizeof (pcl::io::ply::int32) + cloud_->point_step < std::numeric_limits<uint32_t>::max ())
00444           cloud_->point_step += static_cast<uint32_t> (current_field.count * sizeof (pcl::io::ply::int32));
00445       else
00446         cloud_->point_step = static_cast<uint32_t> (std::numeric_limits<uint32_t>::max ());
00447       do_resize_ = true;
00448       return boost::tuple<boost::function<void (pcl::io::ply::uint8)>, boost::function<void (pcl::io::ply::int32)>, boost::function<void ()> > (
00449                                                                                                       boost::bind (&pcl::PLYReader::vertexListPropertyBeginCallback<pcl::io::ply::uint8>, this, property_name, _1),
00450         boost::bind (&pcl::PLYReader::vertexListPropertyContentCallback<pcl::io::ply::int32>, this, _1),
00451         boost::bind (&pcl::PLYReader::vertexListPropertyEndCallback, this)
00452       );
00453     }
00454     else
00455     {
00456       return boost::tuple<boost::function<void (pcl::io::ply::uint8)>, boost::function<void (pcl::io::ply::int32)>, boost::function<void ()> > (0, 0, 0);
00457     }
00458   }
00459 
00460   template <typename SizeType, typename ContentType>
00461   boost::tuple<boost::function<void (SizeType)>, boost::function<void (ContentType)>, boost::function<void ()> >
00462   pcl::PLYReader::listPropertyDefinitionCallback (const std::string& element_name, const std::string& property_name)
00463   {
00464     if (element_name == "vertex")
00465     {
00466       cloud_->fields.push_back (pcl::PCLPointField ());
00467       pcl::PCLPointField &current_field = cloud_->fields.back ();
00468       current_field.name = property_name;
00469       current_field.offset = cloud_->point_step;
00470       current_field.datatype = pcl::traits::asEnum<ContentType>::value;
00471       current_field.count = std::numeric_limits<SizeType>::max ();
00472       if (current_field.count * sizeof (ContentType) + cloud_->point_step < std::numeric_limits<uint32_t>::max ())
00473         cloud_->point_step += static_cast<uint32_t> (current_field.count * sizeof (ContentType));
00474       else
00475         cloud_->point_step = static_cast<uint32_t> (std::numeric_limits<uint32_t>::max ());
00476       do_resize_ = true;
00477       return boost::tuple<boost::function<void (SizeType)>, boost::function<void (ContentType)>, boost::function<void ()> > (
00478         boost::bind (&pcl::PLYReader::vertexListPropertyBeginCallback<SizeType>, this, property_name, _1),
00479         boost::bind (&pcl::PLYReader::vertexListPropertyContentCallback<ContentType>, this, _1),
00480         boost::bind (&pcl::PLYReader::vertexListPropertyEndCallback, this)
00481       );
00482     }
00483     else
00484     {
00485       return boost::tuple<boost::function<void (SizeType)>, boost::function<void (ContentType)>, boost::function<void ()> > (0, 0, 0);
00486     }
00487   }
00488 
00489 }
00490 
00491 void
00492 pcl::PLYReader::vertexFloatPropertyCallback (pcl::io::ply::float32 value)
00493 {
00494   memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + vertex_offset_before_],
00495           &value,
00496           sizeof (pcl::io::ply::float32));
00497   vertex_offset_before_ += static_cast<int> (sizeof (pcl::io::ply::float32));
00498 }
00499 
00500 void
00501 pcl::PLYReader::vertexDoublePropertyCallback (pcl::io::ply::float64 value)
00502 {
00503   memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + vertex_offset_before_],
00504           &value,
00505           sizeof (pcl::io::ply::float64));
00506   vertex_offset_before_ += static_cast<int> (sizeof (pcl::io::ply::float64));
00507 }
00508 
00509 void
00510 pcl::PLYReader::vertexUnsignedIntPropertyCallback (pcl::io::ply::uint32 value)
00511 {
00512   memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + vertex_offset_before_],
00513           &value,
00514           sizeof (pcl::io::ply::uint32));
00515   vertex_offset_before_ += static_cast<int> (sizeof (pcl::io::ply::uint32));
00516 }
00517 
00518 void
00519 pcl::PLYReader::vertexIntPropertyCallback (pcl::io::ply::int32 value)
00520 {
00521   memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + vertex_offset_before_],
00522           &value,
00523           sizeof (pcl::io::ply::int32));
00524   vertex_offset_before_ += static_cast<int> (sizeof (pcl::io::ply::int32));
00525 }
00526 
00527 void
00528 pcl::PLYReader::vertexUnsignedShortPropertyCallback (pcl::io::ply::uint16 value)
00529 {
00530   memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + vertex_offset_before_],
00531           &value,
00532           sizeof (pcl::io::ply::uint16));
00533   vertex_offset_before_ += static_cast<int> (sizeof (pcl::io::ply::uint16));
00534 }
00535 
00536 void
00537 pcl::PLYReader::vertexShortPropertyCallback (pcl::io::ply::int16 value)
00538 {
00539   memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + vertex_offset_before_],
00540           &value,
00541           sizeof (pcl::io::ply::int16));
00542   vertex_offset_before_ += static_cast<int> (sizeof (pcl::io::ply::int16));
00543 }
00544 
00545 void
00546 pcl::PLYReader::vertexUnsignedCharPropertyCallback (pcl::io::ply::uint8 value)
00547 {
00548   memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + vertex_offset_before_],
00549           &value,
00550           sizeof (pcl::io::ply::uint8));
00551   vertex_offset_before_ += static_cast<int> (sizeof (pcl::io::ply::uint8));
00552 }
00553 
00554 void
00555 pcl::PLYReader::vertexCharPropertyCallback (pcl::io::ply::int8 value)
00556 {
00557   memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + vertex_offset_before_],
00558           &value,
00559           sizeof (pcl::io::ply::int8));
00560   vertex_offset_before_ += static_cast<int> (sizeof (pcl::io::ply::int8));
00561 }
00562 
00563 void
00564 pcl::PLYReader::vertexColorCallback (const std::string& color_name, pcl::io::ply::uint8 color)
00565 {
00566   static int32_t r, g, b;
00567   if ((color_name == "red") || (color_name == "diffuse_red"))
00568   {
00569     r = int32_t (color);
00570     rgb_offset_before_ = vertex_offset_before_;
00571   }
00572   if ((color_name == "green") || (color_name == "diffuse_green"))
00573   {
00574     g = int32_t (color);
00575   }
00576   if ((color_name == "blue") || (color_name == "diffuse_blue"))
00577   {
00578     b = int32_t (color);
00579     int32_t rgb = r << 16 | g << 8 | b;
00580     memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + rgb_offset_before_],
00581             &rgb,
00582             sizeof (pcl::io::ply::float32));
00583     vertex_offset_before_ += static_cast<int> (sizeof (pcl::io::ply::float32));
00584   }
00585 }
00586 
00587 void
00588 pcl::PLYReader::vertexAlphaCallback (pcl::io::ply::uint8 alpha)
00589 {
00590   static uint32_t a, rgba;
00591   a = uint32_t (alpha);
00592   // get anscient rgb value and store it in rgba
00593   memcpy (&rgba, 
00594           &cloud_->data[vertex_count_ * cloud_->point_step + rgb_offset_before_], 
00595           sizeof (pcl::io::ply::float32));
00596   // append alpha
00597   rgba = rgba | a << 24;
00598   // put rgba back
00599   memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + rgb_offset_before_], 
00600           &rgba, 
00601           sizeof (uint32_t));
00602 }
00603 
00604 void
00605 pcl::PLYReader::vertexIntensityCallback (pcl::io::ply::uint8 intensity)
00606 {
00607   pcl::io::ply::float32 intensity_ (intensity);
00608   memcpy (&cloud_->data[vertex_count_ * cloud_->point_step + vertex_offset_before_],
00609           &intensity_,
00610           sizeof (pcl::io::ply::float32));
00611   vertex_offset_before_ += static_cast<int> (sizeof (pcl::io::ply::float32));
00612 }
00613 
00614 void
00615 pcl::PLYReader::vertexBeginCallback ()
00616 {
00617   vertex_offset_before_ = 0;
00618 }
00619 
00620 void
00621 pcl::PLYReader::vertexEndCallback ()
00622 {
00623   // Resize data if needed
00624   if (vertex_count_ == 0 && do_resize_)
00625   {
00626     cloud_->point_step = vertex_offset_before_;
00627     cloud_->row_step = cloud_->point_step * cloud_->width;
00628     cloud_->data.resize (cloud_->point_step * cloud_->width * cloud_->height);
00629   }
00630   ++vertex_count_;
00631 }
00632 
00633 void
00634 pcl::PLYReader::rangeGridBeginCallback () { }
00635 
00636 void
00637 pcl::PLYReader::rangeGridVertexIndicesBeginCallback (pcl::io::ply::uint8 size)
00638 {
00639   (*range_grid_)[range_count_].reserve (size);
00640 }
00641 
00642 void pcl::PLYReader::rangeGridVertexIndicesElementCallback (pcl::io::ply::int32 vertex_index)
00643 {
00644   (*range_grid_)[range_count_].push_back (vertex_index);
00645 }
00646 
00647 void
00648 pcl::PLYReader::rangeGridVertexIndicesEndCallback () { }
00649 
00650 void
00651 pcl::PLYReader::rangeGridEndCallback ()
00652 {
00653   ++range_count_;
00654 }
00655 
00656 void
00657 pcl::PLYReader::objInfoCallback (const std::string& line)
00658 {
00659   std::vector<std::string> st;
00660   boost::split (st, line, boost::is_any_of (std::string ( "\t ")), boost::token_compress_on);
00661   assert (st[0].substr (0, 8) == "obj_info");
00662   {
00663     assert (st.size () == 3);
00664     {
00665       if (st[1] == "num_cols")
00666         cloudWidthCallback (atoi (st[2].c_str ()));
00667       else if (st[1] == "num_rows")
00668         cloudHeightCallback (atoi (st[2].c_str ()));
00669       else if (st[1] == "echo_rgb_offset_x")
00670         originXCallback (static_cast<float> (atof (st[2].c_str ())));
00671       else if (st[1] == "echo_rgb_offset_y")
00672         originYCallback (static_cast<float> (atof (st[2].c_str ())));
00673       else if (st[1] == "echo_rgb_offset_z")
00674         originZCallback (static_cast<float> (atof (st[2].c_str ())));
00675     }
00676   }
00677 }
00678 
00679 void
00680 pcl::PLYReader::vertexListPropertyEndCallback () {}
00681 
00682 bool
00683 pcl::PLYReader::parse (const std::string& istream_filename)
00684 {
00685   pcl::io::ply::ply_parser::flags_type ply_parser_flags = 0;
00686   pcl::io::ply::ply_parser ply_parser (ply_parser_flags);
00687 
00688   ply_parser.info_callback (boost::bind (&pcl::PLYReader::infoCallback, this, boost::ref (istream_filename), _1, _2));
00689   ply_parser.warning_callback (boost::bind (&pcl::PLYReader::warningCallback, this, boost::ref (istream_filename), _1, _2));
00690   ply_parser.error_callback (boost::bind (&pcl::PLYReader::errorCallback, this, boost::ref (istream_filename), _1, _2));
00691 
00692   ply_parser.obj_info_callback (boost::bind (&pcl::PLYReader::objInfoCallback, this, _1));
00693   ply_parser.element_definition_callback (boost::bind (&pcl::PLYReader::elementDefinitionCallback, this, _1, _2));
00694   ply_parser.end_header_callback (boost::bind (&pcl::PLYReader::endHeaderCallback, this));
00695 
00696   pcl::io::ply::ply_parser::scalar_property_definition_callbacks_type scalar_property_definition_callbacks;
00697   pcl::io::ply::at<pcl::io::ply::float64> (scalar_property_definition_callbacks) = boost::bind (&pcl::PLYReader::scalarPropertyDefinitionCallback<pcl::io::ply::float64>, this, _1, _2);
00698   pcl::io::ply::at<pcl::io::ply::float32> (scalar_property_definition_callbacks) = boost::bind (&pcl::PLYReader::scalarPropertyDefinitionCallback<pcl::io::ply::float32>, this, _1, _2);
00699   pcl::io::ply::at<pcl::io::ply::int8> (scalar_property_definition_callbacks) = boost::bind (&pcl::PLYReader::scalarPropertyDefinitionCallback<pcl::io::ply::int8>, this, _1, _2);
00700   pcl::io::ply::at<pcl::io::ply::uint8> (scalar_property_definition_callbacks) = boost::bind (&pcl::PLYReader::scalarPropertyDefinitionCallback<pcl::io::ply::uint8>, this, _1, _2);
00701   pcl::io::ply::at<pcl::io::ply::int32> (scalar_property_definition_callbacks) = boost::bind (&pcl::PLYReader::scalarPropertyDefinitionCallback<pcl::io::ply::int32>, this, _1, _2);
00702   pcl::io::ply::at<pcl::io::ply::uint32> (scalar_property_definition_callbacks) = boost::bind (&pcl::PLYReader::scalarPropertyDefinitionCallback<pcl::io::ply::uint32>, this, _1, _2);
00703   pcl::io::ply::at<pcl::io::ply::int16> (scalar_property_definition_callbacks) = boost::bind (&pcl::PLYReader::scalarPropertyDefinitionCallback<pcl::io::ply::int16>, this, _1, _2);
00704   pcl::io::ply::at<pcl::io::ply::uint16> (scalar_property_definition_callbacks) = boost::bind (&pcl::PLYReader::scalarPropertyDefinitionCallback<pcl::io::ply::uint16>, this, _1, _2);
00705   ply_parser.scalar_property_definition_callbacks (scalar_property_definition_callbacks);
00706 
00707   pcl::io::ply::ply_parser::list_property_definition_callbacks_type list_property_definition_callbacks;
00708   pcl::io::ply::at<pcl::io::ply::uint8, pcl::io::ply::int32> (list_property_definition_callbacks) = boost::bind (&pcl::PLYReader::listPropertyDefinitionCallback<pcl::io::ply::uint8, pcl::io::ply::int32>, this, _1, _2);
00709     pcl::io::ply::at<pcl::io::ply::uint32, pcl::io::ply::float64> (list_property_definition_callbacks) = boost::bind (&pcl::PLYReader::listPropertyDefinitionCallback<pcl::io::ply::uint32, pcl::io::ply::float64>, this, _1, _2);
00710   pcl::io::ply::at<pcl::io::ply::uint32, pcl::io::ply::float32> (list_property_definition_callbacks) = boost::bind (&pcl::PLYReader::listPropertyDefinitionCallback<pcl::io::ply::uint32, pcl::io::ply::float32>, this, _1, _2);
00711   pcl::io::ply::at<pcl::io::ply::uint32, pcl::io::ply::uint32> (list_property_definition_callbacks) = boost::bind (&pcl::PLYReader::listPropertyDefinitionCallback<pcl::io::ply::uint32, pcl::io::ply::uint32>, this, _1, _2);
00712   pcl::io::ply::at<pcl::io::ply::uint32, pcl::io::ply::int32> (list_property_definition_callbacks) = boost::bind (&pcl::PLYReader::listPropertyDefinitionCallback<pcl::io::ply::uint32, pcl::io::ply::int32>, this, _1, _2);
00713   pcl::io::ply::at<pcl::io::ply::uint32, pcl::io::ply::uint16> (list_property_definition_callbacks) = boost::bind (&pcl::PLYReader::listPropertyDefinitionCallback<pcl::io::ply::uint32, pcl::io::ply::uint16>, this, _1, _2);
00714   pcl::io::ply::at<pcl::io::ply::uint32, pcl::io::ply::int16> (list_property_definition_callbacks) = boost::bind (&pcl::PLYReader::listPropertyDefinitionCallback<pcl::io::ply::uint32, pcl::io::ply::int16>, this, _1, _2);
00715   pcl::io::ply::at<pcl::io::ply::uint32, pcl::io::ply::uint8> (list_property_definition_callbacks) = boost::bind (&pcl::PLYReader::listPropertyDefinitionCallback<pcl::io::ply::uint32, pcl::io::ply::uint8>, this, _1, _2);
00716   pcl::io::ply::at<pcl::io::ply::uint32, pcl::io::ply::int8> (list_property_definition_callbacks) = boost::bind (&pcl::PLYReader::listPropertyDefinitionCallback<pcl::io::ply::uint32, pcl::io::ply::int8>, this, _1, _2);
00717   ply_parser.list_property_definition_callbacks (list_property_definition_callbacks);
00718 
00719   return ply_parser.parse (istream_filename);
00720 }
00721 
00723 int
00724 pcl::PLYReader::readHeader (const std::string &file_name, pcl::PCLPointCloud2 &cloud,
00725                             Eigen::Vector4f &, Eigen::Quaternionf &,
00726                             int &, int &, unsigned int &, const int)
00727 {
00728   // Silence compiler warnings
00729   cloud_ = &cloud;
00730   range_grid_ = new std::vector<std::vector<int> >;
00731   cloud_->width = cloud_->height = 0;
00732   if (!parse (file_name))
00733   {
00734     PCL_ERROR ("[pcl::PLYReader::read] problem parsing header!\n");
00735     return (-1);
00736   }
00737   cloud_->row_step = cloud_->point_step * cloud_->width;
00738   return 0;
00739 }
00740 
00742 int
00743 pcl::PLYReader::read (const std::string &file_name, pcl::PCLPointCloud2 &cloud,
00744                       Eigen::Vector4f &origin, Eigen::Quaternionf &orientation, int &ply_version, const int)
00745 {
00746   // kept only for backward compatibility
00747   int data_type;
00748   unsigned int data_idx;
00749 
00750   if (this->readHeader (file_name, cloud, origin, orientation, ply_version, data_type, data_idx))
00751   {
00752     PCL_ERROR ("[pcl::PLYReader::read] problem parsing header!\n");
00753     return (-1);
00754   }
00755 
00756   // a range_grid element was found ?
00757   size_t r_size;
00758   if ((r_size  = (*range_grid_).size ()) > 0 && r_size != vertex_count_)
00759   {
00760     //cloud.header = cloud_->header;
00761     std::vector<pcl::uint8_t> data ((*range_grid_).size () * cloud.point_step);
00762     const static float f_nan = std::numeric_limits <float>::quiet_NaN ();
00763     const static double d_nan = std::numeric_limits <double>::quiet_NaN ();
00764     for (size_t r = 0; r < r_size; ++r)
00765     {
00766       if ((*range_grid_)[r].size () == 0)
00767       {
00768         for (size_t f = 0; f < cloud_->fields.size (); ++f)
00769           if (cloud_->fields[f].datatype == ::pcl::PCLPointField::FLOAT32)
00770             memcpy (&data[r * cloud_->point_step + cloud_->fields[f].offset],
00771                     reinterpret_cast<const char*> (&f_nan), sizeof (float));
00772           else if (cloud_->fields[f].datatype == ::pcl::PCLPointField::FLOAT64)
00773             memcpy (&data[r * cloud_->point_step + cloud_->fields[f].offset],
00774                     reinterpret_cast<const char*> (&d_nan), sizeof (double));
00775           else
00776             memset (&data[r * cloud_->point_step + cloud_->fields[f].offset], 0,
00777                     pcl::getFieldSize (cloud_->fields[f].datatype) * cloud_->fields[f].count);
00778       }
00779       else
00780         memcpy (&data[r* cloud_->point_step], &cloud_->data[(*range_grid_)[r][0] * cloud_->point_step], cloud_->point_step);
00781     }
00782     cloud_->data.swap (data);
00783   }
00784 
00785   orientation = Eigen::Quaternionf (orientation_);
00786   origin = origin_;
00787 
00788   for (size_t i = 0; i < cloud_->fields.size (); ++i)
00789   {
00790     if (cloud_->fields[i].name == "nx")
00791       cloud_->fields[i].name = "normal_x";
00792     if (cloud_->fields[i].name == "ny")
00793       cloud_->fields[i].name = "normal_y";
00794     if (cloud_->fields[i].name == "nz")
00795       cloud_->fields[i].name = "normal_z";
00796   }
00797   return (0);
00798 }
00799 
00801 
00802 std::string
00803 pcl::PLYWriter::generateHeader (const pcl::PCLPointCloud2 &cloud,
00804                                 const Eigen::Vector4f &origin,
00805                                 const Eigen::Quaternionf &,
00806                                 bool binary,
00807                                 bool use_camera,
00808                                 int valid_points)
00809 {
00810   std::ostringstream oss;
00811   // Begin header
00812   oss << "ply";
00813   if (!binary)
00814     oss << "\nformat ascii 1.0";
00815   else
00816   {
00817     if (cloud.is_bigendian)
00818       oss << "\nformat binary_big_endian 1.0";
00819     else
00820       oss << "\nformat binary_little_endian 1.0";
00821   }
00822   oss << "\ncomment PCL generated";
00823 
00824   if (!use_camera)
00825   {
00826     oss << "\nobj_info is_cyberware_data 0"
00827       "\nobj_info is_mesh 0"
00828       "\nobj_info is_warped 0"
00829       "\nobj_info is_interlaced 0";
00830     oss << "\nobj_info num_cols " << cloud.width;
00831     oss << "\nobj_info num_rows " << cloud.height;
00832     oss << "\nobj_info echo_rgb_offset_x " << origin[0];
00833     oss << "\nobj_info echo_rgb_offset_y " << origin[1];
00834     oss << "\nobj_info echo_rgb_offset_z " << origin[2];
00835     oss << "\nobj_info echo_rgb_frontfocus 0.0"
00836       "\nobj_info echo_rgb_backfocus 0.0"
00837       "\nobj_info echo_rgb_pixelsize 0.0"
00838       "\nobj_info echo_rgb_centerpixel 0"
00839       "\nobj_info echo_frames 1"
00840       "\nobj_info echo_lgincr 0.0";
00841   }
00842 
00843   oss << "\nelement vertex "<< valid_points;
00844 
00845   for (std::size_t i = 0; i < cloud.fields.size (); ++i)
00846   {
00847     if (cloud.fields[i].name == "normal_x")
00848     {
00849       oss << "\nproperty float nx";
00850     }
00851     else if (cloud.fields[i].name == "normal_y")
00852     {
00853       oss << "\nproperty float ny";
00854     }
00855     else if (cloud.fields[i].name == "normal_z")
00856     {
00857       oss << "\nproperty float nz";
00858     }
00859     else if (cloud.fields[i].name == "rgb")
00860     {
00861       oss << "\nproperty uchar red"
00862         "\nproperty uchar green"
00863         "\nproperty uchar blue";
00864     }
00865     else if (cloud.fields[i].name == "rgba")
00866     {
00867       oss << "\nproperty uchar red"
00868         "\nproperty uchar green"
00869         "\nproperty uchar blue"
00870         "\nproperty uchar alpha";
00871     }
00872     else
00873     {
00874       oss << "\nproperty";
00875       if (cloud.fields[i].count != 1)
00876         oss << " list uint";
00877       switch (cloud.fields[i].datatype)
00878       {
00879         case pcl::PCLPointField::INT8 : oss << " char "; break;
00880         case pcl::PCLPointField::UINT8 : oss << " uchar "; break;
00881         case pcl::PCLPointField::INT16 : oss << " short "; break;
00882         case pcl::PCLPointField::UINT16 : oss << " ushort "; break;
00883         case pcl::PCLPointField::INT32 : oss << " int "; break;
00884         case pcl::PCLPointField::UINT32 : oss << " uint "; break;
00885         case pcl::PCLPointField::FLOAT32 : oss << " float "; break;
00886         case pcl::PCLPointField::FLOAT64 : oss << " double "; break;
00887         default :
00888         {
00889           PCL_ERROR ("[pcl::PLYWriter::generateHeader] unknown data field type!");
00890           return ("");
00891         }
00892       }
00893       oss << cloud.fields[i].name;
00894     }
00895   }
00896 
00897   if (use_camera)
00898   {
00899     oss << "\nelement camera 1"
00900       "\nproperty float view_px"
00901       "\nproperty float view_py"
00902       "\nproperty float view_pz"
00903       "\nproperty float x_axisx"
00904       "\nproperty float x_axisy"
00905       "\nproperty float x_axisz"
00906       "\nproperty float y_axisx"
00907       "\nproperty float y_axisy"
00908       "\nproperty float y_axisz"
00909       "\nproperty float z_axisx"
00910       "\nproperty float z_axisy"
00911       "\nproperty float z_axisz"
00912       "\nproperty float focal"
00913       "\nproperty float scalex"
00914       "\nproperty float scaley"
00915       "\nproperty float centerx"
00916       "\nproperty float centery"
00917       "\nproperty int viewportx"
00918       "\nproperty int viewporty"
00919       "\nproperty float k1"
00920       "\nproperty float k2";
00921   }
00922   else if (cloud.height > 1)
00923   {
00924     oss << "\nelement range_grid " << cloud.width * cloud.height;
00925     oss << "\nproperty list uchar int vertex_indices";
00926   }
00927 
00928   // End header
00929   oss << "\nend_header\n";
00930   return (oss.str ());
00931 }
00932 
00934 
00935 int
00936 pcl::PLYWriter::writeASCII (const std::string &file_name,
00937                             const pcl::PCLPointCloud2 &cloud,
00938                             const Eigen::Vector4f &origin,
00939                             const Eigen::Quaternionf &orientation,
00940                             int precision,
00941                             bool use_camera)
00942 {
00943   if (cloud.data.empty ())
00944   {
00945     PCL_ERROR ("[pcl::PLYWriter::writeASCII] Input point cloud has no data!\n");
00946     return (-1);
00947   }
00948 
00949   std::ofstream fs;
00950   fs.precision (precision);
00951   // Open file
00952   fs.open (file_name.c_str ());
00953   if (!fs)
00954   {
00955     PCL_ERROR ("[pcl::PLYWriter::writeASCII] Error during opening (%s)!\n", file_name.c_str ());
00956     return (-1);
00957   }
00958 
00959   unsigned int nr_points  = cloud.width * cloud.height;
00960   unsigned int point_size = static_cast<unsigned int> (cloud.data.size () / nr_points);
00961 
00962   // Write the header information if available
00963   if (use_camera)
00964   {
00965     fs << generateHeader (cloud, origin, orientation, false, use_camera, nr_points);
00966     writeContentWithCameraASCII (nr_points, point_size, cloud, origin, orientation, fs);
00967   }
00968   else
00969   {
00970     std::ostringstream os;
00971     int nr_valid_points;
00972     writeContentWithRangeGridASCII (nr_points, point_size, cloud, os, nr_valid_points);
00973     fs << generateHeader (cloud, origin, orientation, false, use_camera, nr_valid_points);
00974     fs << os.str ();
00975   }
00976 
00977   // Close file
00978   fs.close ();
00979   return (0);
00980 }
00981 
00982 void
00983 pcl::PLYWriter::writeContentWithCameraASCII (int nr_points,
00984                                              int point_size,
00985                                              const pcl::PCLPointCloud2 &cloud,
00986                                              const Eigen::Vector4f &origin,
00987                                              const Eigen::Quaternionf &orientation,
00988                                              std::ofstream& fs)
00989 {
00990   // Iterate through the points
00991   for (int i = 0; i < nr_points; ++i)
00992   {
00993     for (size_t d = 0; d < cloud.fields.size (); ++d)
00994     {
00995       int count = cloud.fields[d].count;
00996       if (count == 0)
00997         count = 1; //workaround
00998 
00999       if (count > 1)
01000         fs << count << " ";
01001       for (int c = 0; c < count; ++c)
01002       {
01003         switch (cloud.fields[d].datatype)
01004         {
01005           case pcl::PCLPointField::INT8:
01006           {
01007             char value;
01008             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (char)], sizeof (char));
01009             fs << boost::numeric_cast<int> (value);
01010             break;
01011           }
01012           case pcl::PCLPointField::UINT8:
01013           {
01014             unsigned char value;
01015             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (unsigned char)], sizeof (unsigned char));
01016             fs << boost::numeric_cast<int> (value);
01017             break;
01018           }
01019           case pcl::PCLPointField::INT16:
01020           {
01021             short value;
01022             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (short)], sizeof (short));
01023             fs << boost::numeric_cast<int> (value);
01024             break;
01025           }
01026           case pcl::PCLPointField::UINT16:
01027           {
01028             unsigned short value;
01029             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (unsigned short)], sizeof (unsigned short));
01030             fs << boost::numeric_cast<int> (value);
01031             break;
01032           }
01033           case pcl::PCLPointField::INT32:
01034           {
01035             int value;
01036             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (int)], sizeof (int));
01037             fs << value;
01038             break;
01039           }
01040           case pcl::PCLPointField::UINT32:
01041           {
01042             if (cloud.fields[d].name.find ("rgba") == std::string::npos)
01043             {
01044               unsigned int value;
01045               memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (unsigned int)], sizeof (unsigned int));
01046               fs << value;
01047             }
01048             else
01049             {
01050               pcl::RGB color;
01051               memcpy (&color, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (unsigned int)], sizeof (pcl::RGB));
01052               int r = color.r;
01053               int g = color.g;
01054               int b = color.b;
01055               int a = color.a;
01056               fs << r << " " << g << " " << b << " " << a;
01057             }
01058             break;
01059           }
01060           case pcl::PCLPointField::FLOAT32:
01061           {
01062             if (cloud.fields[d].name.find ("rgb") == std::string::npos)
01063             {
01064               float value;
01065               memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (float)], sizeof (float));
01066               fs << value;
01067             }
01068             else
01069             {
01070               pcl::RGB color;
01071               memcpy (&color, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (float)], sizeof (pcl::RGB));
01072               int r = color.r;
01073               int g = color.g;
01074               int b = color.b;
01075               fs << r << " " << g << " " << b;
01076             }
01077             break;
01078           }
01079           case pcl::PCLPointField::FLOAT64:
01080           {
01081             double value;
01082             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (double)], sizeof (double));
01083             fs << value;
01084             break;
01085           }
01086           default:
01087             PCL_WARN ("[pcl::PLYWriter::writeASCII] Incorrect field data type specified (%d)!\n", cloud.fields[d].datatype);
01088             break;
01089         }
01090 
01091         if (d < cloud.fields.size () - 1 || c < static_cast<int> (cloud.fields[d].count) - 1)
01092           fs << " ";
01093       }
01094     }
01095     fs << std::endl;
01096   }
01097   // Append sensor information
01098   if (origin[3] != 0)
01099     fs << origin[0]/origin[3] << " " << origin[1]/origin[3] << " " << origin[2]/origin[3] << " ";
01100   else
01101     fs << origin[0] << " " << origin[1] << " " << origin[2] << " ";
01102 
01103   Eigen::Matrix3f R = orientation.toRotationMatrix ();
01104   fs << R (0,0) << " " << R (0,1) << " " << R (0,2) << " ";
01105   fs << R (1,0) << " " << R (1,1) << " " << R (1,2) << " ";
01106   fs << R (2,0) << " " << R (2,1) << " " << R (2,2) << " ";
01107   // No focal
01108   fs << 0 << " ";
01109   // No scale
01110   fs << 0 << " " << 0 << " ";
01111   // No center
01112   fs << 0 << " " << 0 << " ";
01113   // Viewport set to width x height
01114   fs << cloud.width << " " << cloud.height << " ";
01115   // No corrections
01116   fs << 0 << " " << 0;
01117   fs << std::endl;
01118   fs.flush ();
01119 }
01120 
01121 void
01122 pcl::PLYWriter::writeContentWithRangeGridASCII (int nr_points,
01123                                                 int point_size,
01124                                                 const pcl::PCLPointCloud2 &cloud,
01125                                                 std::ostringstream& fs,
01126                                                 int& valid_points)
01127 {
01128   valid_points = 0;
01129   std::vector<std::vector <int> > grids (nr_points);
01130   // Iterate through the points
01131   for (int i = 0; i < nr_points; ++i)
01132   {
01133     std::ostringstream line;
01134     bool is_valid_line = true;
01135     for (size_t d = 0; d < cloud.fields.size (); ++d)
01136     {
01137       int count = cloud.fields[d].count;
01138       if (count == 0)
01139         count = 1; //workaround
01140       if (count > 1)
01141         fs << count << " ";
01142       for (int c = 0; c < count; ++c)
01143       {
01144         switch (cloud.fields[d].datatype)
01145         {
01146           case pcl::PCLPointField::INT8:
01147           {
01148             char value;
01149             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (char)], sizeof (char));
01150             line << boost::numeric_cast<int> (value);
01151             break;
01152           }
01153           case pcl::PCLPointField::UINT8:
01154           {
01155             unsigned char value;
01156             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (unsigned char)], sizeof (unsigned char));
01157             line << boost::numeric_cast<int> (value);
01158             break;
01159           }
01160           case pcl::PCLPointField::INT16:
01161           {
01162             short value;
01163             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (short)], sizeof (short));
01164             line << boost::numeric_cast<int> (value);
01165             break;
01166           }
01167           case pcl::PCLPointField::UINT16:
01168           {
01169             unsigned short value;
01170             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (unsigned short)], sizeof (unsigned short));
01171             line << boost::numeric_cast<int> (value);
01172             break;
01173           }
01174           case pcl::PCLPointField::INT32:
01175           {
01176             int value;
01177             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (int)], sizeof (int));
01178             line << value;
01179             break;
01180           }
01181           case pcl::PCLPointField::UINT32:
01182           {
01183             if (cloud.fields[d].name.find ("rgba") == std::string::npos)
01184             {
01185               unsigned int value;
01186               memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (unsigned int)], sizeof (unsigned int));
01187               line << value;
01188             }
01189             else
01190             {
01191               pcl::RGB color;
01192               memcpy (&color, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (unsigned int)], sizeof (pcl::RGB));
01193               int r = color.r;
01194               int g = color.g;
01195               int b = color.b;
01196               int a = color.a;
01197               line << r << " " << g << " " << b << " " << a;
01198             }
01199             break;
01200           }
01201           case pcl::PCLPointField::FLOAT32:
01202           {
01203             if (cloud.fields[d].name.find ("rgb") == std::string::npos)
01204             {
01205               float value;
01206               memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (float)], sizeof (float));
01207               // Test if x-coordinate is NaN, thus an invalid point
01208               if ("x" == cloud.fields[d].name)
01209               {
01210                 if (!pcl_isfinite(value))
01211                   is_valid_line = false;
01212               }
01213               line << value;
01214             }
01215             else
01216             {
01217               pcl::RGB color;
01218               memcpy (&color, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (float)], sizeof (pcl::RGB));
01219               int r = color.r;
01220               int g = color.g;
01221               int b = color.b;
01222               line << r << " " << g << " " << b;
01223             }
01224             break;
01225           }
01226           case pcl::PCLPointField::FLOAT64:
01227           {
01228             double value;
01229             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (double)], sizeof (double));
01230             line << value;
01231             break;
01232           }
01233           default:
01234             PCL_WARN ("[pcl::PLYWriter::writeASCII] Incorrect field data type specified (%d)!\n", cloud.fields[d].datatype);
01235             break;
01236         }
01237 
01238         if (d < cloud.fields.size () - 1 || c < static_cast<int> (cloud.fields[d].count) - 1)
01239           line << " ";
01240       }
01241     }
01242 
01243     if (is_valid_line)
01244     {
01245       grids[i].push_back (valid_points);
01246       fs << line.str () << std::endl;
01247       ++valid_points;
01248     }
01249   }
01250 
01251   // If point cloud is organized, then append range grid
01252   if (cloud.height > 1)
01253   {
01254     for (int i = 0; i < nr_points; ++i)
01255     {
01256       fs << grids [i].size ();
01257       for (std::vector <int>::const_iterator it = grids [i].begin ();
01258            it != grids [i].end ();
01259            ++it)
01260         fs << " " << *it;
01261       fs << std::endl;
01262     }
01263   }
01264 
01265   fs.flush ();
01266 }
01267 
01269 int
01270 pcl::PLYWriter::writeBinary (const std::string &file_name,
01271                              const pcl::PCLPointCloud2 &cloud,
01272                              const Eigen::Vector4f &origin,
01273                              const Eigen::Quaternionf &orientation,
01274                              bool use_camera)
01275 {
01276   if (cloud.data.empty ())
01277   {
01278     PCL_ERROR ("[pcl::PLYWriter::writeBinary] Input point cloud has no data!\n");
01279     return (-1);
01280   }
01281 
01282   std::ofstream fs;
01283   fs.open (file_name.c_str ());      // Open file
01284   if (!fs)
01285   {
01286     PCL_ERROR ("[pcl::PLYWriter::writeBinary] Error during opening (%s)!\n", file_name.c_str ());
01287     return (-1);
01288   }
01289 
01290   unsigned int nr_points  = cloud.width * cloud.height;
01291   unsigned int point_size = static_cast<unsigned int> (cloud.data.size () / nr_points);
01292 
01293   // Compute the range_grid, if necessary, and then write out the PLY header
01294   bool doRangeGrid = !use_camera && cloud.height > 1;
01295   std::vector<pcl::io::ply::int32> rangegrid (nr_points);
01296   if (doRangeGrid)
01297   {
01298     unsigned int valid_points = 0;
01299 
01300     // Determine the field containing the x-coordinate
01301     int xfield = pcl::getFieldIndex (cloud, "x");
01302     if (xfield >= 0 && cloud.fields[xfield].datatype != pcl::PCLPointField::FLOAT32)
01303       xfield = -1;
01304 
01305     // If no x-coordinate field exists, then assume all points are valid
01306     if (xfield < 0)
01307     {
01308       for (unsigned int i=0; i < nr_points; ++i)
01309         rangegrid[i] = i;
01310       valid_points = nr_points;
01311     }
01312     // Otherwise, look at their x-coordinates to determine if points are valid
01313     else
01314     {
01315       for (size_t i=0; i < nr_points; ++i)
01316       {
01317         float value;
01318         memcpy(&value, &cloud.data[i * point_size + cloud.fields[xfield].offset], sizeof(float));
01319         if (pcl_isfinite(value))
01320         {
01321           rangegrid[i] = valid_points;
01322           ++valid_points;
01323         }
01324         else
01325           rangegrid[i] = -1;
01326       }
01327     }
01328     fs << generateHeader (cloud, origin, orientation, true, use_camera, valid_points);
01329   }
01330   else
01331   {
01332     fs << generateHeader (cloud, origin, orientation, true, use_camera, nr_points);
01333   }
01334 
01335   // Close the file
01336   fs.close ();
01337   // Open file in binary appendable
01338   std::ofstream fpout (file_name.c_str (), std::ios::app | std::ios::binary);
01339   if (!fpout)
01340   {
01341     PCL_ERROR ("[pcl::PLYWriter::writeBinary] Error during reopening (%s)!\n", file_name.c_str ());
01342     return (-1);
01343   }
01344 
01345   // Iterate through the points
01346   for (unsigned int i = 0; i < nr_points; ++i)
01347   {
01348     // Skip writing any invalid points from range_grid
01349     if (doRangeGrid && rangegrid[i] < 0)
01350       continue;
01351 
01352     size_t total = 0;
01353     for (size_t d = 0; d < cloud.fields.size (); ++d)
01354     {
01355       int count = cloud.fields[d].count;
01356       if (count == 0)
01357         count = 1; //workaround
01358       if (count > 1)
01359       {
01360         static unsigned int ucount (count);
01361         fpout.write (reinterpret_cast<const char*> (&ucount), sizeof (unsigned int));
01362       }
01363       // Ignore invalid padded dimensions that are inherited from binary data
01364       if (cloud.fields[d].name == "_")
01365       {
01366         total += cloud.fields[d].count; // jump over this many elements in the string token
01367         continue;
01368       }
01369 
01370       for (int c = 0; c < count; ++c)
01371       {
01372         switch (cloud.fields[d].datatype)
01373         {
01374           case pcl::PCLPointField::INT8:
01375           {
01376             char value;
01377             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (char)], sizeof (char));
01378             fpout.write (reinterpret_cast<const char*> (&value), sizeof (char));
01379             break;
01380           }
01381           case pcl::PCLPointField::UINT8:
01382           {
01383             unsigned char value;
01384             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (unsigned char)], sizeof (unsigned char));
01385             fpout.write (reinterpret_cast<const char*> (&value), sizeof (unsigned char));
01386             break;
01387           }
01388           case pcl::PCLPointField::INT16:
01389           {
01390             short value;
01391             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (short)], sizeof (short));
01392             fpout.write (reinterpret_cast<const char*> (&value), sizeof (short));
01393             break;
01394           }
01395           case pcl::PCLPointField::UINT16:
01396           {
01397             unsigned short value;
01398             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (unsigned short)], sizeof (unsigned short));
01399             fpout.write (reinterpret_cast<const char*> (&value), sizeof (unsigned short));
01400             break;
01401           }
01402           case pcl::PCLPointField::INT32:
01403           {
01404             int value;
01405             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (int)], sizeof (int));
01406             fpout.write (reinterpret_cast<const char*> (&value), sizeof (int));
01407             break;
01408           }
01409           case pcl::PCLPointField::UINT32:
01410           {
01411             if (cloud.fields[d].name.find ("rgba") == std::string::npos)
01412             {
01413               unsigned int value;
01414               memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (unsigned int)], sizeof (unsigned int));
01415               fpout.write (reinterpret_cast<const char*> (&value), sizeof (unsigned int));
01416             }
01417             else
01418             {
01419               pcl::RGB color;
01420               memcpy (&color, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (unsigned int)], sizeof (pcl::RGB));
01421               unsigned char r = color.r;
01422               unsigned char g = color.g;
01423               unsigned char b = color.b;
01424               unsigned char a = color.a;
01425               fpout.write (reinterpret_cast<const char*> (&r), sizeof (unsigned char));
01426               fpout.write (reinterpret_cast<const char*> (&g), sizeof (unsigned char));
01427               fpout.write (reinterpret_cast<const char*> (&b), sizeof (unsigned char));
01428               fpout.write (reinterpret_cast<const char*> (&a), sizeof (unsigned char));
01429             }
01430             break;
01431           }
01432           case pcl::PCLPointField::FLOAT32:
01433           {
01434             if (cloud.fields[d].name.find ("rgb") == std::string::npos)
01435             {
01436               float value;
01437               memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (float)], sizeof (float));
01438               fpout.write (reinterpret_cast<const char*> (&value), sizeof (float));
01439             }
01440             else
01441             {
01442               pcl::RGB color;
01443               memcpy (&color, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (float)], sizeof (pcl::RGB));
01444               unsigned char r = color.r;
01445               unsigned char g = color.g;
01446               unsigned char b = color.b;
01447               fpout.write (reinterpret_cast<const char*> (&r), sizeof (unsigned char));
01448               fpout.write (reinterpret_cast<const char*> (&g), sizeof (unsigned char));
01449               fpout.write (reinterpret_cast<const char*> (&b), sizeof (unsigned char));
01450             }
01451             break;
01452           }
01453           case pcl::PCLPointField::FLOAT64:
01454           {
01455             double value;
01456             memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + (total + c) * sizeof (double)], sizeof (double));
01457             fpout.write (reinterpret_cast<const char*> (&value), sizeof (double));
01458             break;
01459           }
01460           default:
01461             PCL_WARN ("[pcl::PLYWriter::writeBinary] Incorrect field data type specified (%d)!\n", cloud.fields[d].datatype);
01462             break;
01463         }
01464       }
01465     }
01466   }
01467 
01468   if (use_camera)
01469   {
01470     // Append sensor information
01471     float t;
01472     for (int i = 0; i < 3; ++i)
01473     {
01474       if (origin[3] != 0)
01475         t = origin[i]/origin[3];
01476       else
01477         t = origin[i];
01478       fpout.write (reinterpret_cast<const char*> (&t), sizeof (float));
01479     }
01480     Eigen::Matrix3f R = orientation.toRotationMatrix ();
01481     for (int i = 0; i < 3; ++i)
01482       for (int j = 0; j < 3; ++j)
01483     {
01484       fpout.write (reinterpret_cast<const char*> (&R (i, j)),sizeof (float));
01485     }
01486 
01488     // Append those properties directly.               //
01489     // They are for perspective cameras so just put 0  //
01490     //                                                 //
01491     // property float focal                            //
01492     // property float scalex                           //
01493     // property float scaley                           //
01494     // property float centerx                          //
01495     // property float centery                          //
01496     // and later on                                    //
01497     // property float k1                               //
01498     // property float k2                               //
01500 
01501     const float zerof = 0;
01502     for (int i = 0; i < 5; ++i)
01503       fpout.write (reinterpret_cast<const char*> (&zerof), sizeof (float));
01504 
01505     // width and height
01506     int width = cloud.width;
01507     fpout.write (reinterpret_cast<const char*> (&width), sizeof (int));
01508 
01509     int height = cloud.height;
01510     fpout.write (reinterpret_cast<const char*> (&height), sizeof (int));
01511 
01512     for (int i = 0; i < 2; ++i)
01513       fpout.write (reinterpret_cast<const char*> (&zerof), sizeof (float));
01514   }
01515   else if (doRangeGrid)
01516   {
01517     // Write out range_grid
01518     for (size_t i=0; i < nr_points; ++i)
01519     {
01520       pcl::io::ply::uint8 listlen;
01521 
01522       if (rangegrid[i] >= 0)
01523       {
01524         listlen = 1;
01525         fpout.write (reinterpret_cast<const char*> (&listlen), sizeof (pcl::io::ply::uint8));
01526         fpout.write (reinterpret_cast<const char*> (&rangegrid[i]), sizeof (pcl::io::ply::int32));
01527       }
01528       else
01529       {
01530         listlen = 0;
01531         fpout.write (reinterpret_cast<const char*> (&listlen), sizeof (pcl::io::ply::uint8));
01532       }
01533     }
01534   }
01535 
01536   // Close file
01537   fpout.close ();
01538   return (0);
01539 }
01540 
01542 int
01543 pcl::io::savePLYFile (const std::string &file_name, const pcl::PolygonMesh &mesh, unsigned precision)
01544 {
01545   if (mesh.cloud.data.empty ())
01546   {
01547     PCL_ERROR ("[pcl::io::savePLYFile] Input point cloud has no data!\n");
01548     return (-1);
01549   }
01550   // Open file
01551   std::ofstream fs;
01552   fs.precision (precision);
01553   fs.open (file_name.c_str ());
01554   if (!fs)
01555   {
01556     PCL_ERROR ("[pcl::io::savePLYFile] Error during opening (%s)!\n", file_name.c_str ());
01557     return (-1);
01558   }
01559 
01560   // number of points
01561   size_t nr_points  = mesh.cloud.width * mesh.cloud.height;
01562   size_t point_size = mesh.cloud.data.size () / nr_points;
01563 
01564   // number of faces
01565   size_t nr_faces = mesh.polygons.size ();
01566 
01567   // Write header
01568   fs << "ply";
01569   fs << "\nformat ascii 1.0";
01570   fs << "\ncomment PCL generated";
01571   // Vertices
01572   fs << "\nelement vertex "<< mesh.cloud.width * mesh.cloud.height;
01573   fs << "\nproperty float x"
01574         "\nproperty float y"
01575         "\nproperty float z";
01576   // Check if we have color on vertices
01577   int rgba_index = getFieldIndex (mesh.cloud, "rgba"),
01578   rgb_index = getFieldIndex (mesh.cloud, "rgb");
01579   if (rgba_index != -1)
01580   {
01581     fs << "\nproperty uchar red"
01582           "\nproperty uchar green"
01583           "\nproperty uchar blue"
01584           "\nproperty uchar alpha";
01585   }
01586   else if (rgb_index != -1)
01587   {
01588     fs << "\nproperty uchar red"
01589           "\nproperty uchar green"
01590           "\nproperty uchar blue";
01591   }
01592   // Faces
01593   fs << "\nelement face "<< nr_faces;
01594   fs << "\nproperty list uchar int vertex_index";
01595   fs << "\nend_header\n";
01596 
01597   // Write down vertices
01598   for (size_t i = 0; i < nr_points; ++i)
01599   {
01600     int xyz = 0;
01601     for (size_t d = 0; d < mesh.cloud.fields.size (); ++d)
01602     {
01603       int count = mesh.cloud.fields[d].count;
01604       if (count == 0)
01605         count = 1;          // we simply cannot tolerate 0 counts (coming from older converter code)
01606       int c = 0;
01607 
01608       // adding vertex
01609       if ((mesh.cloud.fields[d].datatype == pcl::PCLPointField::FLOAT32) && (
01610           mesh.cloud.fields[d].name == "x" ||
01611           mesh.cloud.fields[d].name == "y" ||
01612           mesh.cloud.fields[d].name == "z"))
01613       {
01614         float value;
01615         memcpy (&value, &mesh.cloud.data[i * point_size + mesh.cloud.fields[d].offset + c * sizeof (float)], sizeof (float));
01616         fs << value;
01617         // if (++xyz == 3)
01618         //   break;
01619         ++xyz;
01620       }
01621       else if ((mesh.cloud.fields[d].datatype == pcl::PCLPointField::FLOAT32) &&
01622                 (mesh.cloud.fields[d].name == "rgb"))
01623 
01624       {
01625         pcl::RGB color;
01626         memcpy (&color, &mesh.cloud.data[i * point_size + mesh.cloud.fields[rgb_index].offset + c * sizeof (float)], sizeof (RGB));
01627         fs << int (color.r) << " " << int (color.g) << " " << int (color.b);
01628       }
01629       else if ((mesh.cloud.fields[d].datatype == pcl::PCLPointField::UINT32) &&
01630                (mesh.cloud.fields[d].name == "rgba"))
01631       {
01632         pcl::RGB color;
01633         memcpy (&color, &mesh.cloud.data[i * point_size + mesh.cloud.fields[rgba_index].offset + c * sizeof (uint32_t)], sizeof (RGB));
01634         fs << int (color.r) << " " << int (color.g) << " " << int (color.b) << " " << int (color.a);
01635       }
01636       fs << " ";
01637     }
01638     if (xyz != 3)
01639     {
01640       PCL_ERROR ("[pcl::io::savePLYFile] Input point cloud has no XYZ data!\n");
01641       return (-2);
01642     }
01643     fs << std::endl;
01644   }
01645 
01646   // Write down faces
01647   for (size_t i = 0; i < nr_faces; i++)
01648   {
01649     fs << mesh.polygons[i].vertices.size () << " ";
01650     size_t j = 0;
01651     for (j = 0; j < mesh.polygons[i].vertices.size () - 1; ++j)
01652       fs << mesh.polygons[i].vertices[j] << " ";
01653     fs << mesh.polygons[i].vertices[j] << std::endl;
01654   }
01655 
01656   // Close file
01657   fs.close ();
01658   return (0);
01659 }
01660 
01662 int
01663 pcl::io::savePLYFileBinary (const std::string &file_name, const pcl::PolygonMesh &mesh)
01664 {
01665   if (mesh.cloud.data.empty ())
01666   {
01667     PCL_ERROR ("[pcl::io::savePLYFile] Input point cloud has no data!\n");
01668     return (-1);
01669   }
01670   // Open file
01671   std::ofstream fs;
01672   fs.open (file_name.c_str ());
01673   if (!fs)
01674   {
01675     PCL_ERROR ("[pcl::io::savePLYFile] Error during opening (%s)!\n", file_name.c_str ());
01676     return (-1);
01677   }
01678 
01679   // number of points
01680   size_t nr_points  = mesh.cloud.width * mesh.cloud.height;
01681   size_t point_size = mesh.cloud.data.size () / nr_points;
01682 
01683   // number of faces
01684   size_t nr_faces = mesh.polygons.size ();
01685 
01686   // Write header
01687   fs << "ply";
01688   fs << "\nformat " << (mesh.cloud.is_bigendian ? "binary_big_endian" : "binary_little_endian") << " 1.0";
01689   fs << "\ncomment PCL generated";
01690   // Vertices
01691   fs << "\nelement vertex "<< mesh.cloud.width * mesh.cloud.height;
01692   fs << "\nproperty float x"
01693         "\nproperty float y"
01694         "\nproperty float z";
01695   // Check if we have color on vertices
01696   int rgba_index = getFieldIndex (mesh.cloud, "rgba"),
01697   rgb_index = getFieldIndex (mesh.cloud, "rgb");
01698   if (rgba_index != -1)
01699   {
01700     fs << "\nproperty uchar red"
01701           "\nproperty uchar green"
01702           "\nproperty uchar blue"
01703           "\nproperty uchar alpha";
01704   }
01705   else if (rgb_index != -1)
01706   {
01707     fs << "\nproperty uchar red"
01708           "\nproperty uchar green"
01709           "\nproperty uchar blue";
01710   }
01711   // Faces
01712   fs << "\nelement face "<< nr_faces;
01713   fs << "\nproperty list uchar int vertex_index";
01714   fs << "\nend_header\n";
01715 
01716   // Close the file
01717   fs.close ();
01718   // Open file in binary appendable
01719   std::ofstream fpout (file_name.c_str (), std::ios::app | std::ios::binary);
01720   if (!fpout)
01721   {
01722     PCL_ERROR ("[pcl::io::writePLYFileBinary] Error during reopening (%s)!\n", file_name.c_str ());
01723     return (-1);
01724   }
01725 
01726   // Write down vertices
01727   for (size_t i = 0; i < nr_points; ++i)
01728   {
01729     int xyz = 0;
01730     for (size_t d = 0; d < mesh.cloud.fields.size (); ++d)
01731     {
01732       int count = mesh.cloud.fields[d].count;
01733       if (count == 0)
01734         count = 1;          // we simply cannot tolerate 0 counts (coming from older converter code)
01735       int c = 0;
01736 
01737       // adding vertex
01738       if ((mesh.cloud.fields[d].datatype == pcl::PCLPointField::FLOAT32) && (
01739           mesh.cloud.fields[d].name == "x" ||
01740           mesh.cloud.fields[d].name == "y" ||
01741           mesh.cloud.fields[d].name == "z"))
01742       {
01743         float value;
01744         memcpy (&value, &mesh.cloud.data[i * point_size + mesh.cloud.fields[d].offset + c * sizeof (float)], sizeof (float));
01745         fpout.write (reinterpret_cast<const char*> (&value), sizeof (float));
01746         // if (++xyz == 3)
01747         //   break;
01748         ++xyz;
01749       }
01750       else if ((mesh.cloud.fields[d].datatype == pcl::PCLPointField::FLOAT32) &&
01751                 (mesh.cloud.fields[d].name == "rgb"))
01752 
01753       {
01754         pcl::RGB color;
01755         memcpy (&color, &mesh.cloud.data[i * point_size + mesh.cloud.fields[rgb_index].offset + c * sizeof (float)], sizeof (RGB));
01756         fpout.write (reinterpret_cast<const char*> (&color.r), sizeof (unsigned char));
01757         fpout.write (reinterpret_cast<const char*> (&color.g), sizeof (unsigned char));
01758         fpout.write (reinterpret_cast<const char*> (&color.b), sizeof (unsigned char));
01759       }
01760       else if ((mesh.cloud.fields[d].datatype == pcl::PCLPointField::UINT32) &&
01761                (mesh.cloud.fields[d].name == "rgba"))
01762       {
01763         pcl::RGB color;
01764         memcpy (&color, &mesh.cloud.data[i * point_size + mesh.cloud.fields[rgba_index].offset + c * sizeof (uint32_t)], sizeof (RGB));
01765         fpout.write (reinterpret_cast<const char*> (&color.r), sizeof (unsigned char));
01766         fpout.write (reinterpret_cast<const char*> (&color.g), sizeof (unsigned char));
01767         fpout.write (reinterpret_cast<const char*> (&color.b), sizeof (unsigned char));
01768         fpout.write (reinterpret_cast<const char*> (&color.a), sizeof (unsigned char));
01769       }
01770     }
01771     if (xyz != 3)
01772     {
01773       PCL_ERROR ("[pcl::io::savePLYFile] Input point cloud has no XYZ data!\n");
01774       return (-2);
01775     }
01776   }
01777 
01778   // Write down faces
01779   for (size_t i = 0; i < nr_faces; i++)
01780   {
01781     unsigned char value = static_cast<unsigned char> (mesh.polygons[i].vertices.size ());
01782     fpout.write (reinterpret_cast<const char*> (&value), sizeof (unsigned char));
01783     size_t j = 0;
01784     for (j = 0; j < mesh.polygons[i].vertices.size (); ++j)
01785     {
01786       //fs << mesh.polygons[i].vertices[j] << " ";
01787       int value = mesh.polygons[i].vertices[j];
01788       fpout.write (reinterpret_cast<const char*> (&value), sizeof (int));
01789     }
01790   }
01791 
01792   // Close file
01793   fs.close ();
01794   return (0);
01795 }


pcl
Author(s): Open Perception
autogenerated on Wed Aug 26 2015 15:28:18