import_stl.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2004                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
00021 *                                                                           *
00022 ****************************************************************************/
00023 
00024 #ifndef __VCGLIB_IMPORT_STL
00025 #define __VCGLIB_IMPORT_STL
00026 #include <stdio.h>
00027 #include <wrap/io_trimesh/io_mask.h>
00028 
00029 namespace vcg {
00030 namespace tri {
00031 namespace io {
00032 
00038 template <class OpenMeshType>
00039 class ImporterSTL
00040 {
00041 public:
00042 
00043 typedef typename OpenMeshType::VertexPointer VertexPointer;
00044 typedef typename OpenMeshType::ScalarType ScalarType;
00045 typedef typename OpenMeshType::VertexType VertexType;
00046 typedef typename OpenMeshType::FaceType FaceType;
00047 typedef typename OpenMeshType::VertexIterator VertexIterator;
00048 typedef typename OpenMeshType::FaceIterator FaceIterator;
00049 
00050 // if it is binary there are 80 char of comment, the number fn of faces and then exactly fn*4*3 bytes.
00051 
00052 enum {STL_LABEL_SIZE=80};
00053 
00054 class STLFacet
00055 {
00056 public:
00057   Point3f n;
00058   Point3f v[3];
00059 //  short attr;
00060 };
00061 
00062 enum STLError {
00063     E_NOERROR,                          // 0
00064         // Errori di open
00065     E_CANTOPEN,                         // 1
00066     E_UNESPECTEDEOF                             // 2
00067 };
00068 
00069 static const char *ErrorMsg(int error)
00070 {
00071   static const char * stl_error_msg[] =
00072   {
00073     "No errors",
00074     "Can't open file",
00075     "Premature End of file",
00076     };
00077 
00078   if(error>2 || error<0) return "Unknown error";
00079   else return stl_error_msg[error];
00080 };
00081 
00082 static bool LoadMask(const char * filename, int &mask)
00083 {
00084   bool magicMode;
00085   mask = Mask::IOM_VERTCOORD | Mask::IOM_FACEINDEX;
00086   if(IsSTLColored(filename,magicMode))
00087     mask |= Mask::IOM_FACECOLOR;
00088   return true;
00089 }
00090 
00091 /* Try to guess if a stl has color
00092  *
00093  * rules:
00094  * - It has to be binary
00095  * - The per face attribute should be not zero
00096  *
00097  */
00098 static bool IsSTLColored(const char * filename, bool &magicsMode)
00099 {
00100   if(IsSTLBinary(filename)==false)
00101     return false;
00102    FILE *fp = fopen(filename, "rb");
00103    char buf[STL_LABEL_SIZE+1];
00104    fread(buf,sizeof(char),STL_LABEL_SIZE,fp);
00105    std::string strInput(buf);
00106    size_t cInd = strInput.rfind("COLOR=");
00107    size_t mInd = strInput.rfind("MATERIAL=");
00108    if(cInd!=std::string::npos && mInd!=std::string::npos)
00109      magicsMode = true;
00110    else
00111      magicsMode = false;
00112    int facenum;
00113    fread(&facenum, sizeof(int), 1, fp);
00114 
00115    for(int i=0;i<std::min(facenum,1000);++i)
00116    {
00117      unsigned short attr;
00118      Point3f norm;
00119      Point3f tri[3];
00120      fread(&norm,sizeof(Point3f),1,fp);
00121      fread(&tri,sizeof(Point3f),3,fp);
00122      fread(&attr,sizeof(unsigned short),1,fp);
00123      if(attr!=0)
00124      {
00125       if(Color4b::FromUnsignedR5G5B5(attr) != Color4b(Color4b::White))
00126     return true;
00127      }
00128    }
00129 
00130    return false;
00131 }
00132 
00133 static bool IsSTLBinary(const char * filename)
00134 {
00135   bool binary=false;
00136   FILE *fp = fopen(filename, "r");
00137   /* Find size of file */
00138   fseek(fp, 0, SEEK_END);
00139   int file_size = ftell(fp);
00140   int facenum;
00141   /* Check for binary or ASCII file */
00142   fseek(fp, STL_LABEL_SIZE, SEEK_SET);
00143   fread(&facenum, sizeof(int), 1, fp);
00144   int expected_file_size=STL_LABEL_SIZE + 4 + (sizeof(short)+sizeof(STLFacet) )*facenum ;
00145   if(file_size ==  expected_file_size) binary = true;
00146   unsigned char tmpbuf[128];
00147   fread(tmpbuf,sizeof(tmpbuf),1,fp);
00148   for(unsigned int i = 0; i < sizeof(tmpbuf); i++)
00149     {
00150       if(tmpbuf[i] > 127)
00151           {
00152             binary=true;
00153             break;
00154           }
00155     }
00156   // Now we know if the stl file is ascii or binary.
00157   fclose(fp);
00158   return binary;
00159 }
00160 
00161 static int Open( OpenMeshType &m, const char * filename, int &loadMask, CallBackPos *cb=0)
00162 {
00163   FILE *fp = fopen(filename, "r");
00164   if(fp == NULL)
00165       return E_CANTOPEN;
00166   fclose(fp);
00167   loadMask |= Mask::IOM_VERTCOORD | Mask::IOM_FACEINDEX;
00168 
00169   if(IsSTLBinary(filename)) return OpenBinary(m,filename,loadMask,cb);
00170   else return OpenAscii(m,filename,cb);
00171 }
00172 
00173 static int OpenBinary( OpenMeshType &m, const char * filename, int &loadMask, CallBackPos *cb=0)
00174 {
00175   FILE *fp;
00176   fp = fopen(filename, "rb");
00177   if(fp == NULL)
00178   {
00179     return E_CANTOPEN;
00180   }
00181 
00182   bool magicsMode;
00183   if(!IsSTLColored(filename,magicsMode))
00184     loadMask = loadMask & (~Mask::IOM_FACECOLOR);
00185 
00186   int facenum;
00187   fseek(fp, STL_LABEL_SIZE, SEEK_SET);
00188   fread(&facenum, sizeof(int), 1, fp);
00189 
00190   m.Clear();
00191   FaceIterator fi=Allocator<OpenMeshType>::AddFaces(m,facenum);
00192   VertexIterator vi=Allocator<OpenMeshType>::AddVertices(m,facenum*3);
00193   // For each triangle read the normal, the three coords and a short set to zero
00194     for(int i=0;i<facenum;++i)
00195     {
00196       unsigned short attr;
00197       Point3f norm;
00198       Point3f tri[3];
00199       fread(&norm,sizeof(Point3f),1,fp);
00200       fread(&tri,sizeof(Point3f),3,fp);
00201       fread(&attr,sizeof(unsigned short),1,fp);
00202       if(tri::HasPerFaceColor(m) && (loadMask & Mask::IOM_FACECOLOR) )
00203       {
00204         if(magicsMode) (*fi).C()= Color4b::FromUnsignedR5G5B5(attr);
00205                   else (*fi).C()= Color4b::FromUnsignedB5G5R5(attr);
00206       }
00207       for(int k=0;k<3;++k)
00208       {
00209         (*vi).P().Import(tri[k]);
00210         (*fi).V(k)=&*vi;
00211         ++vi;
00212       }
00213       ++fi;
00214       if(cb && (i%1000)==0) cb((i*100)/facenum,"STL Mesh Loading");
00215     }
00216     fclose(fp);
00217     return E_NOERROR;
00218   }
00219 
00220 
00221   static int OpenAscii( OpenMeshType &m, const char * filename, CallBackPos *cb=0)
00222   {
00223     FILE *fp;
00224     fp = fopen(filename, "r");
00225     if(fp == NULL)
00226     {
00227       return E_CANTOPEN;
00228     }
00229         long currentPos = ftell(fp);
00230         fseek(fp,0L,SEEK_END);
00231         long fileLen = ftell(fp);
00232         fseek(fp,currentPos,SEEK_SET);
00233 
00234     m.Clear();
00235 
00236     /* Skip the first line of the file */
00237     while(getc(fp) != '\n') { }
00238 
00239     STLFacet f;
00240     int cnt=0;
00241         int lineCnt=0;
00242         int ret;
00243     /* Read a single facet from an ASCII .STL file */
00244     while(!feof(fp))
00245     {
00246       if(cb && (++cnt)%1000)   cb( int(double(ftell(fp))*100.0/fileLen), "STL Mesh Loading");
00247         ret=fscanf(fp, "%*s %*s %f %f %f\n", &f.n.X(), &f.n.Y(), &f.n.Z()); // --> "facet normal 0 0 0"
00248             if(ret!=3)
00249             {
00250                 // we could be in the case of a multiple solid object, where after a endfaced instead of another facet we have to skip two lines:
00251                 //     endloop
00252                 //       endfacet
00253                 //endsolid     <- continue on ret==0 will skip this line
00254                 //solid ascii  <- and this one.
00255                 //   facet normal 0.000000e+000 7.700727e-001 -6.379562e-001
00256                 lineCnt++;
00257                 continue;
00258             }
00259       ret=fscanf(fp, "%*s %*s"); // --> "outer loop"
00260       ret=fscanf(fp, "%*s %f %f %f\n", &f.v[0].X(),  &f.v[0].Y(),  &f.v[0].Z()); // --> "vertex x y z"
00261             if(ret!=3)
00262                 return E_UNESPECTEDEOF;
00263       ret=fscanf(fp, "%*s %f %f %f\n", &f.v[1].X(),  &f.v[1].Y(),  &f.v[1].Z()); // --> "vertex x y z"
00264             if(ret!=3)
00265                 return E_UNESPECTEDEOF;
00266       ret=fscanf(fp, "%*s %f %f %f\n", &f.v[2].X(),  &f.v[2].Y(),  &f.v[2].Z()); // --> "vertex x y z"
00267             if(ret!=3)
00268                 return E_UNESPECTEDEOF;
00269       ret=fscanf(fp, "%*s"); // --> "endloop"
00270       ret=fscanf(fp, "%*s"); // --> "endfacet"
00271             lineCnt+=7;
00272       if(feof(fp)) break;
00273       FaceIterator fi=Allocator<OpenMeshType>::AddFaces(m,1);
00274       VertexIterator vi=Allocator<OpenMeshType>::AddVertices(m,3);
00275       for(int k=0;k<3;++k)
00276       {
00277         (*vi).P().Import(f.v[k]);
00278         (*fi).V(k)=&*vi;
00279         ++vi;
00280       }
00281     }
00282     fclose(fp);
00283     return E_NOERROR;
00284   }
00285 }; // end class
00286 } // end Namespace tri
00287 } // end Namespace io
00288 } // end Namespace vcg
00289 
00290 #endif


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