1

I am trying to put the example provided by VTK here into a C++ class. This example reads an STL file and visualizes it in a window.

Below is my code for which I get no compiler or run-time error. My input STL file is read correctly but my code exits without producing any visualization of the STL object.

In my C++ class, I organized the VTK example code by separating the reader from the visualizer and putting them into two functions in the class. The visualizer uses a mapper, actor, and a renderer to visualize the STL object. However, I am not able to get the code to visualize my STL object.

The only way I am able to get my C++ class to work is to copy the codes of the function visualize into my readSTL function, then I can see the window with my STL object rendered in it.

Could someone kindly give me some hints how I can perform the visualization in a separate function in the class?

#include <vtkPolyData.h>
#include <vtkSTLReader.h>
#include <vtkSmartPointer.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>


class triangulation
{
public:
    vtkIdType numberOfFaces;
    // Constructor
    triangulation(void);
    triangulation(std::string filename);
    void setFilename(std::string filename);
    std::string getFilename(void);

    // Getters
    vtkSmartPointer<vtkPolyData> getMesh(void);
    vtkSmartPointer<vtkCellArray> getPolys(void);
    vtkSmartPointer<vtkPoints>    getPoints(void);
    vtkSmartPointer<vtkDataArray> getDataArray(void);
    vtkIdType getNumberofFaces(void);

    // Visualizer
    void visualize(void);

    // Reader
    void readSTL(void);

private:
    std::string stlFilename;
    vtkSmartPointer<vtkPolyData> mesh;
    vtkSmartPointer<vtkSTLReader> reader;
    vtkSmartPointer<vtkCellArray> polys;
    vtkSmartPointer<vtkPoints>    points;
    vtkSmartPointer<vtkDataArray> dataArray;
};

triangulation::triangulation()
{
    //
}

triangulation::triangulation(std::string filename)
{
    setFilename(filename);
}


void triangulation::readSTL(void)
{
    vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
    reader->SetFileName(stlFilename.c_str());
    reader->Update();
    mesh = reader->GetOutput();
    polys = mesh->GetPolys();
    points = mesh->GetPoints();
    numberOfFaces = mesh->GetNumberOfCells();
}

void triangulation::setFilename(std::string filename)
{
    stlFilename = filename;
}

std::string triangulation::getFilename(void)
{
    return stlFilename;
}

vtkSmartPointer<vtkPolyData> triangulation::getMesh(void)
{
    return mesh;
}

vtkSmartPointer<vtkCellArray> triangulation::getPolys(void)
{
    return polys;
}

vtkIdType triangulation::getNumberofFaces(void)
{
    return numberOfFaces;
}

vtkSmartPointer<vtkPoints> triangulation::getPoints(void)
{
    return points;
}

vtkSmartPointer<vtkDataArray> triangulation::getDataArray(void)
{
    return dataArray;
}

void triangulation::visualize(void)
{
    // Visualize
    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection(reader->GetOutputPort());

    vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
    actor->SetMapper(mapper);

    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
    vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->AddRenderer(renderer);
    vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    renderWindowInteractor->SetRenderWindow(renderWindow);

    renderer->AddActor(actor);
    renderer->SetBackground(.3, .6, .3); // Background color green

    renderWindow->Render();
    renderWindowInteractor->Start();
}



int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        cout << "Required parameters: Filename" << endl;
        return EXIT_FAILURE;
    }

    std::string inputFilename = argv[1];
    cout << inputFilename << endl;
    triangulation *tr = new triangulation(inputFilename);
    tr->readSTL();
    cout << "Number of Faces = " << tr->getNumberofFaces() << endl;

    vtkSmartPointer<vtkPolyData> mesh = tr->getMesh();
    vtkSmartPointer<vtkCellArray> polys = tr->getPolys();
    vtkSmartPointer<vtkPoints>    points = tr->getPoints();
    vtkSmartPointer<vtkDataArray> data = tr->getDataArray();
    //mesh->Print(cout);
    // polys->Print(cout);
    // points->Print(cout);
    // data->Print(cout);
    tr->visualize();


    delete tr;
    return EXIT_SUCCESS;
}

Here is my STL object that I used to test my code:

"myobject.stl":

solid STL generated by MeshLab
  facet normal -4.919344e-01  2.986337e-01  8.178133e-01
    outer loop
      vertex  -1.265660e+00  4.756133e+00  1.702858e-01
      vertex  -1.649185e+00  4.810246e+00 -8.017353e-02
      vertex  -1.602208e+00  4.484959e+00  6.686619e-02
    endloop
  endfacet
  facet normal -5.898571e-01  2.603427e-01  7.643889e-01
    outer loop
      vertex  -1.861084e+00  4.821712e+00 -2.475956e-01
      vertex  -1.602208e+00  4.484959e+00  6.686619e-02
      vertex  -1.649185e+00  4.810246e+00 -8.017353e-02
    endloop
  endfacet
  facet normal -6.398674e-01  2.007942e-01  7.417893e-01
    outer loop
      vertex  -1.861084e+00  4.821712e+00 -2.475956e-01
      vertex  -1.845646e+00  4.479523e+00 -1.416520e-01
      vertex  -1.602208e+00  4.484959e+00  6.686619e-02
    endloop
  endfacet
  facet normal -6.901410e-01  1.854371e-01  6.995131e-01
    outer loop
      vertex  -2.043903e+00  4.838252e+00 -4.323493e-01
      vertex  -1.845646e+00  4.479523e+00 -1.416520e-01
      vertex  -1.861084e+00  4.821712e+00 -2.475956e-01
    endloop
  endfacet
endsolid vcg
afp_2008
  • 1,940
  • 1
  • 19
  • 46

1 Answers1

4

Your code will work if you simply replace the following line in triangulation::readSTL():

// Problem: local variable 'reader' shadows class member 'reader'.
vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
// Solution: 
reader = vtkSmartPointer<vtkSTLReader>::New();

Because the class-member reader remains unintialized, the application crashes with a segfault when it is being accessed in triangulation::visualize().

Hint: you probably would not have encountered this problem if you consequently used this-> or a naming prefix (m_ or _) to refer to class members. See this SO post for some explanations.

normanius
  • 8,629
  • 7
  • 53
  • 83