Search code examples
c++vtk

vtkSTLReader reads only files in folder of execution


NOTE: The question is invalid, I made an entirely different mistake, see edit at the end.

I want to simply read a STL file using the vtkSTLReader class. My code for that looks like this:

        vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
        reader->SetFileName(path.c_str());
        reader->Update();
        vtkSmartPointer<vtkPolyData> poly_data = reader->GetOutput();

and then the code proceeds to display the poly data.

This works to some degree. The code as it is will ignore anything in path except for the name of the file, and then look for that file at wherever I execute my program.

For example, if I go like path = /home/local/users/myusername/file.stl, have the program located at /some_path/somefolder/myprogram while calling it in the console being in /some_path/, it will only work if (and only if) there is a copy of the file at /some_path/file.stl.
Should I instead execute the program from within /some_path/somefolder, it will work only if there is /some_path/somefolder/file.stl.

I even went and tried what happens if I add a line of code

        path = "/dsgsdmklgmoeg/" + path;

and the outcome stays exactly the same.

As my paths suggest, I work under linux.
I tried stating an absolute path as above, a relative path from the place of execution and also a relative path from the executable (just in case).
For the relative path, I tried all sorts of variants of what I think it might want, with a leading ./, with and without a leading /.
For the absolute path, I tried out replacing all slashes with backslashes, on the idea that it might use windows style paths.

I realize that a quick fix would be to simply copy the file to the required location, but that is surely not a permanent solution.

Has anybody had some experience with that? Is this some peculiarity of vtk?
If it is of importance, I use vtk 5.6.1 (and can't switch to a higher version due to some compatibility requirements).

Edit: I realized that I made a very simple mistake, instead of path.c_str() I had file.c_str() in my original code, with file being a variable from which path is assembled. I did not made the mistake when typing the code above, making the question invalid.


Solution

  • Out of curiosity, I digged a bit into github.

    This is what I found:

    VTK/vtkSTLReader.cxx at v5.6.1 (int vtkSTLReader::RequestData(), lines 96 ... 110):

      if (!this->FileName || (this->FileName && (0==strlen(this->FileName))))
        {
        vtkErrorMacro(<<"A FileName must be specified.");
        this->SetErrorCode( vtkErrorCode::NoFileNameError );
        return 0;
        }
    
      // Initialize
      //
      if ((fp = fopen(this->FileName, "r")) == NULL)
        {
        vtkErrorMacro(<< "File " << this->FileName << " not found");
        this->SetErrorCode( vtkErrorCode::CannotOpenFileError );
        return 0;
        }
    

    VTK/vtkSTLReader.h at v5.6.1 (lines 57 ... 60):

      // Description:
      // Specify file name of stereo lithography file.
      vtkSetStringMacro(FileName);
      vtkGetStringMacro(FileName);
    

    VTK/vtkSetGet.h at v5.6.1 (lines 88 ... 122):

    //
    // Set character string.  Creates member Set"name"() 
    // (e.g., SetFilename(char *));
    //
    #define vtkSetStringMacro(name) \
    virtual void Set##name (const char* _arg) \
      { \
      vtkDebugMacro(<< this->GetClassName() << " (" << this << "): setting " << #name " to " << (_arg?_arg:"(null)") ); \
      if ( this->name == NULL && _arg == NULL) { return;} \
      if ( this->name && _arg && (!strcmp(this->name,_arg))) { return;} \
      if (this->name) { delete [] this->name; } \
      if (_arg) \
        { \
        size_t n = strlen(_arg) + 1; \
        char *cp1 =  new char[n]; \
        const char *cp2 = (_arg); \
        this->name = cp1; \
        do { *cp1++ = *cp2++; } while ( --n ); \
        } \
       else \
        { \
        this->name = NULL; \
        } \
      this->Modified(); \
      } 
    
    //
    // Get character string.  Creates member Get"name"() 
    // (e.g., char *GetFilename());
    //
    #define vtkGetStringMacro(name) \
    virtual char* Get##name () { \
      vtkDebugMacro(<< this->GetClassName() << " (" << this << "): returning " << #name " of " << (this->name?this->name:"(null)")); \
      return this->name; \
      } 
    

    Looking at this code (which IMHO is the relevant code for OPs issue), I cannot find any hint that directories are stripped from a file path given by SetFileName().

    I've no idea what actually could cause the issue of OP that only files in the current directory are considered. However, I struggle to believe that VTK can be blamed for this.

    So, I would recommend to search further above and below:

    • above: Is the provided path in SetFileName() correct? (the easy part)
    • below: Is this strange behavior caused by fopen() (or something which is called in fopen())?