nanoply.hpp
Go to the documentation of this file.
00001 /****************************************************************************
00002 * NanoPLY                                                                   *
00003 * NanoPLY is a C++11 header-only library to read and write PLY file         *
00004 *                                                                           *
00005 * Copyright(C) 2014-2015                                                    *
00006 * Visual Computing Lab                                                      *
00007 * ISTI - Italian National Research Council                                  *
00008 *                                                                           *
00009 * This Source Code Form is subject to the terms of the Mozilla Public       *
00010 * License, v. 2.0. If a copy of the MPL was not distributed with this       *
00011 * file, You can obtain one at http://mozilla.org/MPL/2.0/.                  *
00012 *                                                                           *
00013 ****************************************************************************/
00014 
00015 
00016 #ifndef NANOPLY_HPP
00017 #define NANOPLY_HPP
00018 
00019 #include <vector>
00020 #include <unordered_map>
00021 #include <tuple>
00022 #include <cassert>
00023 #include <algorithm>
00024 #include <stdexcept>
00025 #include <cstdio>
00026 #include <cmath>
00027 #include <limits>
00028 #include <fstream>
00029 #include <sstream>
00030 #include <stdint.h>
00031 #include <string>
00032 
00033 
00034 // Avoid conflicting declaration of min/max macros in windows headers
00035 #if !defined(NOMINMAX) && (defined(_WIN32) || defined(_WIN32_)  || defined(WIN32) || defined(_WIN64))
00036 # define NOMINMAX
00037 # ifdef max
00038 #  undef   max
00039 #  undef   min
00040 # endif
00041 #endif
00042 
00043 namespace nanoply
00044 {
00045 
00049   typedef enum NNP_ERROR
00050   {
00051     NNP_OK = 0x0000,  
00052     NNP_UNABLE_TO_OPEN = 0x0001,  
00053     NNP_MISSING_HEADER = 0x0002,  
00054     NNP_MISSING_FORMAT = 0x0004,  
00055     NNP_INVALID_ELEMENT = 0x0008,  
00056     NNP_INVALID_PROPERTY = 0x0010         
00057   } ErrorCode;
00058 
00059 
00063   typedef enum NNP_ELEM
00064   {
00065     NNP_UNKNOWN_ELEM = 0x0, 
00066     NNP_VERTEX_ELEM = 0x1, 
00067     NNP_EDGE_ELEM = 0x2, 
00068     NNP_FACE_ELEM = 0x4  
00069   } PlyElemEntity;
00070 
00071 
00075   typedef enum NNP_ENTITY
00076   {
00077     NNP_UNKNOWN_ENTITY = 0x00000000,    
00078     NNP_PX = 0x00000001,        
00079     NNP_PY = 0x00000002,        
00080     NNP_PZ = 0x00000004,        
00081     NNP_PXYZ = 0x00000007,      
00082     NNP_NX = 0x00000010,        
00083     NNP_NY = 0x00000020,        
00084     NNP_NZ = 0x00000040,        
00085     NNP_NXYZ = 0x00000070,      
00086     NNP_CR = 0x00000100,        
00087     NNP_CG = 0x00000200,        
00088     NNP_CB = 0x00000400,        
00089     NNP_CRGB = 0x00000700,      
00090     NNP_CA = 0x00000800,        
00091     NNP_CRGBA = 0x00000F00,     
00092     NNP_DENSITY = 0x00000008,   
00093     NNP_SCALE = 0x00000080,     
00094     NNP_TEXTUREU = 0x00001000,  
00095     NNP_TEXTUREV = 0x00002000,  
00096     NNP_TEXTURE2D = 0x00003000, 
00097     NNP_TEXTUREW = 0x00004000,  
00098     NNP_TEXTURE3D = 0x00007000, 
00099     NNP_TEXTUREINDEX = 0x00008000,      
00100     NNP_QUALITY = 0x00010000,   
00101     NNP_REFLECTANCE = 0x00020000,       
00102     NNP_BITFLAG = 0x00040000,   
00103     NNP_K1 = 0x00080000,        
00104     NNP_K2 = 0x00100000,        
00105     NNP_KG = 0x00200000,        
00106     NNP_KH = 0x00400000, 
00107     NNP_K1DIR = 0x00800000, 
00108     NNP_K2DIR = 0x01000000, 
00109     NNP_EDGE_V1 = 0x02000000,   
00110     NNP_EDGE_V2 = 0x04000000,   
00111     NNP_FACE_VERTEX_LIST = 0x08000000, 
00112     NNP_FACE_WEDGE_COLOR = 0x10000000, 
00113     NNP_FACE_WEDGE_NORMAL = 0x20000000, 
00114     NNP_FACE_WEDGE_TEX = 0x40000000  
00115   } PlyEntity;
00116 
00117 
00121   typedef enum NNP_PLYTYPE
00122   {
00123     NNP_UNKNOWN_TYPE = 0x000000, 
00124     NNP_FLOAT32 = 0x000001, 
00125     NNP_FLOAT64 = 0x000002, 
00126     NNP_INT8 = 0x000004, 
00127     NNP_INT16 = 0x000008, 
00128     NNP_INT32 = 0x000010, 
00129     NNP_UINT8 = 0x000020, 
00130     NNP_UINT16 = 0x000040, 
00131     NNP_UINT32 = 0x000080, 
00132     NNP_LIST_UINT8_UINT32 = 0x000100, 
00133     NNP_LIST_INT8_UINT32 = 0x000200, 
00134     NNP_LIST_UINT8_INT32 = 0x000400, 
00135     NNP_LIST_INT8_INT32 = 0x000800, 
00136     NNP_LIST_UINT8_FLOAT32 = 0x001000, 
00137     NNP_LIST_INT8_FLOAT32 = 0x002000, 
00138     NNP_LIST_UINT8_FLOAT64 = 0x004000, 
00139     NNP_LIST_INT8_FLOAT64 = 0x008000, 
00140     NNP_LIST_UINT8_UINT8 = 0x010000, 
00141     NNP_LIST_INT8_UINT8 = 0x020000, 
00142     NNP_LIST_UINT8_INT8 = 0x040000, 
00143     NNP_LIST_INT8_INT8 = 0x080000, 
00144     NNP_LIST_UINT8_UINT16 = 0x100000, 
00145     NNP_LIST_INT8_UINT16 = 0x200000, 
00146     NNP_LIST_UINT8_INT16 = 0x400000, 
00147     NNP_LIST_INT8_INT16 = 0x800000  
00148   } PlyType;
00149 
00150 
00154   template < size_t T> struct SizeT {};
00155 
00156   typedef std::vector<std::string> NameVector;
00157   typedef std::unordered_map<PlyType, NameVector> TypeMap;
00158   typedef std::unordered_map<PlyType, NameVector>::iterator TypeMapIterator;
00159   typedef std::unordered_map<PlyEntity, NameVector> EntityMap;
00160   typedef std::unordered_map<PlyEntity, NameVector>::iterator EntityMapIterator;
00161   typedef std::unordered_map<PlyElemEntity, NameVector> ElementMap;
00162   typedef std::unordered_map<PlyElemEntity, NameVector>::iterator ElementMapIterator;
00163 
00164   static NameVector emptyVec;
00165 
00166   /* Names used for the PlyType */
00167   static TypeMap mapType({
00168       { PlyType::NNP_UNKNOWN_TYPE, NameVector({ "unknonw" }) },
00169       { PlyType::NNP_FLOAT32, NameVector({ "float", "float32" }) },
00170       { PlyType::NNP_FLOAT64, NameVector({ "double", "float64" }) },
00171       { PlyType::NNP_INT8, NameVector({ "char", "int8" }) },
00172       { PlyType::NNP_INT16, NameVector({ "short", "int16" }) },
00173       { PlyType::NNP_INT32, NameVector({ "int", "int32" }) },
00174       { PlyType::NNP_UINT8, NameVector({ "uchar", "uint8" }) },
00175       { PlyType::NNP_UINT16, NameVector({ "ushort", "uint16" }) },
00176       { PlyType::NNP_UINT32, NameVector({ "uint", "uint32" }) },
00177       { PlyType::NNP_LIST_UINT8_UINT32, NameVector({ "list uchar uint", "list uint8 uint32" }) },
00178       { PlyType::NNP_LIST_INT8_UINT32, NameVector({ "list char uint", "list int8 uint32" }) },
00179       { PlyType::NNP_LIST_UINT8_INT32, NameVector({ "list uchar int", "list uint8 int32" }) },
00180       { PlyType::NNP_LIST_INT8_INT32, NameVector({ "list char int", "list int8 int32" }) },
00181       { PlyType::NNP_LIST_UINT8_FLOAT32, NameVector({ "list uchar float", "list uint8 float32" }) },
00182       { PlyType::NNP_LIST_INT8_FLOAT32, NameVector({ "list char float", "list int8 float32" }) },
00183       { PlyType::NNP_LIST_UINT8_FLOAT64, NameVector({ "list uchar double", "list uint8 float64" }) },
00184       { PlyType::NNP_LIST_INT8_FLOAT64, NameVector({ "list char double", "list int8 float64" }) },
00185       { PlyType::NNP_LIST_UINT8_UINT8, NameVector({ "list uchar uchar", "list uint8 uint8" }) },
00186       { PlyType::NNP_LIST_INT8_UINT8, NameVector({ "list char uchar", "list int8 uint8" }) },
00187       { PlyType::NNP_LIST_UINT8_INT8, NameVector({ "list uchar char", "list uint8 int8" }) },
00188       { PlyType::NNP_LIST_INT8_INT8, NameVector({ "list char char", "list int8 int8" }) },
00189       { PlyType::NNP_LIST_UINT8_UINT16, NameVector({ "list uchar ushort", "list uint8 uint16" }) },
00190       { PlyType::NNP_LIST_INT8_UINT16, NameVector({ "list char ushort", "list int8 uint16" }) },
00191       { PlyType::NNP_LIST_UINT8_INT16, NameVector({ "list uchar short", "list uint8 int16" }) },
00192       { PlyType::NNP_LIST_INT8_INT16, NameVector({ "list char short", "list int8 int16" }) }
00193   });
00194 
00195 
00196   /* Names used for the PlyProperty */
00197   static EntityMap mapProp({
00198       { PlyEntity::NNP_UNKNOWN_ENTITY, NameVector({ "unknonw" }) },
00199       { PlyEntity::NNP_PX, NameVector({ "x", "px", "posx" }) },
00200       { PlyEntity::NNP_PY, NameVector({ "y", "py", "posy" }) },
00201       { PlyEntity::NNP_PZ, NameVector({ "z", "pz", "posz" }) },
00202       { PlyEntity::NNP_PXYZ, NameVector({ "x y z", "px py pz", "posx posy posz" }) },
00203       { PlyEntity::NNP_NX, NameVector({ "nx", "normalx" }) },
00204       { PlyEntity::NNP_NY, NameVector({ "ny", "normaly" }) },
00205       { PlyEntity::NNP_NZ, NameVector({ "nz", "normalz" }) },
00206       { PlyEntity::NNP_NXYZ, NameVector({ "nx ny nz", "normalx normaly normalz" }) },
00207       { PlyEntity::NNP_CR, NameVector({ "red", "diffuse_red", "r", "diffuse_r" }) },
00208       { PlyEntity::NNP_CG, NameVector({ "green", "diffuse_green", "g", "diffuse_g" }) },
00209       { PlyEntity::NNP_CB, NameVector({ "blue", "diffuse_blue", "b", "diffuse_b" }) },
00210       { PlyEntity::NNP_CA, NameVector({ "alpha", "diffuse_alpha", "a", "diffuse_a" }) },
00211       { PlyEntity::NNP_CRGB, NameVector({ "rgb", "diffuse_rgb" }) },
00212       { PlyEntity::NNP_CRGBA, NameVector({ "rgba", "diffuse_rgba" }) },
00213       { PlyEntity::NNP_DENSITY, NameVector({ "radius", "density" }) },
00214       { PlyEntity::NNP_SCALE, NameVector({ "scale", "value" }) },
00215       { PlyEntity::NNP_TEXTUREU, NameVector({ "texture_u", "u", "s" }) },
00216       { PlyEntity::NNP_TEXTUREV, NameVector({ "texture_v", "v", "t" }) },
00217       { PlyEntity::NNP_TEXTURE2D, NameVector({ "texture_uv", "uv" }) },
00218       { PlyEntity::NNP_TEXTUREW, NameVector({ "texture_w", "w" }) },
00219       { PlyEntity::NNP_TEXTURE3D, NameVector({ "texture_uvw", "uvw" }) },
00220       { PlyEntity::NNP_TEXTUREINDEX, NameVector({ "texnumber", "texid" }) },
00221       { PlyEntity::NNP_QUALITY, NameVector({ "quality", "confidence" }) },
00222       { PlyEntity::NNP_REFLECTANCE, NameVector({ "reflectance" }) },
00223       { PlyEntity::NNP_BITFLAG, NameVector({ "flags" }) },
00224       { PlyEntity::NNP_K1, NameVector({ "k1" }) },
00225       { PlyEntity::NNP_K2, NameVector({ "k2" }) },
00226       { PlyEntity::NNP_KG, NameVector({ "k" }) },
00227       { PlyEntity::NNP_KH, NameVector({ "h" }) },
00228       { PlyEntity::NNP_K1DIR, NameVector({ "k1dir" }) },
00229       { PlyEntity::NNP_K2DIR, NameVector({ "k2dir" }) },
00230       { PlyEntity::NNP_EDGE_V1, NameVector({ "vertex1", "v1" }) },
00231       { PlyEntity::NNP_EDGE_V2, NameVector({ "vertex2", "v2" }) },
00232       { PlyEntity::NNP_FACE_VERTEX_LIST, NameVector({ "vertex_index", "vertex_indices" }) },
00233       { PlyEntity::NNP_FACE_WEDGE_COLOR, NameVector({ "color" }) },
00234       { PlyEntity::NNP_FACE_WEDGE_NORMAL, NameVector({ "normal" }) },
00235       { PlyEntity::NNP_FACE_WEDGE_TEX, NameVector({ "texcoord" }) }
00236   });
00237 
00238 
00239   /* Names used for the PlyElement */
00240   static ElementMap mapElem({
00241       { PlyElemEntity::NNP_UNKNOWN_ELEM, NameVector({ "unknonw" }) },
00242       { PlyElemEntity::NNP_VERTEX_ELEM, NameVector({ "vertex" }) },
00243       { PlyElemEntity::NNP_EDGE_ELEM, NameVector({ "edge" }) },
00244       { PlyElemEntity::NNP_FACE_ELEM, NameVector({ "face" }) },
00245   });
00246 
00247 
00248   /* Returns the vector of possible name for the input PlyEntity */
00249   static const NameVector& PlyPropertyName(PlyEntity ent)
00250   {
00251     if (mapProp.find(ent) != mapProp.end())
00252       return    mapProp[ent];
00253     return  emptyVec;
00254   };
00255 
00256 
00257   /* Returns the vector of possible name for the input PlyType */
00258   static const NameVector& PlyTypeName(PlyType ent)
00259   {
00260     if (mapType.find(ent) != mapType.end())
00261       return    mapType[ent];
00262     return  emptyVec;
00263   };
00264 
00265 
00266   /* Returns the vector of possible name for the input PlyElement */
00267   static const NameVector& PlyElementName(PlyElemEntity ent)
00268   {
00269     if (mapElem.find(ent) != mapElem.end())
00270       return    mapElem[ent];
00271     return  emptyVec;
00272   };
00273 
00274 
00275   /* Return 1 for little endian, 0 for big endian*/
00276   int checkEndianness()
00277   {
00278     unsigned int x = 1;
00279     char *c = (char*)&x;
00280     return (int)*c;
00281   };
00282 
00283   /* Adjust the endianess of the input buffer*/
00284   void adjustEndianess(unsigned char* buffer, int typeSize, int count)
00285   {
00286     for (int i = 0; i < count; i++)
00287     {
00288       int offset = i*typeSize;
00289       for (int j = 0; j < typeSize / 2; j++)
00290       {
00291         unsigned char temp = buffer[offset + j];
00292         buffer[offset + j] = buffer[offset + typeSize - 1 - j];
00293         buffer[offset + typeSize - 1 - j] = temp;
00294       }
00295     }
00296   }
00306   class PlyFile
00307   {
00308   private:
00309     std::fstream fileStream;    
00310     char mode;                                  
00312     int64_t bufferSize;                 
00313     int64_t bufferOffset;               
00314     int64_t maxSize;                    
00315     char* buffer;                               
00317   public:
00318 
00319     PlyFile();
00320 
00321     ~PlyFile();
00322 
00329     bool OpenFileToRead(const std::string &filename);
00330 
00337     bool OpenFileToWrite(const std::string &filename);
00338 
00346     bool NextHeaderLine(std::string &line, bool &last);
00347 
00354     bool WriteHeaderLine(std::string &line);
00355 
00363     bool ReadBinaryData(void *dest, int nByte);
00364 
00371     template <typename T>
00372     bool ReadAsciiData(T &dest);
00373 
00381     bool WriteBinaryData(void *src, int nByte);
00382 
00389     template <typename T>
00390     bool WriteAsciiData(T &src);
00391 
00397     void SetBufferSize(int64_t size);
00398 
00402     void Flush();
00403   };
00404 
00405 
00406   PlyFile::PlyFile()
00407   {
00408     buffer = NULL;
00409     maxSize = 1000000;
00410     mode = -1;
00411   }
00412 
00413 
00414   PlyFile::~PlyFile()
00415   {
00416     Flush();
00417     if (buffer != NULL)
00418       delete[] buffer;
00419     if (fileStream.is_open())
00420       fileStream.close();
00421   }
00422 
00423 
00424   bool PlyFile::OpenFileToRead(const std::string& filename)
00425   {
00426     if (fileStream.is_open())
00427       fileStream.close();
00428     mode = 0;
00429     fileStream.open(filename, std::fstream::in | std::fstream::binary);
00430     if (fileStream.fail())
00431       return false;
00432     bufferOffset = 0;
00433     return true;
00434   }
00435 
00436 
00437   bool PlyFile::OpenFileToWrite(const std::string& filename)
00438   {
00439     if (fileStream.is_open())
00440       fileStream.close();
00441     mode = 1;
00442     fileStream.open(filename, std::fstream::out | std::fstream::binary);
00443     if (fileStream.fail())
00444       return false;
00445     bufferOffset = 0;
00446     //fileStream.setf(std::ios::fixed, std::ios::floatfield);
00447     //fileStream.precision(7);
00448     return true;
00449   }
00450 
00451 
00452   bool PlyFile::NextHeaderLine(std::string& line, bool& last)
00453   {
00454     if (mode != 0)
00455       return false;
00456     std::getline(fileStream, line);
00457     std::transform(line.begin(), line.end(), line.begin(), ::tolower);
00458     last = false;
00459     if (line == "end_header")
00460       last = true;
00461     return true;
00462   }
00463 
00464 
00465   bool PlyFile::WriteHeaderLine(std::string& line)
00466   {
00467     if (mode != 1)
00468       return false;
00469     fileStream << line;
00470     return true;
00471   }
00472 
00473 
00474   bool PlyFile::ReadBinaryData(void* dest, int nByte)
00475   {
00476     if (mode != 0)
00477       return false;
00478     if (buffer == NULL)
00479     {
00480       buffer = new char[maxSize];
00481       fileStream.read(buffer, maxSize);
00482       bufferSize = fileStream.gcount();
00483       bufferOffset = 0;
00484     }
00485     else if (bufferOffset + nByte > bufferSize)
00486     {
00487       unsigned int lastByte = bufferSize - bufferOffset;
00488       memcpy(buffer, &buffer[bufferOffset], lastByte);
00489       fileStream.read(&buffer[lastByte], maxSize - lastByte);
00490       bufferSize = fileStream.gcount() + lastByte;
00491       bufferOffset = 0;
00492     }
00493     memcpy(dest, &buffer[bufferOffset], nByte);
00494     bufferOffset += nByte;
00495     return true;
00496   }
00497 
00498 
00499   template <typename T>
00500   bool PlyFile::ReadAsciiData(T& dest)
00501   {
00502     if (mode != 0)
00503       return false;
00504     fileStream >> dest;
00505     return true;
00506   }
00507 
00508   bool PlyFile::WriteBinaryData(void* src, int nByte)
00509   {
00510     if (mode != 1)
00511       return false;
00512     if (buffer == NULL)
00513     {
00514       buffer = new char[maxSize];
00515       bufferSize = maxSize;
00516       bufferOffset = 0;
00517     }
00518     else if (bufferOffset + nByte > bufferSize)
00519     {
00520       fileStream.write(buffer, bufferOffset);
00521       bufferOffset = 0;
00522     }
00523     memcpy(&buffer[bufferOffset], src, nByte);
00524     bufferOffset += nByte;
00525     return true;
00526   }
00527 
00528 
00529   template <typename T>
00530   bool PlyFile::WriteAsciiData(T& src)
00531   {
00532     if (mode != 1)
00533       return false;
00534     fileStream << src;
00535     return true;
00536   }
00537 
00538   void PlyFile::SetBufferSize(int64_t size)
00539   {
00540     maxSize = size;
00541   }
00542 
00543 
00544   void PlyFile::Flush()
00545   {
00546     if (mode == 1)
00547       fileStream.write(buffer, bufferOffset);
00548   }
00549 
00550 
00551 
00552 
00556   class PlyProperty
00557   {
00558   public:
00559 
00560     std::string name;   
00561     PlyType type;               
00562     PlyEntity elem;             
00563     bool validToWrite;  
00571     PlyProperty(PlyType _t, PlyEntity _e) :type(_t), elem(_e), name(PlyPropertyName(_e)[0]), validToWrite(false){}
00572 
00580     PlyProperty(PlyType _t, PlyEntity _e, std::string _n) :type(_t), elem(_e), name(_n), validToWrite(false){}
00581 
00588     PlyProperty(PlyType _t, std::string _n) :type(_t), elem(PlyEntity::NNP_UNKNOWN_ENTITY), name(_n), validToWrite(false){}
00589 
00595     const char* EntityStr();
00596 
00602     const char* EntityName();
00603 
00609     const char* TypeStr();
00610 
00616     int TypeSize();
00617 
00623     int CountValue();
00624 
00630     bool IsSigned();
00631 
00638     bool SkipAsciiPropertyInFile(PlyFile &file);
00639 
00646     bool SkipBinaryPropertyInFile(PlyFile &file);
00647 
00654     bool WriteHeader(PlyFile &file);
00655   };
00656 
00657 
00658   const char* PlyProperty::EntityStr()
00659   {
00660     switch (this->elem)
00661     {
00662     case NNP_UNKNOWN_ENTITY:    return "NNP_UNKNOWN_ENTITY   ";
00663     case NNP_PX:    return "NNP_PX               ";
00664     case NNP_PY:    return "NNP_PY               ";
00665     case NNP_PZ:    return "NNP_PZ               ";
00666     case NNP_PXYZ:    return "NNP_PXYZ             ";
00667     case NNP_NX:    return "NNP_NX               ";
00668     case NNP_NY:    return "NNP_NY               ";
00669     case NNP_NZ:    return "NNP_NZ               ";
00670     case NNP_NXYZ:    return "NNP_NXYZ             ";
00671     case NNP_CR:    return "NNP_CR               ";
00672     case NNP_CG:    return "NNP_CG               ";
00673     case NNP_CB:    return "NNP_CB               ";
00674     case NNP_CRGB:    return "NNP_CRGB             ";
00675     case NNP_CA:    return "NNP_CA               ";
00676     case NNP_CRGBA:    return "NNP_CRGBA            ";
00677     case NNP_DENSITY:    return "NNP_DENSITY          ";
00678     case NNP_SCALE:    return "NNP_SCALE            ";
00679     case NNP_QUALITY:    return "NNP_QUALITY          ";
00680     case NNP_REFLECTANCE:    return "NNP_REFLECTANCE      ";
00681     case NNP_TEXTUREU:    return "NNP_TEXTUREU         ";
00682     case NNP_TEXTUREV:    return "NNP_TEXTUREV         ";
00683     case NNP_TEXTURE2D:    return "NNP_TEXTURE2D        ";
00684     case NNP_TEXTUREW:    return "NNP_TEXTUREW         ";
00685     case NNP_TEXTURE3D:    return "NNP_TEXTURE3D        ";
00686     case NNP_TEXTUREINDEX:    return "NNP_TEXTUREINDEX     ";
00687     case NNP_BITFLAG:    return "NNP_BITFLAG          ";
00688     case NNP_K1:    return "NNP_K1               ";
00689     case NNP_K2:    return "NNP_K2               ";
00690     case NNP_KG:    return "NNP_K                ";
00691     case NNP_KH:    return "NNP_H                ";
00692     case NNP_K1DIR:    return "NNP_K1DIR            ";
00693     case NNP_K2DIR:    return "NNP_K2DIR            ";
00694     case NNP_EDGE_V1:    return "NNP_EDGE_V1          ";
00695     case NNP_EDGE_V2:    return "NNP_EDGE_V2          ";
00696     case NNP_FACE_VERTEX_LIST:    return "NNP_FACE_VERTEX_LIST ";
00697     case NNP_FACE_WEDGE_COLOR:    return "NNP_FACE_WEDGE_COLOR ";
00698     case NNP_FACE_WEDGE_NORMAL:    return "NNP_FACE_WEDGE_NORMAL";
00699     case NNP_FACE_WEDGE_TEX:    return "NNP_FACE_WEDGE_TEX   ";
00700 
00701     default: assert(0);
00702       break;
00703     }
00704     return 0;
00705   }
00706 
00707 
00708   const char* PlyProperty::EntityName()
00709   {
00710 
00711     if (this->elem == PlyEntity::NNP_UNKNOWN_ENTITY)
00712       return (*this).name.c_str();
00713 #ifdef USE_NOSTANDARDPLY_OUTPUT
00714     if (this->elem == PlyEntity::NNP_SCALE)
00715       return PlyPropertyName(this->elem)[1].c_str();
00716     if (this->elem == PlyEntity::NNP_QUALITY)
00717       return PlyPropertyName(this->elem)[1].c_str();
00718     if (this->elem == PlyEntity::NNP_CR)
00719       return PlyPropertyName(this->elem)[1].c_str();
00720     if (this->elem == PlyEntity::NNP_CB)
00721       return PlyPropertyName(this->elem)[1].c_str();
00722     if (this->elem == PlyEntity::NNP_CG)
00723       return PlyPropertyName(this->elem)[1].c_str();
00724     if (this->elem == PlyEntity::NNP_CA)
00725       return PlyPropertyName(this->elem)[1].c_str();
00726 #endif
00727     const std::vector<std::string>& vect = PlyPropertyName(this->elem);
00728     if (vect.size() > 0)
00729       return vect[0].c_str();
00730     assert(0);
00731     return 0;
00732   }
00733 
00734 
00735   const char* PlyProperty::TypeStr()
00736   {
00737     switch (this->type)
00738     {
00739     case NNP_UNKNOWN_TYPE:    return "NNP_UNKNOWN_TYPE       ";
00740     case NNP_FLOAT32:    return "NNP_FLOAT32            ";
00741     case NNP_FLOAT64:    return "NNP_FLOAT64            ";
00742     case NNP_INT8:    return "NNP_INT8               ";
00743     case NNP_INT16:    return "NNP_INT16              ";
00744     case NNP_INT32:    return "NNP_INT32              ";
00745     case NNP_UINT8:    return "NNP_UINT8              ";
00746     case NNP_UINT16:    return "NNP_UINT16             ";
00747     case NNP_UINT32:    return "NNP_UINT32             ";
00748     case NNP_LIST_UINT8_UINT32:    return "NNP_LIST_UINT8_UINT32  ";
00749     case NNP_LIST_INT8_UINT32:    return "NNP_LIST_INT8_UINT32   ";
00750     case NNP_LIST_UINT8_INT32:    return "NNP_LIST_UINT8_INT32   ";
00751     case NNP_LIST_INT8_INT32:    return "NNP_LIST_INT8_INT32    ";
00752     case NNP_LIST_UINT8_FLOAT32:    return "NNP_LIST_UINT8_FLOAT32 ";
00753     case NNP_LIST_INT8_FLOAT32:    return "NNP_LIST_INT8_FLOAT32  ";
00754     case NNP_LIST_UINT8_FLOAT64:    return "NNP_LIST_UINT8_FLOAT64 ";
00755     case NNP_LIST_INT8_FLOAT64:    return "NNP_LIST_INT8_FLOAT64  ";
00756     case NNP_LIST_UINT8_UINT8:    return "NNP_LIST_UINT8_UINT8  ";
00757     case NNP_LIST_INT8_UINT8:    return "NNP_LIST_INT8_UINT8   ";
00758     case NNP_LIST_UINT8_INT8:    return "NNP_LIST_UINT8_INT8   ";
00759     case NNP_LIST_INT8_INT8:    return "NNP_LIST_INT8_INT8    ";
00760     case NNP_LIST_UINT8_UINT16:    return "NNP_LIST_UINT8_UINT16  ";
00761     case NNP_LIST_INT8_UINT16:    return "NNP_LIST_INT8_UINT16   ";
00762     case NNP_LIST_UINT8_INT16:    return "NNP_LIST_UINT8_INT16   ";
00763     case NNP_LIST_INT8_INT16:    return "NNP_LIST_INT8_INT16    ";
00764     default: assert(0);
00765       break;
00766     }
00767     return 0;
00768   }
00769 
00770 
00771   int PlyProperty::TypeSize()
00772   {
00773     switch (this->type)
00774     {
00775     case NNP_UNKNOWN_TYPE:
00776       return 0;
00777     case NNP_INT8:
00778     case NNP_UINT8:
00779       return sizeof(char);
00780     case NNP_INT16:
00781     case NNP_UINT16:
00782       return sizeof(short);
00783     case NNP_FLOAT32:
00784     case NNP_INT32:
00785     case NNP_UINT32:
00786       return sizeof(int);
00787     case NNP_FLOAT64:
00788       return sizeof(double);
00789     case NNP_LIST_UINT8_UINT32:
00790     case NNP_LIST_INT8_UINT32:
00791     case NNP_LIST_UINT8_INT32:
00792     case NNP_LIST_INT8_INT32:
00793       return sizeof(int);
00794     case NNP_LIST_UINT8_UINT16:
00795     case NNP_LIST_INT8_UINT16:
00796     case NNP_LIST_UINT8_INT16:
00797     case NNP_LIST_INT8_INT16:
00798       return sizeof(short);
00799     case NNP_LIST_UINT8_UINT8:
00800     case NNP_LIST_INT8_UINT8:
00801     case NNP_LIST_UINT8_INT8:
00802     case NNP_LIST_INT8_INT8:
00803       return sizeof(char);
00804     case NNP_LIST_UINT8_FLOAT32:
00805     case NNP_LIST_INT8_FLOAT32:
00806       return sizeof(float);
00807     case NNP_LIST_UINT8_FLOAT64:
00808     case NNP_LIST_INT8_FLOAT64:
00809       return sizeof(double);
00810     default: assert(0);
00811       break;
00812     }
00813     return 0;
00814   }
00815 
00816 
00817   bool PlyProperty::IsSigned()
00818   {
00819     switch (this->type)
00820     {
00821     case NNP_INT8:
00822     case NNP_INT16:
00823     case NNP_INT32:
00824     case NNP_FLOAT32:
00825     case NNP_FLOAT64:
00826     case NNP_LIST_INT8_UINT32:
00827     case NNP_LIST_INT8_INT32:
00828     case NNP_LIST_INT8_UINT16:
00829     case NNP_LIST_INT8_INT16:
00830     case NNP_LIST_INT8_UINT8:
00831     case NNP_LIST_INT8_INT8:
00832     case NNP_LIST_INT8_FLOAT32:
00833     case NNP_LIST_INT8_FLOAT64:
00834       return true;
00835     case NNP_UINT8:
00836     case NNP_UINT16:
00837     case NNP_UINT32:
00838     case NNP_LIST_UINT8_UINT32:
00839     case NNP_LIST_UINT8_INT32:
00840     case NNP_LIST_UINT8_UINT16:
00841     case NNP_LIST_UINT8_INT16:
00842     case NNP_LIST_UINT8_UINT8:
00843     case NNP_LIST_UINT8_INT8:
00844     case NNP_LIST_UINT8_FLOAT32:
00845     case NNP_LIST_UINT8_FLOAT64:
00846       return false;
00847     default:
00848       return false;
00849     }
00850   }
00851 
00852 
00853   int PlyProperty::CountValue()
00854   {
00855     if (this->elem == NNP_CRGB || this->elem == NNP_NXYZ || this->elem == NNP_PXYZ || this->elem == NNP_TEXTURE3D)
00856       return 3;
00857     else if (this->elem == NNP_CRGBA)
00858       return 4;
00859     else if (this->elem == NNP_TEXTURE2D)
00860       return 2;
00861     return 1;
00862   }
00863 
00864 
00865   bool PlyProperty::SkipAsciiPropertyInFile(PlyFile &file)
00866   {
00867     int count = CountValue();
00868     if (this->type >= NNP_LIST_UINT8_UINT32)
00869       file.ReadAsciiData(count);
00870     switch (type)
00871     {
00872     case NNP_INT8:
00873     case NNP_INT16:
00874     case NNP_INT32:
00875     case NNP_LIST_UINT8_INT32:
00876     case NNP_LIST_INT8_INT32:
00877     case NNP_LIST_UINT8_INT16:
00878     case NNP_LIST_INT8_INT16:
00879     case NNP_LIST_UINT8_INT8:
00880     case NNP_LIST_INT8_INT8:
00881     {
00882       int* temp = new int[count];
00883       for (int i = 0; i < count; i++)
00884         file.ReadAsciiData(temp[i]);
00885       delete[] temp;
00886       break;
00887     }
00888     case NNP_UINT8:
00889     case NNP_UINT16:
00890     case NNP_UINT32:
00891     case NNP_LIST_UINT8_UINT32:
00892     case NNP_LIST_INT8_UINT32:
00893     case NNP_LIST_UINT8_UINT16:
00894     case NNP_LIST_INT8_UINT16:
00895     case NNP_LIST_UINT8_UINT8:
00896     case NNP_LIST_INT8_UINT8:
00897     {
00898       unsigned int* temp = new unsigned int[count];
00899       for (int i = 0; i < count; i++)
00900         file.ReadAsciiData(temp[i]);
00901       delete[] temp;
00902       break;
00903     }
00904     case NNP_FLOAT32:
00905     case NNP_LIST_UINT8_FLOAT32:
00906     case NNP_LIST_INT8_FLOAT32:
00907     {
00908       float* temp = new float[count];
00909       for (int i = 0; i < count; i++)
00910         file.ReadAsciiData(temp[i]);
00911       delete[] temp;
00912       break;
00913     }
00914     case NNP_FLOAT64:
00915     case NNP_LIST_UINT8_FLOAT64:
00916     case NNP_LIST_INT8_FLOAT64:
00917     {
00918       double* temp = new double[count];
00919       for (int i = 0; i < count; i++)
00920         file.ReadAsciiData(temp[i]);
00921       delete[] temp;
00922       break;
00923     }
00924     }
00925     return true;
00926   }
00927 
00928 
00929   bool PlyProperty::SkipBinaryPropertyInFile(PlyFile& file)
00930   {
00931     unsigned char* temp;
00932     int count = CountValue();
00933     if (this->type >= NNP_LIST_UINT8_UINT32)
00934     {
00935       int size;
00936       if (this->IsSigned())
00937       {
00938         unsigned char cntList = 0;
00939         file.ReadBinaryData(&cntList, sizeof(char));
00940         size = this->TypeSize() * cntList;
00941       }
00942       else
00943       {
00944         char cntList = 0;
00945         file.ReadBinaryData(&cntList, sizeof(char));
00946         size = this->TypeSize() * cntList;
00947       }
00948       temp = new unsigned char[size];
00949       file.ReadBinaryData(temp, size);
00950     }
00951     else
00952     {
00953       int size = this->TypeSize()*count;
00954       temp = new unsigned char[size];
00955       file.ReadBinaryData(temp, size);
00956     }
00957     delete[] temp;
00958     return true;
00959   }
00960 
00961 
00962   bool PlyProperty::WriteHeader(PlyFile& file)
00963   {
00964     if (!validToWrite)
00965       return true;
00966     std::string name, type;
00967     type = PlyTypeName(this->type)[0];
00968     name = this->EntityName();
00969     std::vector<std::string> v;
00970     switch (this->elem)
00971     {
00972     case NNP_PXYZ:
00973     {
00974       v.push_back(PlyPropertyName(NNP_PX)[0]);
00975       v.push_back(PlyPropertyName(NNP_PY)[0]);
00976       v.push_back(PlyPropertyName(NNP_PZ)[0]);
00977       break;
00978     }
00979     case NNP_NXYZ:
00980     {
00981       v.push_back(PlyPropertyName(NNP_NX)[0]);
00982       v.push_back(PlyPropertyName(NNP_NY)[0]);
00983       v.push_back(PlyPropertyName(NNP_NZ)[0]);
00984       break;
00985     }
00986     case NNP_CRGB:
00987     {
00988       v.push_back(PlyPropertyName(NNP_CR)[0]);
00989       v.push_back(PlyPropertyName(NNP_CG)[0]);
00990       v.push_back(PlyPropertyName(NNP_CB)[0]);
00991       break;
00992     }
00993     case NNP_CRGBA:
00994     {
00995       v.push_back(PlyPropertyName(NNP_CR)[0]);
00996       v.push_back(PlyPropertyName(NNP_CG)[0]);
00997       v.push_back(PlyPropertyName(NNP_CB)[0]);
00998       v.push_back(PlyPropertyName(NNP_CA)[0]);
00999       break;
01000     }
01001     case NNP_TEXTURE2D:
01002     {
01003       v.push_back(PlyPropertyName(NNP_TEXTUREU)[0]);
01004       v.push_back(PlyPropertyName(NNP_TEXTUREV)[0]);
01005       break;
01006     }
01007     case NNP_TEXTURE3D:
01008     {
01009       v.push_back(PlyPropertyName(NNP_TEXTUREU)[0]);
01010       v.push_back(PlyPropertyName(NNP_TEXTUREV)[0]);
01011       v.push_back(PlyPropertyName(NNP_TEXTUREW)[0]);
01012       break;
01013     }
01014     default:
01015       v.push_back(name);
01016 
01017     }
01018     for (int i = 0; i < v.size(); i++)
01019     {
01020       std::stringstream s;
01021       s << "property " << type << " " << v[i] << "\n";
01022       if (!file.WriteHeaderLine(s.str()))
01023         return false;
01024     }
01025     return true;
01026   }
01027 
01028 
01029 
01030 
01034   class PlyElement
01035   {
01036   public:
01037 
01038     std::string name;                                   
01039     PlyElemEntity plyElem;                              
01040     size_t cnt;                                                 
01041     std::vector<PlyProperty> propVec;   
01042     bool validToWrite;                                  
01047     PlyElement() :validToWrite(false){};
01048 
01056     PlyElement(std::string& _name, std::vector<PlyProperty> &prop, size_t nElem) :name(_name), cnt(nElem), propVec(prop), plyElem(PlyElemEntity::NNP_UNKNOWN_ELEM), validToWrite(false){};
01057 
01065     PlyElement(PlyElemEntity ent, std::vector<PlyProperty> &prop, size_t nElem) :name(PlyElementName(ent)[0]), cnt(nElem), propVec(prop), plyElem(ent), validToWrite(false){};
01066 
01074     bool AddProperty(std::string &line);
01075 
01083     bool InitFromHeader(std::string &elemStr, std::vector<std::string> &propStr);
01084 
01091     bool WriteHeader(PlyFile &file);
01092 
01099     bool SkipAsciiElementsInFile(PlyFile &file);
01100 
01107     bool SkipBinaryElementsInFile(PlyFile &file);
01108 
01115     bool Contains(NNP_ENTITY entity);
01116   };
01117 
01118 
01119   bool PlyElement::InitFromHeader(std::string &elemStr, std::vector<std::string> &propStr)
01120   {
01121     char* token;
01122     char* tempStr = &elemStr[0];
01123     token = strtok(tempStr, " \t");
01124     if (strstr(token, "element") == NULL)
01125       return false;
01126     token = strtok(0, " \t\n");
01127     name = std::string(token);
01128     plyElem = PlyElemEntity::NNP_UNKNOWN_ELEM;
01129     ElementMapIterator iter = mapElem.begin();
01130     bool found = false;
01131     while (iter != mapElem.end())
01132     {
01133       NameVector& v = (*iter).second;
01134       for (size_t i = 0; i < v.size(); i++)
01135       {
01136         if (v[i] == name)
01137         {
01138           found = true;
01139           break;
01140         }
01141       }
01142       if (found)
01143       {
01144         plyElem = (*iter).first;
01145         break;
01146       }
01147       iter++;
01148     }
01149     token = strtok(0, " \t\n");
01150     cnt = atoi(token);
01151     for (size_t i = 0; i < propStr.size(); i++)
01152       if (!AddProperty(propStr[i]))
01153         return false;
01154     unsigned int mask = 0;
01155     for (size_t i = 0; i < propVec.size(); i++)
01156       mask |= propVec[i].elem;
01157     std::vector<PlyProperty> compactPropVec;
01158     for (size_t i = 0; i < propVec.size(); i++)
01159     {
01160       switch (propVec[i].elem)
01161       {
01162       case NNP_NX:
01163       case NNP_NY:
01164         if ((mask & NNP_NXYZ) != NNP_NXYZ)
01165           compactPropVec.push_back(propVec[i]);
01166         break;
01167       case NNP_NZ:
01168         if ((mask & NNP_NXYZ) != NNP_NXYZ)
01169           compactPropVec.push_back(propVec[i]);
01170         else
01171           compactPropVec.push_back(PlyProperty(propVec[i].type, NNP_NXYZ));
01172         break;
01173       case NNP_PX:
01174       case NNP_PY:
01175         if ((mask & NNP_PXYZ) != NNP_PXYZ)
01176           compactPropVec.push_back(propVec[i]);
01177         break;
01178       case NNP_PZ:
01179         if ((mask & NNP_PXYZ) != NNP_PXYZ)
01180           compactPropVec.push_back(propVec[i]);
01181         else
01182           compactPropVec.push_back(PlyProperty(propVec[i].type, NNP_PXYZ));
01183         break;
01184       case NNP_CR:
01185       case NNP_CG:
01186         if (((mask & NNP_CRGB) != NNP_CRGB) && ((mask & NNP_CRGBA) != NNP_CRGBA))
01187           compactPropVec.push_back(propVec[i]);
01188         break;
01189       case NNP_CB:
01190         if (((mask & NNP_CRGB) != NNP_CRGB) & ((mask & NNP_CRGBA) != NNP_CRGBA))
01191           compactPropVec.push_back(propVec[i]);
01192         else if (((mask & NNP_CRGB) == NNP_CRGB) & ((mask & NNP_CRGBA) != NNP_CRGBA))
01193           compactPropVec.push_back(PlyProperty(propVec[i].type, NNP_CRGB));
01194         break;
01195       case NNP_CA:
01196         if (((mask & NNP_CRGB) != NNP_CRGB) & ((mask & NNP_CRGBA) != NNP_CRGBA))
01197           compactPropVec.push_back(propVec[i]);
01198         else if ((mask & NNP_CRGBA) == NNP_CRGBA)
01199           compactPropVec.push_back(PlyProperty(propVec[i].type, NNP_CRGBA));
01200         break;
01201       case NNP_TEXTUREU:
01202         if (((mask & NNP_TEXTURE2D) != NNP_TEXTURE2D) & ((mask & NNP_TEXTURE3D) != NNP_TEXTURE3D))
01203           compactPropVec.push_back(propVec[i]);
01204         break;
01205       case NNP_TEXTUREV:
01206         if (((mask & NNP_TEXTURE2D) != NNP_TEXTURE2D) & ((mask & NNP_TEXTURE3D) != NNP_TEXTURE3D))
01207           compactPropVec.push_back(propVec[i]);
01208         else if (((mask & NNP_TEXTURE2D) == NNP_TEXTURE2D) & ((mask & NNP_TEXTURE3D) != NNP_TEXTURE3D))
01209           compactPropVec.push_back(PlyProperty(propVec[i].type, NNP_TEXTURE2D));
01210         break;
01211       case NNP_TEXTUREW:
01212         if (((mask & NNP_TEXTURE2D) != NNP_TEXTURE2D) & ((mask & NNP_TEXTURE3D) != NNP_TEXTURE3D))
01213           compactPropVec.push_back(propVec[i]);
01214         else if ((mask & NNP_TEXTURE3D) == NNP_TEXTURE3D)
01215           compactPropVec.push_back(PlyProperty(propVec[i].type, NNP_TEXTURE3D));
01216         break;
01217       default:
01218         compactPropVec.push_back(propVec[i]);
01219         break;
01220       }
01221     }
01222     propVec.clear();
01223     propVec = compactPropVec;
01224     return true;
01225   }
01226 
01227 
01228   bool PlyElement::WriteHeader(PlyFile &file)
01229   {
01230     if (!validToWrite || cnt == 0)
01231       return true;
01232     bool ok = true;
01233     std::stringstream temp;
01234     temp << "element " << name << " " << cnt << "\n";
01235     if (file.WriteHeaderLine(temp.str()))
01236     {
01237       for (int i = 0; i < propVec.size(); i++)
01238         ok = propVec[i].WriteHeader(file);
01239     }
01240     else
01241       return false;
01242     return ok;
01243   }
01244 
01245 
01246   bool PlyElement::SkipAsciiElementsInFile(PlyFile &file)
01247   {
01248     for (int i = 0; i < this->cnt; ++i)
01249       for (int j = 0; j < this->propVec.size(); ++j)
01250         this->propVec[j].SkipAsciiPropertyInFile(file);
01251     return true;
01252   }
01253 
01254 
01255   bool PlyElement::SkipBinaryElementsInFile(PlyFile &file)
01256   {
01257     for (int i = 0; i < this->cnt; ++i)
01258       for (int j = 0; j < this->propVec.size(); ++j)
01259         this->propVec[j].SkipBinaryPropertyInFile(file);
01260     return true;
01261   }
01262 
01263 
01264   bool PlyElement::AddProperty(std::string &line)
01265   {
01266     char* token;
01267     char* tempStr = &line[0];
01268     token = strtok(tempStr, " \t");
01269     if (strstr(token, "property") == NULL)
01270       return false;
01271     char* typeStr = strtok(0, " \t\n");
01272     char *ty1, *ty2;
01273     std::string type;
01274     type.append(typeStr);
01275     if (strcmp(typeStr, "list") == 0)
01276     {
01277       ty1 = strtok(0, " \t\n");
01278       ty2 = strtok(0, " \t\n");
01279       type.append(" ");
01280       type.append(ty1);
01281       type.append(" ");
01282       type.append(ty2);
01283     }
01284     PlyType plyType = PlyType::NNP_UNKNOWN_TYPE;
01285     TypeMapIterator iterType = mapType.begin();
01286     bool found = false;
01287     while (iterType != mapType.end())
01288     {
01289       NameVector& v = (*iterType).second;
01290       for (size_t i = 0; i < v.size(); i++)
01291       {
01292         if (v[i] == type)
01293         {
01294           found = true;
01295           break;
01296         }
01297       }
01298       if (found)
01299       {
01300         plyType = (*iterType).first;
01301         break;
01302       }
01303       iterType++;
01304     }
01305     if (plyType == PlyType::NNP_UNKNOWN_TYPE)
01306       return false;
01307     char* nameStr = strtok(0, " \t\n");
01308     PlyEntity plyEntity = PlyEntity::NNP_UNKNOWN_ENTITY;
01309     EntityMapIterator iterEnt = mapProp.begin();
01310     found = false;
01311     while (iterEnt != mapProp.end())
01312     {
01313       NameVector& v = (*iterEnt).second;
01314       for (size_t i = 0; i < v.size(); i++)
01315       {
01316         if (v[i] == nameStr)
01317         {
01318           found = true;
01319           break;
01320         }
01321       }
01322       if (found)
01323       {
01324         plyEntity = (*iterEnt).first;
01325         break;
01326       }
01327       iterEnt++;
01328     }
01329     if (plyEntity != PlyEntity::NNP_UNKNOWN_ENTITY)
01330       propVec.push_back(PlyProperty(plyType, plyEntity, nameStr));
01331     else
01332       propVec.push_back(PlyProperty(plyType, nameStr));
01333     return true;
01334   }
01335 
01336 
01337   bool PlyElement::Contains(PlyEntity entity)
01338   {
01339     for (int i = 0; i < propVec.size(); i++)
01340     {
01341       if (propVec[i].elem == entity)
01342         return true;
01343     }
01344     return false;
01345   }
01346 
01347 
01348 
01349 
01353   class Info
01354   {
01355 
01356   public:
01357     ErrorCode errInfo;                                          
01358     bool binary;                                                        
01359     std::vector<PlyElement> elemVec;            
01360     bool bigEndian;                                                     
01361     std::string filename;                                       
01362     std::vector<std::string> textureFile;       
01367     Info();
01368 
01374     Info(const std::string& filename);
01375 
01382     bool LoadHeader(const std::string& filename);
01383 
01390     bool WriteHeader(PlyFile& file);
01391 
01397     void AddPlyElement(PlyElement& pe);
01398 
01402     void Clear() { errInfo = NNP_OK; }
01403 
01410     size_t GetElementCount(std::string& name);
01411 
01418     size_t GetElementCount(PlyElemEntity e);
01419 
01425     size_t GetVertexCount();
01426 
01432     size_t GetFaceCount();
01433 
01439     size_t GetEdgeCount();
01440 
01447     PlyElement* GetElement(std::string& name);
01448 
01455     PlyElement* GetElement(PlyElemEntity e);
01456 
01462     PlyElement* GetVertexElement();
01463 
01469     PlyElement* GetFaceElement();
01470 
01476     PlyElement* GetEdgeElement();
01477 
01478   };
01479 
01480 
01481   Info::Info()
01482   {
01483     this->binary = true;
01484     this->bigEndian = true;
01485     this->Clear();
01486   }
01487 
01488 
01489   Info::Info(const std::string& filename)
01490   {
01491     this->LoadHeader(filename);
01492   }
01493 
01494 
01495   bool Info::LoadHeader(const std::string& filename)
01496   {
01497     this->filename = filename;
01498     this->errInfo = NNP_OK;
01499     std::ifstream input(filename, std::ios::binary);
01500     if (!input.good())
01501     {
01502       this->errInfo = NNP_UNABLE_TO_OPEN;
01503       input.close();
01504       return false;
01505     }
01506     std::string buffer;
01507     std::getline(input, buffer);
01508     std::transform(buffer.begin(), buffer.end(), buffer.begin(), ::tolower);
01509     if (buffer != "ply")
01510     {
01511       this->errInfo = NNP_MISSING_HEADER;
01512       input.close();
01513       return false;
01514     }
01515     std::getline(input, buffer);
01516     std::transform(buffer.begin(), buffer.end(), buffer.begin(), ::tolower);
01517     std::size_t pos = buffer.find("format");
01518     if (pos == std::string::npos)
01519     {
01520       this->errInfo = NNP_MISSING_FORMAT;
01521       input.close();
01522       return false;
01523     }
01524     if (buffer.find("binary_lit") != std::string::npos)
01525     {
01526       this->binary = true;
01527       this->bigEndian = false;
01528     }
01529     else if (buffer.find("binary_big") != std::string::npos)
01530     {
01531       this->binary = true;
01532       this->bigEndian = true;
01533     }
01534     else if (buffer.find("ascii") != std::string::npos)
01535     {
01536       this->binary = false;
01537       this->bigEndian = false;
01538     }
01539     else
01540     {
01541       this->errInfo = NNP_MISSING_FORMAT;
01542       return false;
01543     }
01544     std::getline(input, buffer);
01545     std::transform(buffer.begin(), buffer.end(), buffer.begin(), ::tolower);
01546     while (buffer != "end_header")
01547     {
01548       if (buffer.find("element") != std::string::npos)
01549       {
01550         std::string elemStr = buffer;
01551         std::vector<std::string> propStr;
01552         do
01553         {
01554           std::getline(input, buffer);
01555           std::transform(buffer.begin(), buffer.end(), buffer.begin(), ::tolower);
01556           pos = buffer.find("property");
01557           if (pos != std::string::npos)
01558             propStr.push_back(buffer);
01559         } while (pos != std::string::npos);
01560         PlyElement pe;
01561         if (!pe.InitFromHeader(elemStr, propStr))
01562         {
01563           this->errInfo = NNP_INVALID_ELEMENT;
01564           input.close();
01565           return false;
01566         }
01567         elemVec.push_back(pe);
01568       }
01569       else
01570       {
01571         if (buffer.find("comment TextureFile"))
01572           textureFile.push_back(buffer.substr(21));
01573         std::getline(input, buffer);
01574         std::transform(buffer.begin(), buffer.end(), buffer.begin(), ::tolower);
01575       }
01576     }
01577     input.close();
01578     return true;
01579   }
01580 
01581 
01582   bool Info::WriteHeader(PlyFile& file)
01583   {
01584     bool ok = true;
01585     ok = file.WriteHeaderLine(std::string("ply\n"));
01586     if (this->binary)
01587       ok = file.WriteHeaderLine(std::string("format binary_little_endian 1.0\n"));
01588     else
01589       ok = file.WriteHeaderLine(std::string("format ascii 1.0\n"));
01590     ok = file.WriteHeaderLine(std::string("comment nanoply generated\n"));
01591     for (int i = 0; i < this->textureFile.size(); i++)
01592       ok = file.WriteHeaderLine(std::string("comment TextureName ") + this->textureFile[i] + "\n");
01593     for (int i = 0; i < this->elemVec.size(); i++)
01594       ok = this->elemVec[i].WriteHeader(file);
01595     ok = file.WriteHeaderLine(std::string("end_header\n"));
01596     return ok;
01597   }
01598 
01599 
01600   void Info::AddPlyElement(PlyElement& pe)
01601   {
01602     elemVec.push_back(pe);
01603   }
01604 
01605 
01606   size_t Info::GetElementCount(std::string& name)
01607   {
01608     PlyElement* pe = GetElement(name);
01609     if (pe != NULL)
01610       return pe->cnt;
01611     return -1;
01612   }
01613 
01614 
01615   size_t Info::GetElementCount(PlyElemEntity e)
01616   {
01617     PlyElement* pe = GetElement(e);
01618     if (pe != NULL)
01619       return pe->cnt;
01620     return -1;
01621   }
01622 
01623 
01624   size_t Info::GetVertexCount()
01625   {
01626     return GetElementCount(PlyElemEntity::NNP_VERTEX_ELEM);
01627   }
01628 
01629 
01630   size_t Info::GetFaceCount()
01631   {
01632     return GetElementCount(PlyElemEntity::NNP_FACE_ELEM);
01633   }
01634 
01635 
01636   size_t Info::GetEdgeCount()
01637   {
01638     return GetElementCount(PlyElemEntity::NNP_EDGE_ELEM);
01639   }
01640 
01641 
01642   PlyElement* Info::GetElement(std::string& name)
01643   {
01644     for (int i = 0; i < elemVec.size(); i++)
01645     {
01646       if (elemVec[i].name == name)
01647         return &elemVec[i];
01648     }
01649     return NULL;
01650   }
01651 
01652 
01653   PlyElement* Info::GetElement(PlyElemEntity e)
01654   {
01655     for (int i = 0; i < elemVec.size(); i++)
01656     {
01657       if (elemVec[i].plyElem == e)
01658         return &elemVec[i];
01659     }
01660     return NULL;
01661   }
01662 
01663 
01664   PlyElement* Info::GetVertexElement()
01665   {
01666     return GetElement(PlyElemEntity::NNP_VERTEX_ELEM);
01667   }
01668 
01669 
01670   PlyElement* Info::GetFaceElement()
01671   {
01672     return GetElement(PlyElemEntity::NNP_FACE_ELEM);
01673   }
01674 
01675 
01676   PlyElement* Info::GetEdgeElement()
01677   {
01678     return GetElement(PlyElemEntity::NNP_EDGE_ELEM);
01679   }
01680 
01681 
01682 
01686   class DescriptorInterface
01687   {
01688 
01689   public:
01690 
01691     int64_t curPos;             
01693     void *base;                 
01695     PlyEntity elem;             
01697     std::string name;   
01705     DescriptorInterface(PlyEntity _e, void *_b) :curPos(0), elem(_e), base(_b), name(PlyPropertyName(_e)[0]){};
01706 
01713     DescriptorInterface(std::string& _s, void *_b) :curPos(0), elem(PlyEntity::NNP_UNKNOWN_ENTITY), name(_s), base(_b){};
01714 
01718     virtual void Restart() = 0;
01719 
01728     virtual bool ReadElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian) = 0;
01729 
01737     virtual bool ReadElemAscii(PlyFile &file, PlyProperty &prop) = 0;
01738 
01747     virtual bool WriteElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian) = 0;
01748 
01756     virtual bool WriteElemAscii(PlyFile &file, PlyProperty &prop) = 0;
01757   };
01758 
01759 
01760 
01764   class ElementDescriptor
01765   {
01766   public:
01767 
01768     typedef std::vector<nanoply::DescriptorInterface*> PropertyDescriptor;
01769 
01770     std::string name;                                   
01771     PlyElemEntity elem;                                 
01772     PropertyDescriptor dataDescriptor;  
01779     ElementDescriptor(PlyElemEntity _e) : elem(_e), name(PlyElementName(_e)[0]){};
01780 
01786     ElementDescriptor(std::string &_s) : elem(PlyElemEntity::NNP_UNKNOWN_ELEM), name(_s){};
01787 
01796     bool ReadElemBinary(PlyFile &file, PlyElement &elem, bool fixEndian);
01797 
01805     bool ReadElemAscii(PlyFile &file, PlyElement &elem);
01806 
01815     bool WriteElemBinary(PlyFile &file, PlyElement &elem, bool fixEndian);
01816 
01824     bool WriteElemAscii(PlyFile &file, PlyElement &elem);
01825 
01832     void CheckDescriptor(PlyElement &elem);
01833 
01834   private:
01835 
01836     void ExtractDescriptor(PropertyDescriptor &descr, PlyElement &elem);
01837 
01838   };
01839 
01840 
01841   void ElementDescriptor::ExtractDescriptor(PropertyDescriptor& descr, PlyElement &elem)
01842   {
01843     for (int j = 0; j < elem.propVec.size(); j++)
01844     {
01845       PlyProperty& prop = elem.propVec[j];
01846       int i = 0;
01847       for (; i < dataDescriptor.size(); i++)
01848       {
01849         if (dataDescriptor[i]->elem == prop.elem)
01850         {
01851           if (prop.elem != PlyEntity::NNP_UNKNOWN_ENTITY)
01852           {
01853             descr.push_back(dataDescriptor[i]);
01854             break;
01855           }
01856           else //if (dataDescriptor[i]->name == prop.name)
01857           {
01858             std::string name1(dataDescriptor[i]->name);
01859             std::string name2(prop.name);
01860             std::transform(name1.begin(), name1.end(), name1.begin(), ::tolower);
01861             std::transform(name2.begin(), name2.end(), name2.begin(), ::tolower);
01862             if (name1 == name2)
01863             {
01864               descr.push_back(dataDescriptor[i]);
01865               break;
01866             }
01867           }
01868         }
01869       }
01870       if (i == dataDescriptor.size())
01871         descr.push_back(NULL);
01872     }
01873   }
01874 
01875 
01876   bool ElementDescriptor::ReadElemBinary(PlyFile &file, PlyElement &elem, bool fixEndian)
01877   {
01878     PropertyDescriptor descr;
01879     ExtractDescriptor(descr, elem);
01880     for (int i = 0; i < elem.cnt; i++)
01881     {
01882       for (int j = 0; j < elem.propVec.size(); j++)
01883       {
01884         PlyProperty& prop = elem.propVec[j];
01885         if (descr[j] != NULL)
01886           (*descr[j]).ReadElemBinary(file, prop, fixEndian);
01887         else
01888           prop.SkipBinaryPropertyInFile(file);
01889       }
01890     }
01891     return true;
01892   }
01893 
01894 
01895   bool ElementDescriptor::ReadElemAscii(PlyFile &file, PlyElement &elem)
01896   {
01897     PropertyDescriptor descr;
01898     ExtractDescriptor(descr, elem);
01899     for (int i = 0; i < elem.cnt; i++)
01900     {
01901       for (int j = 0; j < elem.propVec.size(); j++)
01902       {
01903         PlyProperty& prop = elem.propVec[j];
01904         if (descr[j] != NULL)
01905           (*descr[j]).ReadElemAscii(file, prop);
01906         else
01907           prop.SkipAsciiPropertyInFile(file);
01908       }
01909     }
01910     return true;
01911   }
01912 
01913   bool ElementDescriptor::WriteElemBinary(PlyFile &file, PlyElement &elem, bool fixEndian)
01914   {
01915     PropertyDescriptor descr;
01916     ExtractDescriptor(descr, elem);
01917     for (int i = 0; i < elem.cnt; i++)
01918     {
01919       for (int j = 0; j < elem.propVec.size(); j++)
01920       {
01921         if (descr[j] != NULL)
01922           (*descr[j]).WriteElemBinary(file, elem.propVec[j], fixEndian);
01923       }
01924     }
01925     return true;
01926   }
01927 
01928   bool ElementDescriptor::WriteElemAscii(PlyFile &file, PlyElement &elem)
01929   {
01930     PropertyDescriptor descr;
01931     ExtractDescriptor(descr, elem);
01932     for (int i = 0; i < elem.cnt; i++)
01933     {
01934       bool first = true;
01935       for (int j = 0; j < elem.propVec.size(); j++)
01936       {
01937         if (descr[j] != NULL)
01938         {
01939           if (!first)
01940             file.WriteAsciiData(std::string(" "));
01941           else
01942             first = false;
01943           (*descr[j]).WriteElemAscii(file, elem.propVec[j]);
01944         }
01945       }
01946       file.WriteAsciiData(std::string("\n"));
01947     }
01948     return true;
01949   }
01950 
01951 
01952   void ElementDescriptor::CheckDescriptor(PlyElement &elem)
01953   {
01954     if (elem.propVec.size() == 0)
01955     {
01956       elem.validToWrite = false;
01957       return;
01958     }
01959     elem.validToWrite = true;
01960     PropertyDescriptor descr;
01961     ExtractDescriptor(descr, elem);
01962     for (int j = 0; j < elem.propVec.size(); j++)
01963     {
01964       if (descr[j] != NULL)
01965         elem.propVec[j].validToWrite = true;
01966     }
01967   }
01968 
01969 
01970 
01978   template<class CointainerType, int VectorSize, typename ScalarType>
01979   class DataDescriptor : public DescriptorInterface
01980   {
01981   public:
01982 
01983     DataDescriptor();
01984 
01991     DataDescriptor(PlyEntity _e, void *_b) :DescriptorInterface(_e, _b){};
01992 
01999     DataDescriptor(std::string& _s, void *_b) :DescriptorInterface(_s, _b){};
02000 
02001     void Restart();
02002 
02003     bool ReadElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian);
02004 
02005     bool ReadElemAscii(PlyFile &file, PlyProperty &prop);
02006 
02007     bool WriteElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian);
02008 
02009     bool WriteElemAscii(PlyFile &file, PlyProperty &prop);
02010 
02011   private:
02012 
02013     template<typename C>
02014     void ReadBinary(PlyFile &file, PlyProperty &prop, bool fixEndian);
02015 
02016     template<typename C>
02017     void ReadAscii(PlyFile &file, PlyProperty &prop);
02018 
02019     template<typename C>
02020     void WriteBinary(PlyFile &file, PlyProperty &prop, bool fixEndian);
02021 
02022     template<typename C>
02023     void WriteAscii(PlyFile &file, PlyProperty &prop);
02024 
02025   };
02026 
02027 
02028   template<class CointainerType, int VectorSize, typename ScalarType>
02029   void DataDescriptor<CointainerType, VectorSize, ScalarType>::Restart()
02030   {
02031     this->curPos = 0;
02032   }
02033 
02034   template<class ContainerType, int VectorSize, typename ScalarType>
02035   template<typename C>
02036   void DataDescriptor<ContainerType, VectorSize, ScalarType>::ReadBinary(PlyFile &file, PlyProperty &prop, bool fixEndian)
02037   {
02038     unsigned char* buffer;
02039     int size;
02040     int count = prop.CountValue();
02041     int typeSize = prop.TypeSize();
02042     if (prop.type >= NNP_LIST_UINT8_UINT32)
02043     {
02044       if (prop.IsSigned())
02045       {
02046         char cntList = 0;
02047         file.ReadBinaryData(&cntList, sizeof(char));
02048         size = typeSize * cntList;
02049         count = cntList;
02050       }
02051       else
02052       {
02053         unsigned char cntList = 0;
02054         file.ReadBinaryData(&cntList, sizeof(char));
02055         size = typeSize * cntList;
02056         count = cntList;
02057       }
02058     }
02059     else
02060       size = typeSize * count;
02061     buffer = new unsigned char[size];
02062     file.ReadBinaryData(buffer, size);
02063 
02064     if (typeSize > 1 && fixEndian)
02065       adjustEndianess(buffer, typeSize, count);
02066 
02067     C* temp = (C*)buffer;
02068     float norm = 1.0f;
02069     if ((prop.elem == NNP_CRGB || prop.elem == NNP_CRGBA))
02070     {
02071       if (std::is_same<ScalarType, float>::value && std::is_same<C, unsigned char>::value)
02072         norm = 1.0f / 255.0f;
02073       else if (std::is_same<ScalarType, unsigned char>::value && std::is_same<C, float>::value)
02074         norm = 255.0f;
02075     }
02076     unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType);
02077     for (int i = 0; i < std::min(VectorSize, count); i++)
02078       *(ScalarType *)(baseProp + i*sizeof(ScalarType)) = ScalarType(temp[i] * norm);
02079     ++(this->curPos);
02080     delete[] buffer;
02081   }
02082 
02083 
02084   template<class ContainerType, int VectorSize, typename ScalarType>
02085   bool DataDescriptor<ContainerType, VectorSize, ScalarType>::ReadElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian)
02086   {
02087     if (prop.elem != elem)
02088       return false;
02089     switch (prop.type)
02090     {
02091     case NNP_LIST_INT8_INT8:
02092     case NNP_LIST_UINT8_INT8:
02093     case NNP_INT8:                              this->ReadBinary<char>(file, prop, fixEndian); break;
02094     case NNP_LIST_INT8_UINT8:
02095     case NNP_LIST_UINT8_UINT8:
02096     case NNP_UINT8:                             this->ReadBinary<unsigned char>(file, prop, fixEndian); break;
02097     case NNP_LIST_INT8_INT16:
02098     case NNP_LIST_UINT8_INT16:
02099     case NNP_INT16:                             this->ReadBinary<short>(file, prop, fixEndian); break;
02100     case NNP_LIST_INT8_UINT16:
02101     case NNP_LIST_UINT8_UINT16:
02102     case NNP_UINT16:                    this->ReadBinary<unsigned short>(file, prop, fixEndian); break;
02103     case NNP_LIST_INT8_FLOAT32:
02104     case NNP_LIST_UINT8_FLOAT32:
02105     case NNP_FLOAT32:                   this->ReadBinary<float>(file, prop, fixEndian); break;
02106     case NNP_LIST_UINT8_INT32:
02107     case NNP_LIST_INT8_INT32:
02108     case NNP_INT32:                             this->ReadBinary<int>(file, prop, fixEndian); break;
02109     case NNP_LIST_UINT8_UINT32:
02110     case NNP_LIST_INT8_UINT32:
02111     case NNP_UINT32:                    this->ReadBinary<unsigned int>(file, prop, fixEndian); break;
02112     case NNP_LIST_INT8_FLOAT64:
02113     case NNP_LIST_UINT8_FLOAT64:
02114     case NNP_FLOAT64:                   this->ReadBinary<double>(file, prop, fixEndian); break;
02115     }
02116     return true;
02117   }
02118 
02119 
02120 
02121   template<class ContainerType, int VectorSize, typename ScalarType>
02122   template<typename C>
02123   void DataDescriptor<ContainerType, VectorSize, ScalarType>::ReadAscii(PlyFile &file, PlyProperty &prop)
02124   {
02125     int count = prop.CountValue();
02126     if (prop.type >= NNP_LIST_UINT8_UINT32)
02127       file.ReadAsciiData(count);
02128 
02129     C* temp = new C[count];
02130     for (int i = 0; i < count; i++)
02131       file.ReadAsciiData(temp[i]);
02132 
02133     float norm = 1.0f;
02134     if ((prop.elem == NNP_CRGB || prop.elem == NNP_CRGBA))
02135     {
02136       if (std::is_same<ScalarType, float>::value && prop.type == NNP_UINT8)
02137         norm = 1.0f / 255.0f;
02138       else if (std::is_same<ScalarType, unsigned char>::value && prop.type == NNP_FLOAT32)
02139         norm = 255.0f;
02140     }
02141     unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType);
02142     for (int i = 0; i < std::min(VectorSize, count); i++)
02143       *(ScalarType *)(baseProp + i*sizeof(ScalarType)) = ScalarType(temp[i] * norm);
02144 
02145     delete[] temp;
02146     ++(this->curPos);
02147   }
02148 
02149 
02150 
02151   template<class ContainerType, int VectorSize, typename ScalarType>
02152   bool DataDescriptor<ContainerType, VectorSize, ScalarType>::ReadElemAscii(PlyFile &file, PlyProperty &prop)
02153   {
02154     if (prop.elem != elem)
02155       return false;
02156     switch (prop.type)
02157     {
02158     case NNP_LIST_UINT8_INT8:
02159     case NNP_LIST_INT8_INT8:
02160     case NNP_INT8:                              this->ReadAscii<int>(file, prop); break;
02161     case NNP_LIST_UINT8_UINT8:
02162     case NNP_LIST_INT8_UINT8:
02163     case NNP_UINT8:                             this->ReadAscii<unsigned int>(file, prop); break;
02164     case NNP_LIST_UINT8_INT16:
02165     case NNP_LIST_INT8_INT16:
02166     case NNP_INT16:                             this->ReadAscii<short>(file, prop); break;
02167     case NNP_LIST_UINT8_UINT16:
02168     case NNP_LIST_INT8_UINT16:
02169     case NNP_UINT16:                    this->ReadAscii<unsigned short>(file, prop); break;
02170     case NNP_LIST_UINT8_FLOAT32:
02171     case NNP_LIST_INT8_FLOAT32:
02172     case NNP_FLOAT32:                   this->ReadAscii<float>(file, prop); break;
02173     case NNP_LIST_UINT8_INT32:
02174     case NNP_LIST_INT8_INT32:
02175     case NNP_INT32:                             this->ReadAscii<int>(file, prop); break;
02176     case NNP_LIST_UINT8_UINT32:
02177     case NNP_LIST_INT8_UINT32:
02178     case NNP_UINT32:                    this->ReadAscii<unsigned int>(file, prop); break;
02179     case NNP_LIST_UINT8_FLOAT64:
02180     case NNP_LIST_INT8_FLOAT64:
02181     case NNP_FLOAT64:                   this->ReadAscii<double>(file, prop); break;
02182     }
02183     return true;
02184   }
02185 
02186 
02187 
02188   template<class ContainerType, int VectorSize, typename ScalarType>
02189   template<typename C>
02190   void DataDescriptor<ContainerType, VectorSize, ScalarType>::WriteBinary(PlyFile &file, PlyProperty &prop, bool fixEndian)
02191   {
02192     int count = prop.CountValue();
02193     C data[VectorSize];
02194     if (prop.type >= NNP_LIST_UINT8_UINT32)
02195     {
02196       if (prop.IsSigned())
02197       {
02198         char listSize = (char)VectorSize;
02199         file.WriteBinaryData(&listSize, 1);
02200         count = VectorSize;
02201       }
02202       else
02203       {
02204         unsigned char listSize = (unsigned char)VectorSize;
02205         file.WriteBinaryData(&listSize, 1);
02206         count = VectorSize;
02207       }
02208     }
02209 
02210     float norm = 1.0f;
02211     if ((prop.elem == NNP_CRGB || prop.elem == NNP_CRGBA))
02212     {
02213       if (std::is_same<ScalarType, float>::value && std::is_same<C, unsigned char>::value)
02214         norm = 255.0f;
02215       else if (std::is_same<ScalarType, unsigned char>::value && std::is_same<C, float>::value)
02216         norm = 1.0f / 255.0f;
02217     }
02218 
02219     C temp = 0;
02220     unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType);
02221     for (int i = 0; i < std::min(VectorSize, count); i++)
02222       data[i] = (C)((*(ScalarType*)(baseProp + i*sizeof(ScalarType))) * norm);
02223     if (sizeof(C) > 1 && fixEndian)
02224       adjustEndianess((unsigned char*)data, sizeof(C), std::min(VectorSize, count));
02225 
02226     file.WriteBinaryData(data, sizeof(C)*std::min(VectorSize, count));
02227     for (int i = 0; i < (count - VectorSize); i++)
02228       file.WriteBinaryData(&temp, sizeof(C));
02229     ++(this->curPos);
02230   }
02231 
02232 
02233   template<class ContainerType, int VectorSize, typename ScalarType>
02234   bool DataDescriptor<ContainerType, VectorSize, ScalarType>::WriteElemBinary(PlyFile &file, PlyProperty &prop, bool fixEndian)
02235   {
02236     if (prop.elem != elem)
02237       return false;
02238     switch (prop.type)
02239     {
02240     case NNP_LIST_INT8_INT8:
02241     case NNP_LIST_UINT8_INT8:
02242     case NNP_INT8:                              this->WriteBinary<char>(file, prop, fixEndian); break;
02243     case NNP_LIST_INT8_UINT8:
02244     case NNP_LIST_UINT8_UINT8:
02245     case NNP_UINT8:                             this->WriteBinary<unsigned char>(file, prop, fixEndian); break;
02246     case NNP_LIST_INT8_INT16:
02247     case NNP_LIST_UINT8_INT16:
02248     case NNP_INT16:                             this->WriteBinary<short>(file, prop, fixEndian); break;
02249     case NNP_LIST_INT8_UINT16:
02250     case NNP_LIST_UINT8_UINT16:
02251     case NNP_UINT16:                    this->WriteBinary<unsigned short>(file, prop, fixEndian); break;
02252     case NNP_LIST_INT8_FLOAT32:
02253     case NNP_LIST_UINT8_FLOAT32:
02254     case NNP_FLOAT32:                   this->WriteBinary<float>(file, prop, fixEndian); break;
02255     case NNP_LIST_UINT8_INT32:
02256     case NNP_LIST_INT8_INT32:
02257     case NNP_INT32:                             this->WriteBinary<int>(file, prop, fixEndian); break;
02258     case NNP_LIST_UINT8_UINT32:
02259     case NNP_LIST_INT8_UINT32:
02260     case NNP_UINT32:                    this->WriteBinary<unsigned int>(file, prop, fixEndian); break;
02261     case NNP_LIST_INT8_FLOAT64:
02262     case NNP_LIST_UINT8_FLOAT64:
02263     case NNP_FLOAT64:                   this->WriteBinary<double>(file, prop, fixEndian); break;
02264     }
02265     return true;
02266   }
02267 
02268 
02269   template<class ContainerType, int VectorSize, typename ScalarType>
02270   template<typename C>
02271   void DataDescriptor<ContainerType, VectorSize, ScalarType>::WriteAscii(PlyFile &file, PlyProperty &prop)
02272   {
02273     int count = prop.CountValue();
02274     if (prop.type >= NNP_LIST_UINT8_UINT32)
02275     {
02276       if (prop.IsSigned())
02277       {
02278         int listSize = (int)VectorSize;
02279         file.WriteAsciiData(listSize);
02280         count = VectorSize;
02281       }
02282       else
02283       {
02284         unsigned int listSize = (unsigned int)VectorSize;
02285         file.WriteAsciiData(listSize);
02286         count = VectorSize;
02287       }
02288       file.WriteAsciiData(std::string(" "));
02289     }
02290 
02291     float norm = 1.0;
02292     if ((prop.elem == NNP_CRGB || prop.elem == NNP_CRGBA))
02293     {
02294       if (std::is_same<ScalarType, float>::value && prop.type == NNP_UINT8)
02295         norm = 255.0f;
02296       else if (std::is_same<ScalarType, unsigned char>::value && prop.type == NNP_FLOAT32)
02297         norm = 1.0f / 255.0f;
02298     }
02299 
02300     C data[VectorSize];
02301     unsigned char* baseProp = (unsigned char*)base + this->curPos*sizeof(ContainerType);
02302     for (int i = 0; i < std::min(VectorSize, count); i++)
02303       data[i] = (C)((*(ScalarType*)(baseProp + i*sizeof(ScalarType))) * norm);
02304     for (int i = 0; i < (count - VectorSize); i++)
02305       data[i] = 0;
02306 
02307     for (int i = 0; i < count; i++)
02308     {
02309       file.WriteAsciiData(data[i]);
02310       if (i < count - 1)
02311         file.WriteAsciiData(std::string(" "));
02312     }
02313     ++(this->curPos);
02314   }
02315 
02316 
02317   template<class ContainerType, int VectorSize, typename ScalarType>
02318   bool DataDescriptor<ContainerType, VectorSize, ScalarType>::WriteElemAscii(PlyFile &file, PlyProperty& prop)
02319   {
02320     if (prop.elem != elem)
02321       return false;
02322     if (prop.elem == PlyEntity::NNP_UNKNOWN_ENTITY && prop.name != name)
02323       return false;
02324     switch (prop.type)
02325     {
02326     case NNP_LIST_UINT8_INT8:
02327     case NNP_LIST_INT8_INT8:
02328     case NNP_INT8:                              this->WriteAscii<int>(file, prop); break;
02329     case NNP_LIST_UINT8_UINT8:
02330     case NNP_LIST_INT8_UINT8:
02331     case NNP_UINT8:                             this->WriteAscii<unsigned int>(file, prop); break;
02332     case NNP_LIST_UINT8_INT16:
02333     case NNP_LIST_INT8_INT16:
02334     case NNP_INT16:                             this->WriteAscii<short>(file, prop); break;
02335     case NNP_LIST_UINT8_UINT16:
02336     case NNP_LIST_INT8_UINT16:
02337     case NNP_UINT16:                    this->WriteAscii<unsigned short>(file, prop); break;
02338     case NNP_LIST_UINT8_FLOAT32:
02339     case NNP_LIST_INT8_FLOAT32:
02340     case NNP_FLOAT32:                   this->WriteAscii<float>(file, prop); break;
02341     case NNP_LIST_UINT8_INT32:
02342     case NNP_LIST_INT8_INT32:
02343     case NNP_INT32:                             this->WriteAscii<int>(file, prop); break;
02344     case NNP_LIST_UINT8_UINT32:
02345     case NNP_LIST_INT8_UINT32:
02346     case NNP_UINT32:                    this->WriteAscii<unsigned int>(file, prop); break;
02347     case NNP_LIST_UINT8_FLOAT64:
02348     case NNP_LIST_INT8_FLOAT64:
02349     case NNP_FLOAT64:                   this->WriteAscii<double>(file, prop); break;
02350     }
02351     return true;
02352   }
02353 
02354 
02355 
02356   template <size_t ActionType>
02357   inline bool ElemProcessing(ElementDescriptor& elemDescr, PlyElement &elem, PlyFile& file, bool fixEndian)
02358   {
02359     if ((elemDescr.elem != PlyElemEntity::NNP_UNKNOWN_ELEM && elemDescr.elem == elem.plyElem) ||
02360       (elemDescr.elem == PlyElemEntity::NNP_UNKNOWN_ELEM && elemDescr.name == elem.name))
02361     {
02362       if (ActionType == 0)
02363         elemDescr.ReadElemBinary(file, elem, fixEndian);
02364       else if (ActionType == 1)
02365         elemDescr.ReadElemAscii(file, elem);
02366       else if (ActionType == 2)
02367         elemDescr.WriteElemBinary(file, elem, fixEndian);
02368       else if (ActionType == 3)
02369         elemDescr.WriteElemAscii(file, elem);
02370       else if (ActionType == 4)
02371         elemDescr.CheckDescriptor(elem);
02372       return true;
02373     }
02374     return false;
02375   }
02376 
02377   typedef std::vector<ElementDescriptor*> MeshDescriptor;
02378 
02385   bool OpenModel(Info& info, MeshDescriptor& meshElements)
02386   {
02387     PlyFile file;
02388     if (!file.OpenFileToRead(info.filename))
02389     {
02390       info.errInfo = NNP_UNABLE_TO_OPEN;
02391       return false;
02392     }
02393     bool last;
02394     std::string line;
02395     do
02396     {
02397       file.NextHeaderLine(line, last);
02398     } while (!last);
02399     bool fixEndian = false;
02400     if (checkEndianness() == 1)
02401     {
02402       if (info.bigEndian)
02403         fixEndian = true;
02404     }
02405     else
02406     {
02407       if (!info.bigEndian)
02408         fixEndian = true;
02409     }
02410 
02411     if (info.binary)
02412     {
02413       for (int i = 0; i < info.elemVec.size(); ++i)
02414       {
02415         PlyElement& pe = info.elemVec[i];
02416         int j = 0;
02417         for (; j < meshElements.size(); j++)
02418           if (ElemProcessing<0>(*meshElements[j], pe, file, false))
02419             break;
02420         if (j == meshElements.size())
02421           pe.SkipBinaryElementsInFile(file);
02422         //if (!TupleForEach(meshElements, pe, file, fixEndian, SizeT<0>()))
02423         //      pe.SkipBinaryElementsInFile(file);
02424       }
02425     }
02426     else
02427     {
02428       for (int i = 0; i < info.elemVec.size(); ++i)
02429       {
02430         PlyElement& pe = info.elemVec[i];
02431         int j = 0;
02432         for (; j < meshElements.size(); j++)
02433           if (ElemProcessing<1>(*meshElements[j], pe, file, false))
02434             break;
02435         if (j == meshElements.size())
02436           pe.SkipAsciiElementsInFile(file);
02437         //if (!TupleForEach(meshElements, pe, file, fixEndian, SizeT<1>()))
02438         //      pe.SkipAsciiElementsInFile(file);
02439       }
02440     }
02441     return true;
02442   }
02443 
02444 
02445 
02453   bool SaveModel(std::string& filename, MeshDescriptor& meshElements, Info& info)
02454   {
02455     PlyFile file;
02456     if (!file.OpenFileToWrite(filename))
02457     {
02458       info.errInfo = NNP_UNABLE_TO_OPEN;
02459       return false;
02460     }
02461     for (int i = 0; i < info.elemVec.size(); ++i)
02462     {
02463       PlyElement& pe = info.elemVec[i];
02464       for (int j = 0; j < meshElements.size(); j++)
02465         if (ElemProcessing<4>(*meshElements[j], pe, file, false))
02466           break;
02467     }
02468     info.WriteHeader(file);
02469     bool fixEndian = false;
02470     if (checkEndianness() == 1)
02471     {
02472       if (info.bigEndian)
02473         fixEndian = true;
02474     }
02475     else
02476     {
02477       if (!info.bigEndian)
02478         fixEndian = true;
02479     }
02480 
02481     if (info.binary)
02482     {
02483       for (int i = 0; i < info.elemVec.size(); ++i)
02484       {
02485         PlyElement& pe = info.elemVec[i];
02486         if (pe.validToWrite)
02487         {
02488           for (int j = 0; j < meshElements.size(); j++)
02489             if (ElemProcessing<2>(*meshElements[j], pe, file, false))
02490               break;
02491         }
02492       }
02493     }
02494     else
02495     {
02496       for (int i = 0; i < info.elemVec.size(); ++i)
02497       {
02498         PlyElement& pe = info.elemVec[i];
02499         if (pe.validToWrite)
02500         {
02501           for (int j = 0; j < meshElements.size(); j++)
02502             if (ElemProcessing<3>(*meshElements[j], pe, file, false))
02503               break;
02504         }
02505       }
02506     }
02507     file.Flush();
02508     return true;
02509   }
02510 
02511 
02512 
02516   template < typename TupleType, size_t ActionType>
02517   inline bool TupleForEach(TupleType &tuple, PlyElement &elem, PlyFile& file, bool fixEndian, SizeT<ActionType> a)
02518   {
02519     return TupleForEach(tuple, elem, file, fixEndian, SizeT<std::tuple_size<TupleType>::value>(), a);
02520   }
02521 
02522   template < typename TupleType, size_t ActionType>
02523   inline bool TupleForEach(TupleType &tuple, PlyElement &elem, PlyFile& file, bool fixEndian, SizeT<0> t, SizeT<ActionType> a) { return false; }
02524 
02525   template < typename TupleType, size_t N, size_t ActionType>
02526   inline bool TupleForEach(TupleType &tuple, PlyElement &elem, PlyFile& file, bool fixEndian, SizeT<N> t, SizeT<ActionType> a)
02527   {
02528     typename std::tuple_element<N - 1, TupleType>::type &elemDescr = std::get<N - 1>(tuple);
02529     if ((elemDescr.elem != PlyElemEntity::NNP_UNKNOWN_ELEM && elemDescr.elem == elem.plyElem) ||
02530       (elemDescr.elem == PlyElemEntity::NNP_UNKNOWN_ELEM && elemDescr.name == elem.name))
02531     {
02532       if (ActionType == 0)
02533         elemDescr.ReadElemBinary(file, elem, fixEndian);
02534       else if (ActionType == 1)
02535         elemDescr.ReadElemAscii(file, elem);
02536       else if (ActionType == 2)
02537         elemDescr.WriteElemBinary(file, elem, fixEndian);
02538       else if (ActionType == 3)
02539         elemDescr.WriteElemAscii(file, elem);
02540       else if (ActionType == 4)
02541         elemDescr.CheckDescriptor(elem);
02542       return true;
02543     }
02544     return TupleForEach(tuple, elem, file, fixEndian, SizeT<N - 1>(), a);
02545   }
02550 } // end namespace nanoply
02551 #endif // NANOPLY_HPP


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:33:23