Ver Fonte

read directly from file pointer

Former-commit-id: 4adb9bf113ce0166779a8b9ed0d7d12712a042ac
Alec Jacobson há 8 anos atrás
pai
commit
b6e3b252af

+ 97 - 0
include/igl/guess_extension.cpp

@@ -0,0 +1,97 @@
+#include "guess_extension.h"
+#include "is_stl.h"
+#include "ply.h"
+
+IGL_INLINE std::string igl::guess_extension(FILE * fp)
+{
+  const auto is_off = [](FILE * fp)-> bool
+  {
+    char header[1000];
+    const std::string OFF("OFF");
+    const std::string NOFF("NOFF");
+    const std::string COFF("COFF");
+    bool f = (fscanf(fp,"%s\n",header)==1 && (
+        std::string(header).compare(0, OFF.length(), OFF)==0 ||
+        std::string(header).compare(0, COFF.length(), COFF)==0 ||
+        std::string(header).compare(0,NOFF.length(),NOFF)==0));
+    rewind(fp);
+    return f;
+  };
+  const auto is_ply = [](FILE * ply_file) -> bool
+  {
+    int nelems;
+    char ** elem_names;
+    PlyFile * in_ply = ply_read(ply_file,&nelems,&elem_names);
+    if(in_ply==NULL)
+    {
+      return false;
+    }
+    free(in_ply);
+    rewind(ply_file);
+    return true;
+  };
+  const auto is_wrl = [](FILE * wrl_file)->bool
+  {
+    bool still_comments = true;
+    char line[1000];
+    std::string needle("point [");
+    std::string haystack;
+    while(still_comments)
+    {
+      if(fgets(line,1000,wrl_file) == NULL)
+      {
+        rewind(wrl_file);
+        return false;
+      }
+      haystack = std::string(line);
+      still_comments = std::string::npos == haystack.find(needle);
+    }
+    rewind(wrl_file);
+    return true;
+  };
+  const auto is_mesh = [](FILE * mesh_file )->bool
+  {
+    char line[2048];
+    // eat comments at beginning of file
+    bool still_comments= true;
+    while(still_comments)
+    {
+      if(fgets(line,2048,mesh_file) == NULL)
+      {
+        rewind(mesh_file);
+        return false;
+      }
+      still_comments = (line[0] == '#' || line[0] == '\n');
+    }
+    char str[2048];
+    sscanf(line," %s",str);
+    // check that first word is MeshVersionFormatted
+    if(0!=strcmp(str,"MeshVersionFormatted"))
+    {
+      rewind(mesh_file);
+      return false;
+    }
+    rewind(mesh_file);
+    return true;
+  };
+  std::string ext = "obj";
+  if(is_mesh(fp))
+  {
+    ext = "mesh";
+  }else if(is_off(fp))
+  {
+    ext = "off";
+  }else if(is_ply(fp))
+  {
+    ext = "ply";
+  }else if(igl::is_stl(fp))
+  {
+    ext = "stl";
+  }else if(is_wrl(fp))
+  {
+    ext = "wrl";
+  }
+  // else obj
+  rewind(fp);
+  return ext;
+}

+ 24 - 0
include/igl/guess_extension.h

@@ -0,0 +1,24 @@
+#ifndef IGL_GUESS_EXTENSION_H
+#define IGL_GUESS_EXTENSION_H
+#include "igl_inline.h"
+#include <string>
+#include <cstdio>
+namespace igl
+{
+  // Given a file pointer at the beginning of a "mesh" file, try to guess the
+  // extension of the file format it comes from. The file pointer is rewound on
+  // return.
+  //
+  // Inputs:
+  //   fp  file pointer (see output)
+  // Outputs:
+  //   fp  file pointer rewound 
+  // Returns extension as string. One of "mesh",{"obj"},"off","ply","stl", or
+  //   "wrl"
+  //
+  IGL_INLINE std::string guess_extension(FILE * fp);
+}
+#ifndef IGL_STATIC_LIBRARY
+#  include "guess_extension.cpp"
+#endif
+#endif

+ 63 - 0
include/igl/is_stl.cpp

@@ -0,0 +1,63 @@
+#include "is_stl.h"
+#include <string>
+IGL_INLINE bool igl::is_stl(FILE * stl_file, bool & is_ascii)
+{
+
+  //      solid?
+  //   YES      NO
+  //   /         if .stl, definitely binary
+  //  /
+  // perfect size?
+  //      YES     NO
+  //
+  const auto perfect_size = [](FILE * stl_file)->bool
+  {
+    stl_file = freopen(NULL,"rb",stl_file);
+    // Read 80 header
+    char header[80];
+    if(fread(header,sizeof(char),80,stl_file)!=80)
+    {
+      return false;
+    }
+    // Read number of triangles
+    unsigned int num_tri;
+    if(fread(&num_tri,sizeof(unsigned int),1,stl_file)!=1)
+    {
+      return false;
+    }
+    fseek(stl_file,0,SEEK_END);
+    int file_size = ftell(stl_file);
+    stl_file = freopen(NULL,"r",stl_file);
+    return (file_size == 80 + 4 + (4*12 + 2) * num_tri);
+  };
+  // Specifically 80 character header
+  char header[80];
+  char solid[80];
+  is_ascii = true;
+  bool f = true;
+  if(fread(header,1,80,stl_file) != 80)
+  {
+    f = false;
+    goto finish;
+  }
+
+  sscanf(header,"%s",solid);
+  if(std::string("solid") == solid)
+  {
+    f = true;
+    is_ascii = !perfect_size(stl_file);
+  }else
+  {
+    is_ascii = false;
+    f = perfect_size(stl_file);
+  }
+finish:
+  rewind(stl_file);
+  return f;
+}
+
+IGL_INLINE bool igl::is_stl(FILE * stl_file)
+{
+  bool is_ascii;
+  return is_stl(stl_file,is_ascii);
+}

+ 21 - 0
include/igl/is_stl.h

@@ -0,0 +1,21 @@
+#ifndef IGL_IS_STL_H
+#define IGL_IS_STL_H
+#include "igl_inline.h"
+#include <cstdio>
+namespace igl
+{
+  // Given a file pointer, determine if it contains an .stl file and then
+  // rewind it.
+  // 
+  // Inputs:
+  //   stl_file  pointer to file 
+  // Outputs:
+  //   is_ascii  flag whether stl is ascii
+  // Returns  whether stl_file is an .stl file
+  IGL_INLINE bool is_stl(FILE * stl_file, bool & is_ascii);
+  IGL_INLINE bool is_stl(FILE * stl_file);
+};
+#ifndef IGL_STATIC_LIBRARY
+#  include "is_stl.cpp"
+#endif
+#endif

+ 1 - 1
include/igl/ply.h.REMOVED.git-id

@@ -1 +1 @@
-aa5b1239a610dbd02506563452ec69172ae4165a
+0878f821fc814405b3bd8c4bdf25ce10df162e95

+ 29 - 5
include/igl/readMESH.cpp

@@ -7,9 +7,6 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "readMESH.h"
 
-#include <cstdio>
-#include "verbose.h"
-
 template <typename Scalar, typename Index>
 IGL_INLINE bool igl::readMESH(
   const std::string mesh_file_name,
@@ -24,6 +21,17 @@ IGL_INLINE bool igl::readMESH(
     fprintf(stderr,"IOError: %s could not be opened...",mesh_file_name.c_str());
     return false;
   }
+  return igl::readMESH(mesh_file,V,T,F);
+}
+
+template <typename Scalar, typename Index>
+IGL_INLINE bool igl::readMESH(
+  FILE * mesh_file,
+  std::vector<std::vector<Scalar > > & V,
+  std::vector<std::vector<Index > > & T,
+  std::vector<std::vector<Index > > & F)
+{
+  using namespace std;
 #ifndef LINE_MAX
 #  define LINE_MAX 2048
 #endif
@@ -37,10 +45,14 @@ IGL_INLINE bool igl::readMESH(
   still_comments= true;
   while(still_comments)
   {
-    fgets(line,LINE_MAX,mesh_file);
+    if(fgets(line,LINE_MAX,mesh_file) == NULL)
+    {
+      fprintf(stderr, "Error: couldn't find start of .mesh file");
+      fclose(mesh_file);
+      return false;
+    }
     still_comments = (line[0] == '#' || line[0] == '\n');
   }
-
   char str[LINE_MAX];
   sscanf(line," %s",str);
   // check that first word is MeshVersionFormatted
@@ -51,6 +63,7 @@ IGL_INLINE bool igl::readMESH(
     fclose(mesh_file);
     return false;
   }
+
   int one = -1;
   if(2 != sscanf(line,"%s %d",str,&one))
   {
@@ -238,6 +251,17 @@ IGL_INLINE bool igl::readMESH(
     fprintf(stderr,"IOError: %s could not be opened...",mesh_file_name.c_str());
     return false;
   }
+  return readMESH(mesh_file,V,T,F);
+}
+
+template <typename DerivedV, typename DerivedF, typename DerivedT>
+IGL_INLINE bool igl::readMESH(
+  FILE * mesh_file,
+  Eigen::PlainObjectBase<DerivedV>& V,
+  Eigen::PlainObjectBase<DerivedT>& T,
+  Eigen::PlainObjectBase<DerivedF>& F)
+{
+  using namespace std;
 #ifndef LINE_MAX
 #  define LINE_MAX 2048
 #endif

+ 22 - 1
include/igl/readMESH.h

@@ -9,9 +9,10 @@
 #define IGL_READMESH_H
 #include "igl_inline.h"
 
+#include <Eigen/Core>
 #include <string>
 #include <vector>
-#include <Eigen/Core>
+#include <cstdio>
 
 namespace igl
 {
@@ -35,6 +36,16 @@ namespace igl
     std::vector<std::vector<Scalar > > & V,
     std::vector<std::vector<Index > > & T,
     std::vector<std::vector<Index > > & F);
+  // Inputs:
+  //   mesh_file  pointer to already opened .mesh file 
+  // Outputs:
+  //   mesh_file  closed file
+  template <typename Scalar, typename Index>
+  IGL_INLINE bool readMESH(
+    FILE * mesh_file,
+    std::vector<std::vector<Scalar > > & V,
+    std::vector<std::vector<Index > > & T,
+    std::vector<std::vector<Index > > & F);
 
   // Input:
   //   mesh_file_name  path of .mesh file
@@ -48,6 +59,16 @@ namespace igl
     Eigen::PlainObjectBase<DerivedV>& V,
     Eigen::PlainObjectBase<DerivedT>& T,
     Eigen::PlainObjectBase<DerivedF>& F);
+  // Inputs:
+  //   mesh_file  pointer to already opened .mesh file 
+  // Outputs:
+  //   mesh_file  closed file
+  template <typename DerivedV, typename DerivedF, typename DerivedT>
+  IGL_INLINE bool readMESH(
+    FILE * mesh_file,
+    Eigen::PlainObjectBase<DerivedV>& V,
+    Eigen::PlainObjectBase<DerivedT>& T,
+    Eigen::PlainObjectBase<DerivedF>& F);
 }
 
 #ifndef IGL_STATIC_LIBRARY

+ 15 - 0
include/igl/readOBJ.cpp

@@ -33,6 +33,19 @@ IGL_INLINE bool igl::readOBJ(
             obj_file_name.c_str());
     return false;
   }
+  return igl::readOBJ(obj_file,V,TC,N,F,FTC,FN);
+}
+
+template <typename Scalar, typename Index>
+IGL_INLINE bool igl::readOBJ(
+  FILE * obj_file,
+  std::vector<std::vector<Scalar > > & V,
+  std::vector<std::vector<Scalar > > & TC,
+  std::vector<std::vector<Scalar > > & N,
+  std::vector<std::vector<Index > > & F,
+  std::vector<std::vector<Index > > & FTC,
+  std::vector<std::vector<Index > > & FN)
+{
   // File open was succesfull so clear outputs
   V.clear();
   TC.clear();
@@ -337,6 +350,8 @@ IGL_INLINE bool igl::readOBJ(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
+template bool igl::readOBJ<double, int>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >&, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >&, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
+// generated by autoexplicit.sh
 template bool igl::readOBJ<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 template bool igl::readOBJ<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(std::string, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
 template bool igl::readOBJ<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);

+ 14 - 0
include/igl/readOBJ.h

@@ -19,6 +19,7 @@
 #endif
 #include <string>
 #include <vector>
+#include <cstdio>
 
 namespace igl 
 {
@@ -48,6 +49,19 @@ namespace igl
     std::vector<std::vector<Index > > & F,
     std::vector<std::vector<Index > > & FTC,
     std::vector<std::vector<Index > > & FN);
+  // Inputs:
+  //   obj_file  pointer to already opened .obj file 
+  // Outputs:
+  //   obj_file  closed file
+  template <typename Scalar, typename Index>
+  IGL_INLINE bool readOBJ(
+    FILE * obj_file,
+    std::vector<std::vector<Scalar > > & V,
+    std::vector<std::vector<Scalar > > & TC,
+    std::vector<std::vector<Scalar > > & N,
+    std::vector<std::vector<Index > > & F,
+    std::vector<std::vector<Index > > & FTC,
+    std::vector<std::vector<Index > > & FN);
   // Just V and F
   template <typename Scalar, typename Index>
   IGL_INLINE bool readOBJ(

+ 17 - 4
include/igl/readOFF.cpp

@@ -7,7 +7,6 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "readOFF.h"
 #include "list_to_matrix.h"
-#include <cstdio>
 
 template <typename Scalar, typename Index>
 IGL_INLINE bool igl::readOFF(
@@ -24,6 +23,18 @@ IGL_INLINE bool igl::readOFF(
     printf("IOError: %s could not be opened...\n",off_file_name.c_str());
     return false;
   }
+  return readOFF(off_file,V,F,N,C);
+}
+
+template <typename Scalar, typename Index>
+IGL_INLINE bool igl::readOFF(
+  FILE * off_file,
+  std::vector<std::vector<Scalar > > & V,
+  std::vector<std::vector<Index > > & F,
+  std::vector<std::vector<Scalar > > & N,
+  std::vector<std::vector<Scalar > > & C)
+{
+  using namespace std;
   V.clear();
   F.clear();
   N.clear();
@@ -40,7 +51,7 @@ IGL_INLINE bool igl::readOFF(
        string(header).compare(0, COFF.length(), COFF)==0 ||
        string(header).compare(0,NOFF.length(),NOFF)==0))
   {
-    printf("Error: readOFF() %s's first line should be OFF or NOFF or COFF, not %s...",off_file_name.c_str(),header);
+    printf("Error: readOFF() first line should be OFF or NOFF or COFF, not %s...",header);
     fclose(off_file);
     return false;
   }
@@ -105,7 +116,7 @@ IGL_INLINE bool igl::readOFF(
       fscanf(off_file,"%[^\n]",comment);
     }else
     {
-      printf("Error: bad line (%d) in %s\n",i,off_file_name.c_str());
+      printf("Error: bad line (%d)\n",i);
       if(feof(off_file))
       {
         fclose(off_file);
@@ -142,7 +153,7 @@ IGL_INLINE bool igl::readOFF(
       fscanf(off_file,"%[^\n]",comment);
     }else
     {
-      printf("Error: bad line in %s\n",off_file_name.c_str());
+      printf("Error: bad line\n");
       fclose(off_file);
       return false;
     }
@@ -246,6 +257,8 @@ IGL_INLINE bool igl::readOFF(
 #ifdef IGL_STATIC_LIBRARY
 // Explicit template specialization
 // generated by autoexplicit.sh
+template bool igl::readOFF<double, int>(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >&, std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >&);
+// generated by autoexplicit.sh
 template bool igl::readOFF<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
 // generated by autoexplicit.sh
 template bool igl::readOFF<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);

+ 12 - 0
include/igl/readOFF.h

@@ -16,6 +16,7 @@
 #endif
 #include <string>
 #include <vector>
+#include <cstdio>
 
 namespace igl 
 {
@@ -42,6 +43,17 @@ namespace igl
     std::vector<std::vector<Index > > & F,
     std::vector<std::vector<Scalar > > & N,
     std::vector<std::vector<Scalar > > & C);
+  // Inputs:
+  //   off_file  pointer to already opened .off file 
+  // Outputs:
+  //   off_file  closed file
+  template <typename Scalar, typename Index>
+  IGL_INLINE bool readOFF(
+    FILE * off_file,
+    std::vector<std::vector<Scalar > > & V,
+    std::vector<std::vector<Index > > & F,
+    std::vector<std::vector<Scalar > > & N,
+    std::vector<std::vector<Scalar > > & C);
   
   
 #ifndef IGL_NO_EIGEN

+ 22 - 6
include/igl/readPLY.cpp

@@ -24,7 +24,27 @@ IGL_INLINE bool igl::readPLY(
 {
   using namespace std;
   // Largely follows ply2iv.c
+  FILE * ply_file = fopen(filename.c_str(),"r");
+  if(ply_file == NULL)
+  {
+    return false;
+  }
+  return readPLY(ply_file,V,F,N,UV);
+}
 
+template <
+  typename Vtype,
+  typename Ftype,
+  typename Ntype,
+  typename UVtype>
+IGL_INLINE bool igl::readPLY(
+  FILE * ply_file,
+  std::vector<std::vector<Vtype> > & V,
+  std::vector<std::vector<Ftype> > & F,
+  std::vector<std::vector<Ntype> > & N,
+  std::vector<std::vector<UVtype> >  & UV)
+{
+  using namespace std;
    typedef struct Vertex {
      double x,y,z;          /* position */
      double nx,ny,nz;         /* surface normal */
@@ -53,14 +73,10 @@ IGL_INLINE bool igl::readPLY(
     {"vertex_indices", PLY_INT, PLY_INT, offsetof(Face,verts),
       1, PLY_UCHAR, PLY_UCHAR, offsetof(Face,nverts)},
   };
-  FILE * fp = fopen(filename.c_str(),"r");
-  if(fp == NULL)
-  {
-    return false;
-  }
+
   int nelems;
   char ** elem_names;
-  PlyFile * in_ply = ply_read(fp,&nelems,&elem_names);
+  PlyFile * in_ply = ply_read(ply_file,&nelems,&elem_names);
   if(in_ply==NULL)
   {
     return false;

+ 16 - 0
include/igl/readPLY.h

@@ -11,6 +11,7 @@
 #include <Eigen/Core>
 #include <string>
 #include <vector>
+#include <cstdio>
 
 namespace igl
 {
@@ -36,6 +37,21 @@ namespace igl
     std::vector<std::vector<Ntype> > & N,
     std::vector<std::vector<UVtype> >  & UV);
   template <
+    typename Vtype,
+    typename Ftype,
+    typename Ntype,
+    typename UVtype>
+  // Inputs:
+  //   ply_file  pointer to already opened .ply file 
+  // Outputs:
+  //   ply_file  closed file
+  IGL_INLINE bool readPLY(
+    FILE * ply_file,
+    std::vector<std::vector<Vtype> > & V,
+    std::vector<std::vector<Ftype> > & F,
+    std::vector<std::vector<Ntype> > & N,
+    std::vector<std::vector<UVtype> >  & UV);
+    template <
     typename DerivedV,
     typename DerivedF,
     typename DerivedN,

+ 42 - 26
include/igl/readSTL.cpp

@@ -60,21 +60,39 @@ IGL_INLINE bool igl::readSTL(
             filename.c_str());
     return false;
   }
+  return readSTL(stl_file,V,F,N);
+}
+
+template <typename TypeV, typename TypeF, typename TypeN>
+IGL_INLINE bool igl::readSTL(
+  FILE * stl_file, 
+  std::vector<std::vector<TypeV> > & V,
+  std::vector<std::vector<TypeF> > & F,
+  std::vector<std::vector<TypeN> > & N)
+{
+  using namespace std;
+  stl_file = freopen(NULL,"rb",stl_file);
+  if(NULL==stl_file)
+  {
+    fprintf(stderr,"IOError: stl file could not be reopened as binary (1) ...\n");
+    return false;
+  }
+
   V.clear();
   F.clear();
   N.clear();
+
+
   // Specifically 80 character header
   char header[80];
   char solid[80];
   bool is_ascii = true;
   if(fread(header,1,80,stl_file) != 80)
   {
-    cerr<<"IOError: "<<filename<<" too short (1)."<<endl;
+    cerr<<"IOError: too short (1)."<<endl;
     goto close_false;
   }
-
   sscanf(header,"%s",solid);
-
   if(string("solid") != solid)
   {
     // definitely **not** ascii 
@@ -85,7 +103,7 @@ IGL_INLINE bool igl::readSTL(
     char buf[4];
     if(fread(buf,1,4,stl_file) != 4)
     {
-      cerr<<"IOError: "<<filename<<" too short (3)."<<endl;
+      cerr<<"IOError: too short (3)."<<endl;
       goto close_false;
     }
     size_t num_faces = *reinterpret_cast<unsigned int*>(buf);
@@ -99,14 +117,18 @@ IGL_INLINE bool igl::readSTL(
       is_ascii = true;
     }
   }
-  fclose(stl_file);
-
-
 
   if(is_ascii)
   {
     // Rewind to end of header
-    stl_file = fopen(filename.c_str(),"r");
+    //stl_file = fopen(filename.c_str(),"r");
+    stl_file = freopen(NULL,"r",stl_file);
+    if(NULL==stl_file)
+    {
+      fprintf(stderr,"IOError: stl file could not be reopened as ascii ...\n");
+      return false;
+    }
+    // Read 80 header
     // Eat file name
 #ifndef IGL_LINE_MAX
 #  define IGL_LINE_MAX 2048
@@ -114,7 +136,7 @@ IGL_INLINE bool igl::readSTL(
     char name[IGL_LINE_MAX];
     if(NULL==fgets(name,IGL_LINE_MAX,stl_file))
     {
-      cerr<<"IOError: "<<filename<<" ascii too short (2)."<<endl;
+      cerr<<"IOError: ascii too short (2)."<<endl;
       goto close_false;
     }
     // ascii
@@ -136,7 +158,7 @@ IGL_INLINE bool igl::readSTL(
       {
         cout<<"facet: "<<facet<<endl;
         cout<<"normal: "<<normal<<endl;
-        cerr<<"IOError: "<<filename<<" bad format (1)."<<endl;
+        cerr<<"IOError: bad format (1)."<<endl;
         goto close_false;
       }
       // copy casts to Type
@@ -146,7 +168,7 @@ IGL_INLINE bool igl::readSTL(
       ret = fscanf(stl_file,"%s %s",outer,loop);
       if(ret != 2 || string("outer") != outer || string("loop") != loop)
       {
-        cerr<<"IOError: "<<filename<<" bad format (2)."<<endl;
+        cerr<<"IOError: bad format (2)."<<endl;
         goto close_false;
       }
       vector<TypeF> f;
@@ -164,7 +186,7 @@ IGL_INLINE bool igl::readSTL(
           int ret = fscanf(stl_file,"%lg %lg %lg",vd,vd+1,vd+2);
           if(ret != 3)
           {
-            cerr<<"IOError: "<<filename<<" bad format (3)."<<endl;
+            cerr<<"IOError: bad format (3)."<<endl;
             goto close_false;
           }
           f.push_back(V.size());
@@ -173,7 +195,7 @@ IGL_INLINE bool igl::readSTL(
           V.push_back(v);
         }else
         {
-          cerr<<"IOError: "<<filename<<" bad format (4)."<<endl;
+          cerr<<"IOError: bad format (4)."<<endl;
           goto close_false;
         }
       }
@@ -182,7 +204,7 @@ IGL_INLINE bool igl::readSTL(
       ret = fscanf(stl_file,"%s",endfacet);
       if(ret != 1 || string("endfacet") != endfacet)
       {
-        cerr<<"IOError: "<<filename<<" bad format (5)."<<endl;
+        cerr<<"IOError: bad format (5)."<<endl;
         goto close_false;
       }
     }
@@ -191,25 +213,19 @@ IGL_INLINE bool igl::readSTL(
   }else
   {
     // Binary
-    stl_file = fopen(filename.c_str(),"rb");
-    if(NULL==stl_file)
-    {
-      fprintf(stderr,"IOError: %s could not be opened...\n",
-              filename.c_str());
-      return false;
-    }
+    stl_file = freopen(NULL,"rb",stl_file);
     // Read 80 header
     char header[80];
     if(fread(header,sizeof(char),80,stl_file)!=80)
     {
-      cerr<<"IOError: "<<filename<<" bad format (6)."<<endl;
+      cerr<<"IOError: bad format (6)."<<endl;
       goto close_false;
     }
     // Read number of triangles
     unsigned int num_tri;
     if(fread(&num_tri,sizeof(unsigned int),1,stl_file)!=1)
     {
-      cerr<<"IOError: "<<filename<<" bad format (7)."<<endl;
+      cerr<<"IOError: bad format (7)."<<endl;
       goto close_false;
     }
     V.resize(num_tri*3,vector<TypeV >(3,0));
@@ -221,7 +237,7 @@ IGL_INLINE bool igl::readSTL(
       float n[3];
       if(fread(n,sizeof(float),3,stl_file)!=3)
       {
-        cerr<<"IOError: "<<filename<<" bad format (8)."<<endl;
+        cerr<<"IOError: bad format (8)."<<endl;
         goto close_false;
       }
       // Read each vertex
@@ -232,7 +248,7 @@ IGL_INLINE bool igl::readSTL(
         float v[3];
         if(fread(v,sizeof(float),3,stl_file)!=3)
         {
-          cerr<<"IOError: "<<filename<<" bad format (9)."<<endl;
+          cerr<<"IOError: bad format (9)."<<endl;
           goto close_false;
         }
         V[3*t+c][0] = v[0];
@@ -243,7 +259,7 @@ IGL_INLINE bool igl::readSTL(
       unsigned short att_count;
       if(fread(&att_count,sizeof(unsigned short),1,stl_file)!=1)
       {
-        cerr<<"IOError: "<<filename<<" bad format (10)."<<endl;
+        cerr<<"IOError: bad format (10)."<<endl;
         goto close_false;
       }
     }

+ 11 - 0
include/igl/readSTL.h

@@ -13,6 +13,7 @@
 #  include <Eigen/Core>
 #endif
 #include <string>
+#include <cstdio>
 #include <vector>
 
 namespace igl 
@@ -41,6 +42,16 @@ namespace igl
     Eigen::PlainObjectBase<DerivedV> & V,
     Eigen::PlainObjectBase<DerivedF> & F,
     Eigen::PlainObjectBase<DerivedN> & N);
+  // Inputs:
+  //   stl_file  pointer to already opened .stl file 
+  // Outputs:
+  //   stl_file  closed file
+  template <typename TypeV, typename TypeF, typename TypeN>
+  IGL_INLINE bool readSTL(
+    FILE * stl_file, 
+    std::vector<std::vector<TypeV> > & V,
+    std::vector<std::vector<TypeF> > & F,
+    std::vector<std::vector<TypeN> > & N);
   template <typename TypeV, typename TypeF, typename TypeN>
   IGL_INLINE bool readSTL(
     const std::string & filename,

+ 16 - 4
include/igl/readWRL.cpp

@@ -6,7 +6,7 @@
 // v. 2.0. If a copy of the MPL was not distributed with this file, You can 
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "readWRL.h"
-#include <cstdio>
+#include <iostream>
 
 template <typename Scalar, typename Index>
 IGL_INLINE bool igl::readWRL(
@@ -21,9 +21,16 @@ IGL_INLINE bool igl::readWRL(
     printf("IOError: %s could not be opened...",wrl_file_name.c_str());
     return false;
   }
+  return readWRL(wrl_file,V,F);
+}
 
-  V.clear();
-  F.clear();
+template <typename Scalar, typename Index>
+IGL_INLINE bool igl::readWRL(
+  FILE * wrl_file,
+  std::vector<std::vector<Scalar > > & V,
+  std::vector<std::vector<Index > > & F)
+{
+  using namespace std;
 
   char line[1000];
   // Read lines until seeing "point ["
@@ -33,7 +40,12 @@ IGL_INLINE bool igl::readWRL(
   string haystack;
   while(still_comments)
   {
-    fgets(line,1000,wrl_file);
+    if(fgets(line,1000,wrl_file) == NULL)
+    {
+      std::cerr<<"readWRL, reached EOF without finding \"point [\""<<std::endl;
+      fclose(wrl_file);
+      return false;
+    }
     haystack = string(line);
     still_comments = string::npos == haystack.find(needle);
   }

+ 10 - 0
include/igl/readWRL.h

@@ -11,6 +11,7 @@
 
 #include <string>
 #include <vector>
+#include <cstdio>
 
 namespace igl 
 {
@@ -32,6 +33,15 @@ namespace igl
     const std::string wrl_file_name, 
     std::vector<std::vector<Scalar > > & V,
     std::vector<std::vector<Index > > & F);
+  // Inputs:
+  //   wrl_file  pointer to already opened .wrl file 
+  // Outputs:
+  //   wrl_file  closed file
+  template <typename Scalar, typename Index>
+  IGL_INLINE bool readWRL(
+    FILE * wrl_file,
+    std::vector<std::vector<Scalar > > & V,
+    std::vector<std::vector<Index > > & F);
 
 }
 

+ 29 - 18
include/igl/read_triangle_mesh.cpp

@@ -7,18 +7,17 @@
 // obtain one at http://mozilla.org/MPL/2.0/.
 #include "read_triangle_mesh.h"
 
-#include <igl/list_to_matrix.h>
-#include <igl/readMESH.h>
-#include <igl/readOBJ.h>
-#include <igl/readOFF.h>
-#include <igl/readSTL.h>
-#include <igl/readPLY.h>
-#include <igl/readWRL.h>
-#include <igl/pathinfo.h>
-#include <igl/boundary_facets.h>
-#include <igl/polygon_mesh_to_triangle_mesh.h>
+#include "list_to_matrix.h"
+#include "readMESH.h"
+#include "readOBJ.h"
+#include "readOFF.h"
+#include "readSTL.h"
+#include "readPLY.h"
+#include "readWRL.h"
+#include "pathinfo.h"
+#include "boundary_facets.h"
+#include "polygon_mesh_to_triangle_mesh.h"
 
-#include <cstdio>
 #include <algorithm>
 #include <iostream>
 
@@ -85,13 +84,26 @@ IGL_INLINE bool igl::read_triangle_mesh(
   pathinfo(filename,dir,base,ext,name);
   // Convert extension to lower case
   transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
+  FILE * fp = fopen(filename.c_str(),"r");
+  return read_triangle_mesh(ext,fp,V,F);
+}
+
+template <typename DerivedV, typename DerivedF>
+IGL_INLINE bool igl::read_triangle_mesh(
+  const std::string & ext,
+  FILE * fp,
+  Eigen::PlainObjectBase<DerivedV>& V,
+  Eigen::PlainObjectBase<DerivedF>& F)
+{
+  using namespace std;
+  using namespace Eigen;
   vector<vector<double > > vV,vN,vTC,vC;
   vector<vector<int > > vF,vFTC,vFN;
   if(ext == "mesh")
   {
     // Convert extension to lower case
     MatrixXi T;
-    if(!readMESH(filename,V,T,F))
+    if(!readMESH(fp,V,T,F))
     {
       return 1;
     }
@@ -101,7 +113,7 @@ IGL_INLINE bool igl::read_triangle_mesh(
     }
   }else if(ext == "obj")
   {
-    if(!readOBJ(filename,vV,vTC,vN,vF,vFTC,vFN))
+    if(!readOBJ(fp,vV,vTC,vN,vF,vFTC,vFN))
     {
       return false;
     }
@@ -113,26 +125,25 @@ IGL_INLINE bool igl::read_triangle_mesh(
     }
   }else if(ext == "off")
   {
-    if(!readOFF(filename,vV,vF,vN,vC))
+    if(!readOFF(fp,vV,vF,vN,vC))
     {
       return false;
     }
   }else if(ext == "ply")
   {
-    if(!readPLY(filename,vV,vF,vN,vTC))
+    if(!readPLY(fp,vV,vF,vN,vTC))
     {
       return false;
     }
   }else if(ext == "stl")
   {
-    MatrixXd _;
-    if(!readSTL(filename,V,F,_))
+    if(!readSTL(fp,vV,vF,vN))
     {
       return false;
     }
   }else if(ext == "wrl")
   {
-    if(!readWRL(filename,vV,vF))
+    if(!readWRL(fp,vV,vF))
     {
       return false;
     }

+ 12 - 0
include/igl/read_triangle_mesh.h

@@ -13,6 +13,7 @@
 #  include <Eigen/Core>
 #endif
 #include <string>
+#include <cstdio>
 #include <vector>
 // History:
 //  renamed read -> read_triangle_mesh     Daniele 24 June 2014
@@ -58,6 +59,17 @@ namespace igl
     std::string & base,
     std::string & ext,
     std::string & name);
+  // Inputs:
+  //   ext  file extension
+  //   fp  pointer to already opened .ext file 
+  // Outputs:
+  //   fp  closed file
+  template <typename DerivedV, typename DerivedF>
+  IGL_INLINE bool read_triangle_mesh(
+    const std::string & ext,
+    FILE * fp,
+    Eigen::PlainObjectBase<DerivedV>& V,
+    Eigen::PlainObjectBase<DerivedF>& F);
 #endif
 }