0

I am trying to generate triangular mesh from point clouds obtained by Terrestrial Laser Scanners. I use marching cubes algorithm of VTK library. When I visualize the generated mesh it seems as a thick surface as shown in the image below:

enter image description here

However, I was expecting to see it as the figure shown below:

enter image description here

Could you please help me about this problem? I want to generate meshes as shown in the second figure. I am looking forward to hearing from you

By the way my code is:

int main(int argc, char* argv[])
{    
    //nokta bulutu
    vtkSmartPointer<vtkSimplePointsReader> reader =
        vtkSmartPointer<vtkSimplePointsReader>::New();
    reader->SetFileName("SIL_ARKA_ENTIRE.xyz");
    reader->Update();
    vtkPolyData* polydata = reader->GetOutput();    

    FILE *Normaloku = fopen("SIL_ARKA_ENTIRE_NORMALS.xyz", "r");
    int sirasi;
    vtkSmartPointer<vtkDoubleArray> pointNormalsArray =
        vtkSmartPointer<vtkDoubleArray>::New();
    pointNormalsArray->SetNumberOfComponents(3); //3d normals (ie x,y,z)
    pointNormalsArray->SetNumberOfTuples(polydata->GetNumberOfPoints());
    double nokta_normali[3];
    for (sirasi = 0; sirasi < 652802; sirasi++)
    {
        fscanf(Normaloku, "%lf  %lf &lf", &nokta_normali[0], &nokta_normali[1], &nokta_normali[2]);
        pointNormalsArray->SetTuple(sirasi, nokta_normali);
    }
    polydata->GetPointData()->SetNormals(pointNormalsArray);
    fclose(Normaloku);
    std::cout << "eklenen işlem bitti" << std::endl;

    double isoValue;
    double bounds[6];    
    polydata->GetBounds(bounds);
    for (unsigned int i = 0; i < 6; i += 2)
    {    
        double range = bounds[i + 1] - bounds[i];
        bounds[i] = bounds[i] - .1 * range;
        bounds[i + 1] = bounds[i + 1] + .1 * range;
    }

    vtkSmartPointer<vtkImageData> volume = vtkSmartPointer<vtkImageData>::New();
    vtkSmartPointer<vtkVoxelModeller> voxelModeller = vtkSmartPointer<vtkVoxelModeller>::New();
    voxelModeller->SetSampleDimensions(20, 20, 20);
    voxelModeller->SetModelBounds(bounds);
    voxelModeller->SetScalarTypeToFloat();
    voxelModeller->SetMaximumDistance(.1);

    //voxelModeller->SetInputConnection(reader->GetOutputPort());
    voxelModeller->SetInputData(polydata);
    voxelModeller->Update();
    isoValue = 0.0001;
    volume->DeepCopy(voxelModeller->GetOutput());
    vtkSmartPointer<vtkMarchingCubes> surface = vtkSmartPointer<vtkMarchingCubes>::New();    
#if VTK_MAJOR_VERSION <= 5
    surface->SetInput(volume);
#else
    surface->SetInputData(volume);
#endif
    surface->ComputeNormalsOff();
    surface->SetValue(1, isoValue);

    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
    renderer->SetBackground(.1, .2, .3);
    vtkSmartPointer<vtkRenderWindow> renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
    renderWindow->AddRenderer(renderer);
    vtkSmartPointer<vtkRenderWindowInteractor> interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
    interactor->SetRenderWindow(renderWindow);
    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection(surface->GetOutputPort());
    mapper->ScalarVisibilityOff();    
    std::string filename = "VTK_mesh_deneme.ply";
    vtkSmartPointer<vtkPLYWriter> plyWriter = vtkSmartPointer<vtkPLYWriter>::New();
    plyWriter->SetInputConnection(surface->GetOutputPort());
    plyWriter->SetFileName(filename.c_str());
    plyWriter->Write();    
    //volume->DeepCopy(voxelModeller->GetOutput());    
    vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
    actor->SetMapper(mapper);    
    renderer->AddActor(actor);    
    renderWindow->Render();
    interactor->Start();    
    return EXIT_SUCCESS;
}
mozendi
  • 85
  • 1
  • 11

1 Answers1

0

Raise your isovalue. You set it to 0.001, instead use 0.5 for a binary image, to get the boundary between white and black pixels equidistant.

mirni
  • 695
  • 3
  • 6
  • Dear mirni thanks for the comment. I set the isovalue to 1 and thickness of the surface decreased significantly. I also increased the resolution. However, some holes occurred on the surface. Do you have any idea how can I get a surface without holes? – mozendi Apr 30 '17 at 08:21
  • Unfortunately marching cubes algorithm doesn't make any topological guarantees -- you may very well get "holes" or "handles" with noise in data. You can try to smooth the input image to get rid of noise, and or post-process the surface to patch the holes. I don't think marching cubes is the best filter for your problem -- your data seems to be point cloud not image. Try e.g. Gaussian splatter. – mirni May 06 '17 at 03:20
  • You are right my data is an unstructured point cloud. I tried to use 3D delaunay of the VTK but the resulting triangulation consists of many overlapping triangles, which is an undesired result for my case. – mozendi May 07 '17 at 12:18