import_raw.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 /****************************************************************************
00025   History
00026 
00027 $Log: not supported by cvs2svn $
00028 Revision 1.2  2005/05/09 12:29:55  callieri
00029 added line cleaning to eliminate all separators, added a rough triangulation scheme.
00030 
00031 Revision 1.1  2005/05/06 13:58:26  callieri
00032 First working version (callieri)
00033 
00034 
00035 ****************************************************************************/
00036 
00037 #ifndef __VCGLIB_IMPORT_RAW
00038 #define __VCGLIB_IMPORT_RAW
00039 
00040 #include <stdio.h>
00041 #include <fstream>
00042 #include <iostream>
00043 
00044 namespace vcg {
00045 namespace tri {
00046 namespace io {
00047 
00053 template <class MESH_TYPE>
00054 class ImporterRAW
00055 {
00056 public:
00057 
00058 typedef typename MESH_TYPE::VertexPointer VertexPointer;
00059 typedef typename MESH_TYPE::ScalarType ScalarType;
00060 typedef typename MESH_TYPE::VertexType VertexType;
00061 typedef typename MESH_TYPE::FaceType FaceType;
00062 typedef typename MESH_TYPE::VertexIterator VertexIterator;
00063 typedef typename MESH_TYPE::FaceIterator FaceIterator;
00064 
00065 // max token number
00066 #define RAW_MAX_TOKEN_LINE_DESCRIPTOR 32
00067 
00068 
00069 enum RAWError {
00070         E_NOERROR,                              // 0
00071                 // Error open
00072         E_CANTOPEN,                             // 1
00073         E_UNESPECTEDEOF,        // 2
00074             // error line descriptor
00075         E_INVALIDLINEDESC,      // 3
00076             // error line parsing
00077         E_LINEERROR,            // 4
00078         // wrong number of points
00079         E_WRONGPOINTNUM                 // 5
00080 };
00081 
00082 static const char *ErrorMsg(int error)
00083 {
00084   static const char * raw_error_msg[] =
00085   {
00086         "No errors",
00087         "Can't open file",
00088         "Premature End of file",
00089         "Invalid line Descriptor",
00090         "Error parsing a line",
00091         "Point number different from expected"
00092         };
00093 
00094   if(error>2 || error<0) return "Unknown error";
00095   else return stl_error_msg[error];
00096 };
00097 
00098 // line format is a string describing which data is stored for every data line
00099 // PX PY PZ   posizione
00100 // NX NY NZ   normale
00101 // CR CG CB   colore
00102 // RF         riflettanza (qualita')
00103 //
00104 // the string is parsed to know how many value are contained in each line
00105 // and which is the order. the result is a number (how many) and a vector 
00106 // describing the order
00107 //
00108 //
00109 // during reading a data structure is used to store intermediate values
00110 // it is basically an array of float 
00111 //
00112 // float linebuffer[]
00113 //[0][1][2][3][4][5][6][7][8][9]
00114 // p  p  p  n  n  n      c  c  c  r
00115 // x  y  z  x  y  z      r  g  b  f
00116 //
00117 // given the number of tokens and the order vector it is possible to scan a line using the command
00118 //
00119 // for(...n 0->tokennumber...)
00120 //   fscanf(fp,"%f", &linebuffer[tokenorder[n]])
00121 
00122 static int Parselinedescription(const char * linedesc, int &tokennumber, int *order)
00123 {
00124  int ii;
00125  char tok[3];
00126  int index;
00127 
00128  // controllo lunghezza
00129  // se non e' multiplo di 3 allora e' errato
00130  int len = strlen(linedesc) + 1;
00131   if(len%3 != 0)
00132    return E_INVALIDLINEDESC;
00133 
00134  index=0;
00135  tok[2] = '\0';
00136  tokennumber = 0;
00137  for(ii=0; ii<RAW_MAX_TOKEN_LINE_DESCRIPTOR; ii++)
00138    order[ii] = -1;
00139 
00140  while(index <= (len-3))
00141  {
00142   tok[0] = linedesc[index  ];
00143   tok[1] = linedesc[index+1];
00144 
00145   if(strcmp(tok,"PX") == 0)                                             // pos  x
00146     {order[tokennumber] = 0; tokennumber++;}
00147   else if (strcmp(tok,"PY") == 0)                               // pos  y
00148     {order[tokennumber] = 1; tokennumber++;}
00149   else if (strcmp(tok,"PZ") == 0)                               // pos  z
00150     {order[tokennumber] = 2; tokennumber++;}
00151   else if (strcmp(tok,"NX") == 0)                               // norm x
00152     {order[tokennumber] = 3; tokennumber++;}
00153   else if (strcmp(tok,"NY") == 0)                               // norm y
00154     {order[tokennumber] = 4; tokennumber++;}
00155   else if (strcmp(tok,"NZ") == 0)                               // norm z
00156     {order[tokennumber] = 5; tokennumber++;}
00157   else if (strcmp(tok,"CR") == 0)                               // col  r
00158     {order[tokennumber] = 6; tokennumber++;}
00159   else if (strcmp(tok,"CG") == 0)                               // col  g
00160     {order[tokennumber] = 7; tokennumber++;}
00161   else if (strcmp(tok,"CB") == 0)                               // col  b
00162     {order[tokennumber] = 8; tokennumber++;}
00163   else if (strcmp(tok,"RF") == 0)                               // rifl
00164     {order[tokennumber] = 9; tokennumber++;}
00165   else                                                                                  // nessuno dei suddetti... errore
00166   { return E_INVALIDLINEDESC; }
00167 
00168   index +=3;
00169  }
00170 
00171  return E_NOERROR;
00172 }
00173 
00174 
00175 // function to skip a line
00176 static void Skipline(FILE *fp)
00177 {
00178  char buf;
00179 
00180  fread(&(buf),sizeof(char),1,fp);
00181 
00182  while(buf != '\n')
00183   fread(&(buf),sizeof(char),1,fp);
00184 }
00185 
00186 // function to parse the line read from the raw file
00187 // all characters besides numerals,dot,minus,plus 
00188 // if e is found between numbers it's ketpt (12e4)
00189 static int Parseline(int tokennumber, int *tokenorder, char *rawline, float *linebuffer)
00190 {
00191  int linelen;
00192  int ii;
00193  bool change;
00194  int foundtok;
00195 
00196  // length
00197  linelen = strlen(rawline);
00198 
00199  // cleaning the line
00200  for(ii=0;ii<(linelen-1);)
00201  {
00202    change = true;
00203 
00204    if(isdigit(rawline[ii]))             // is a number
00205     change = false;
00206    else if(rawline[ii]==' ')    // is a space
00207     change = false;
00208    else if((rawline[ii]=='-') || (rawline[ii]=='+') || (rawline[ii]=='-') || (rawline[ii]=='.'))        // is + - .
00209     change = false;
00210    else if(rawline[ii]=='e')    // is e... is perhaps an exponential ?
00211      {  
00212            if((ii>0) || (ii<(linelen-2)))       // if it's at the begin or the end of line, it's not an exponential
00213             if(isdigit(rawline[ii-1]))          // a number before it
00214                   if(isdigit(rawline[ii+1]) || (rawline[ii+1]=='+') || (rawline[ii+1]=='-')) // after it a number a plus or a minus
00215             change = false;
00216          }
00217 
00218    if(change)
00219       rawline[ii++] = ' ';                      // then change it to ' ' 
00220    else
00221           ii++;
00222 
00223  }
00224  rawline[linelen] = '\0';
00225 
00226  // now parsing the line
00227  foundtok = 0;
00228  ii = 0;
00229  while((foundtok<tokennumber)&&(ii<linelen))
00230  {
00231   //find the next token begin
00232   while(rawline[ii] == ' ')
00233    ii++;
00234 
00235   foundtok++;
00236   sscanf(&(rawline[ii]),"%f", &(linebuffer[tokenorder[foundtok-1]]));
00237  
00238   // going after the token
00239   while((rawline[ii] != ' ')&&(rawline[ii] != '\0'))
00240    ii++;
00241  }
00242 
00243  if(foundtok<tokennumber)
00244    return E_LINEERROR;
00245  else
00246    return E_NOERROR;
00247 }
00248 
00249 
00250 static int fillHoles( MESH_TYPE &m, size_t rowCount, size_t colCount)
00251 {
00252 
00253  for (size_t i = 1; i<colCount-1; ++i)
00254  for (size_t j = 1; j<rowCount-1; ++j)
00255  {
00256       
00257      size_t ind  = (i) + ((j)   * colCount);
00258      size_t indL = (i-1) + ((j) * colCount);
00259      size_t indR = (i+1) + ((j) * colCount);
00260      size_t indT = (i) + ((j-1) * colCount);
00261      size_t indB = (i) + ((j+1) * colCount);
00262 
00263     if ((m.vert[ind].P()  == vcg::Point3<MESH_TYPE::ScalarType>(0,0,0)) &&
00264         (m.vert[indL].P() != vcg::Point3<MESH_TYPE::ScalarType>(0,0,0)) &&
00265         (m.vert[indR].P() != vcg::Point3<MESH_TYPE::ScalarType>(0,0,0)) &&
00266         (m.vert[indT].P() != vcg::Point3<MESH_TYPE::ScalarType>(0,0,0)) &&
00267         (m.vert[indB].P() != vcg::Point3<MESH_TYPE::ScalarType>(0,0,0)) )
00268     {
00269       m.vert[ind].P() = ( m.vert[indL].P() + m.vert[indR].P() + m.vert[indT].P() + m.vert[indB].P() ) * 0.25;
00270 
00271     } 
00272    
00273   
00274  }
00275 
00276   //vcg::tri::io::ExporterPLY<MESH_TYPE>::Save( hm, "hole.ply" );
00277   return 1;
00278 }
00279 
00288 static int Open( MESH_TYPE &m, const char * filename, bool triangulate=false, int lineskip = 0, const char * linedesc = "PX PY PZ")
00289 {
00290   int ii;
00291   int ret;
00292   
00293  
00294   FILE *fp;
00295   int rownumber;
00296   int colnumber;
00297 
00298   // line description
00299   int   tokennumber;
00300   int   tokenorder[RAW_MAX_TOKEN_LINE_DESCRIPTOR];
00301 
00302   // line read from file, to be parsed
00303   char rawline[512];
00304 
00305    
00306 
00307   //line data buffer
00308   float linebuffer[10];
00309   // fill buffer with standard values
00310   linebuffer[0] = linebuffer[1] = linebuffer[2] = 0.0;
00311   linebuffer[3] = linebuffer[4] = linebuffer[5] = 1.0;
00312   linebuffer[6] = 0.0; linebuffer[7] = 1.0; linebuffer[8] = 0.0;
00313   linebuffer[9] = 1.0;
00314 
00315 
00316   fp = fopen(filename, "r");
00317  
00318   if(fp == NULL)
00319   {
00320    return E_CANTOPEN;
00321   }
00322 
00323   // skip initial lines
00324   for(ii=0; ii<lineskip; ii++) Skipline(fp);
00325 
00326   // in raw files with indication of rows and columns it's also possible to triangulate points
00327   // after the skipped lines there should be the number of row and columns
00328   if(triangulate)
00329   {
00330    fscanf(fp,"%i", &(rownumber));
00331    fscanf(fp,"%i\n", &(colnumber));
00332   }
00333 
00334   // parsing line description
00335   ret = Parselinedescription(linedesc, tokennumber, tokenorder);
00336   if(ret)
00337    return ret;
00338 
00339   m.Clear();
00340   m.vert.reserve( rownumber * colnumber );
00341   int line = 0;
00342   size_t rowCounter = 0;
00343   size_t colCounter = 0;
00344   while(!feof(fp))
00345   {
00346           
00347    //read a new line
00348 
00349    ii=0;
00350    memset( rawline, 0, 512);
00351    fread(&(rawline[ii++]),sizeof(char),1,fp);
00352    while( (rawline[ii-1] != '\n') && (ii<512) ) 
00353    {
00354    fread(&(rawline[ii++]),sizeof(char),1,fp);
00355    }
00356    rawline[ii-1] = '\0';
00357    line++;
00358    if(strlen(rawline) >0)  // empty line, just skip
00359    {
00360 
00361     ret = Parseline(tokennumber, tokenorder, rawline, linebuffer);
00362     if(ret)
00363      return ret;
00364 
00365     /*
00366     // old code reading directly fom file stream
00367     for(ii=0; ii<tokennumber; ii++)
00368       fscanf(fp,"%f", &(linebuffer[tokenorder[ii]]));
00369     */
00370 
00371     // new vertex
00372     VertexType nv;
00373 
00374     // store the position
00375     nv.P()[0] = linebuffer[0];
00376     nv.P()[1] = linebuffer[1];
00377     nv.P()[2] = linebuffer[2];
00378 
00379     // store the normal
00380     if(HasPerVertexNormal(m))
00381     {
00382      nv.N()[0] = linebuffer[3];
00383      nv.N()[1] = linebuffer[4];
00384      nv.N()[2] = linebuffer[5];
00385     }
00386 
00387     // store the color
00388     if(HasPerVertexColor(m))
00389     {
00390      nv.C()[0] = linebuffer[6];
00391      nv.C()[1] = linebuffer[7];
00392      nv.C()[2] = linebuffer[8];
00393     }
00394 
00395     // store the reflectance
00396     if(m.HasPerVertexQuality())
00397     {
00398      nv.Q() = linebuffer[9];
00399     }
00400 
00401     m.vert.push_back(nv);
00402     
00403     
00404     
00405    } // end if zero length
00406   }
00407    m.vn = m.vert.size();
00408  if(triangulate) fillHoles(m, rownumber, colnumber);
00409 
00410   // update model point number
00411  
00412 
00413   // now generate the triangles
00414   if(triangulate)
00415   {
00416     int rr,cc;
00417     //if(m.vn != (rownumber * colnumber)) return E_WRONGPOINTNUM;
00418 
00419     int trinum = (rownumber-1) * (colnumber-1) * 2;
00420 
00421     FaceIterator fi=Allocator<MESH_TYPE>::AddFaces(m,trinum);
00422     FaceIterator fi2 = fi;
00423         m.fn = trinum;
00424         for(cc=0; cc<colnumber-1; cc++)
00425         for(rr=0; rr<rownumber-1; rr++)
00426          {
00427                 // upper tri
00428                 (*fi).V(0) = &(m.vert[(cc+1) + ((rr  ) * colnumber)]);
00429                 (*fi).V(1) = &(m.vert[(cc  ) + ((rr  ) * colnumber)]);
00430                 (*fi).V(2) = &(m.vert[(cc  ) + ((rr+1) * colnumber)]);
00431 
00432 
00433                  fi++;
00434 
00435                 // lower tri
00436                 (*fi).V(0) = &(m.vert[(cc  ) + ((rr+1) * colnumber)]);
00437                 (*fi).V(1) = &(m.vert[(cc+1) + ((rr+1) * colnumber)]);
00438                 (*fi).V(2) = &(m.vert[(cc+1) + ((rr  ) * colnumber)]);
00439 
00440                  fi++;
00441          
00442          }
00443          
00444          // tag faux faces
00445    if (m.HasPerFaceFlags()) {
00446      for (; fi2!=m.face.end(); fi2++) {
00447        (*fi2).SetF(2);
00448      }
00449    }
00450 
00451          
00452         
00453   }
00454 
00455   fclose(fp);
00456   return E_NOERROR;
00457 }
00458 
00459 }; // end class
00460 } // end Namespace tri
00461 } // end Namespace io
00462 } // end Namespace vcg
00463 
00464 #endif


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