atom feed2 messages in org.vtk.vtkusers[vtkusers] cleaning polydata preclude...
FromSent OnAttachments
Lane PhillipsMar 30, 2009 9:45 am.cpp
vidyadharMar 30, 2009 9:07 pm 
Subject:[vtkusers] cleaning polydata precludes computing curvatures
From:Lane Phillips (
Date:Mar 30, 2009 9:45:45 am

I have a 3DS model and I want to do analysis of the surface curvature. I use a vtk3DSImporter to load the model and I notice that the model is sliced into multiple meshes, so I take the vtkPolyData from each mesh and send it through a vtkCurvatures and, magically, VTK displays the curvature as color on the surface, and I can spin the model at interactive rates.

I don't want to deal with multiple meshes, so I add each vtkPolyData to a vtkAppendPolyData object, and send the output of that through the vtkCurvatures object. VTK still displays the curvatures on the surface, but now it's extremely slow to rotate. Maybe the slices cached better? However, speed is not my concern right now...

Now I have all the meshes in one vtkPolyData, but I assume they are not contiguous yet, so I run the output of the vtkAppendPolyData through a vtkCleanPolyData, hoping this will merge duplicate points and stitch the meshes together. I send the output of vtkCleanPolyData through vtkCurvatures, but now the surface is rendered in one color.

So my question is, what information is needed by vtkCurvatures that is getting destroyed by vtkCleanPolyData?

I'm attaching my code; sorry it's a mess. The important lines are 81 through 127.

Thanks, Lane

// Based on sample code from Kitware. #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkPolyDataMapper.h> #include <vtkActor.h> #include <vtkCamera.h> #include <vtkProperty.h> #include <vtkPolyDataNormals.h> #include <vtk3DSImporter.h> #include <vtkCurvatures.h> #include <vtkSmoothPolyDataFilter.h> #include <vtkJPEGReader.h> #include <vtkTexture.h> #include <vtkTextureMapToPlane.h> #include <vtkTransformTextureCoords.h> #include <vtkTriangleFilter.h> #include <vtkFeatureEdges.h> #include <vtkCommand.h> #include <vtkPNGWriter.h> #include <vtkWindowToImageFilter.h> #include <vtkAppendPolyData.h> #include <vtkCleanPolyData.h> #include <vector>

// TODO need to interactively choose the file #define MODEL_PREFIX "../../models/3ds/MDH-150" // TODO need to interactively toggle smoothing? //#define USE_SMOOTHING #define SMOOTHING_ITERATIONS 1000

// vtkCommand to takes the snapshot of the renderWindow // Press 'u' on the renWin to save the snapshot

class vtkSnapshotCallback : public vtkCommand { public: static vtkSnapshotCallback *New() { return new vtkSnapshotCallback; }

virtual void Execute(vtkObject *caller, unsigned long, void*) { vtkRenderWindowInteractor *rwi =
reinterpret_cast<vtkRenderWindowInteractor*>(caller); vtkPNGWriter *writer = vtkPNGWriter::New(); vtkWindowToImageFilter *w2iFilter = vtkWindowToImageFilter::New();

w2iFilter->SetInput(rwi->GetRenderWindow()); writer->SetInput(w2iFilter->GetOutput()); std::string prefix(MODEL_PREFIX); std::string snapshotFile = prefix + "_snapshot.png"; writer->SetFileName(snapshotFile.c_str()); writer->Write(); } };

int main(int argc, char **argv) { std::string prefix(MODEL_PREFIX); std::string modelFile = prefix + ".3ds"; std::string textureFile = prefix + ".jpg";

// Create the renderer, the render window, and the interactor. The renderer // draws into the render window, the interactor enables mouse- and // keyboard-based interaction with the data within the render window.

vtkRenderer *aRenderer = vtkRenderer::New(); vtkRenderWindow *renWin = vtkRenderWindow::New(); renWin->AddRenderer(aRenderer); vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); iren->SetRenderWindow(renWin);

vtk3DSImporter* importer = vtk3DSImporter::New(); // Change the file name to something you have on your system. // TODO We will need to make this more user-friendly. importer->SetFileName(modelFile.c_str()); importer->ComputeNormalsOn(); importer->Update(); importer->Read();

vtkAppendPolyData* wholeMesh = vtkAppendPolyData::New(); // The stone tool models seem to consist of multiple meshes, // I hope this is not a problem. vtk3DSMesh* mesh = importer->MeshList; while (mesh) { wholeMesh->AddInput(mesh->aPolyData); // Next mesh in a linked list mesh = (vtk3DSMesh*)mesh->next; } // remove redundant points vtkCleanPolyData* cleaner = vtkCleanPolyData::New(); cleaner->SetInput(wholeMesh->GetOutput()); cleaner->PointMergingOn(); cleaner->SetTolerance(0.0); cleaner->ConvertLinesToPointsOff (); cleaner->ConvertPolysToLinesOff (); cleaner->ConvertStripsToPolysOff (); // vtkPolyDataNormals* normals = vtkPolyDataNormals::New(); // normals->SetInput(cleaner->GetOutput()); // normals->SplittingOn(); // normals->ComputeCellNormalsOn();

//Reading the JPEG file and creating texture object vtkJPEGReader* jpgReader = vtkJPEGReader::New(); jpgReader->SetFileName(textureFile.c_str()); jpgReader->ReleaseDataFlagOn(); vtkTexture* texture = vtkTexture::New(); texture->SetInputConnection(jpgReader->GetOutputPort()); texture->InterpolateOff(); texture->RepeatOn(); texture->ReleaseDataFlagOn(); jpgReader->Delete();

// Code to smooth the data. #if 1 vtkCurvatures* curve = vtkCurvatures::New(); #ifdef USE_SMOOTHING vtkSmoothPolyDataFilter* smoother = vtkSmoothPolyDataFilter::New(); smoother->SetInput(cleaner->GetOutput()); smoother->SetNumberOfIterations(SMOOTHING_ITERATIONS); curve->SetInput(smoother->GetOutput()); #else curve->SetInput(cleaner->GetOutput()); #endif //curve->SetCurvatureTypeToGaussian (); //curve->SetCurvatureTypeToMean (); curve->SetCurvatureTypeToMaximum (); //curve->SetCurvatureTypeToMinimum ();

// Create a mapper and an actor for each mesh // TODO I think we are going to want to combine meshes into one, don't know how
hard that will be. vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();

mapper->SetInput(curve->GetOutput()); vtkActor* actor = vtkActor::New(); actor->SetMapper(mapper); aRenderer->AddActor(actor); #endif

// Code to map texture on to the 3D object #if 0 vtkTextureMapToPlane* tMapper = vtkTextureMapToPlane::New(); vtkPolyDataNormals* normals = vtkPolyDataNormals::New(); vtkTransformTextureCoords* transform = vtkTransformTextureCoords::New(); normals = mesh->aNormals;

tMapper->SetInputConnection(normals->GetOutputPort()); transform->SetInput(tMapper->GetOutput());

vtkPolyDataMapper* textureMapper = vtkPolyDataMapper::New(); textureMapper->SetInputConnection(transform->GetOutputPort());

vtkActor* textureActor = vtkActor::New(); textureActor->SetMapper(textureMapper); textureActor->SetTexture(texture);

aRenderer->AddActor(textureActor); #endif

#if 0 vtkTriangleFilter* triangleFilter = vtkTriangleFilter::New(); vtkPolyDataNormals* normalData = vtkPolyDataNormals::New(); normalData = mesh->aNormals;


vtkFeatureEdges* edges = vtkFeatureEdges::New(); //edges->SetInputConnection(triangleFilter->GetOutputPort()); edges->SetInputConnection(normalData->GetOutputPort()); edges->ColoringOff(); // edges->FeatureEdgesOn(); edges->SetFeatureAngle(15); //edges->BoundaryEdgesOn(); //edges->ManifoldEdgesOn(); //edges->NonManifoldEdgesOn();

vtkPolyDataMapper* edgemapper = vtkPolyDataMapper::New(); edgemapper->SetInputConnection(edges->GetOutputPort()); edgemapper->SetResolveCoincidentTopologyToPolygonOffset();

vtkActor* edgeActor = vtkActor::New(); edgeActor->SetMapper(edgemapper); edgeActor->GetProperty()->SetColor(0,0,0); edgeActor->GetProperty()->SetLineStipplePattern(4369); edgeActor->VisibilityOn();

aRenderer->AddActor(edgeActor); #endif

// It is convenient to create an initial view of the data. The FocalPoint // and Position form a vector direction. Later on (ResetCamera() method) // this vector is used to position the camera to look at the data in // this direction. vtkCamera *aCamera = vtkCamera::New(); aCamera->SetViewUp(0, 0, -1); aCamera->SetPosition(0, 1, 0); aCamera->SetFocalPoint(0, 0, 0); aCamera->ComputeViewPlaneNormal();

// Actors are added to the renderer. An initial camera view is created. // The Dolly() method moves the camera towards the FocalPoint, // thereby enlarging the image. aRenderer->SetActiveCamera(aCamera); aRenderer->ResetCamera(); aCamera->Dolly(1.5);

// Set a background color for the renderer and set the size of the // render window (expressed in pixels). aRenderer->SetBackground(1, 1, 1); renWin->SetSize(640, 480);

// Note that when camera movement occurs (as it does in the Dolly() // method), the clipping planes often need adjusting. Clipping planes // consist of two planes: near and far along the view direction. The // near plane clips out objects in front of the plane; the far plane // clips out objects behind the plane. This way only what is drawn // between the planes is actually rendered. aRenderer->ResetCameraClippingRange();

//callback to snapshot of renWin //press 'u' on the renWin to save the snapshot vtkSnapshotCallback *snapshot = vtkSnapshotCallback::New(); iren->AddObserver(vtkCommand::UserEvent, snapshot);

// Initialize the event loop and then start it. iren->Initialize(); iren->Start();

// It is important to delete all objects created previously to prevent // memory leaks. In this case, since the program is on its way to // exiting, it is not so important. But in applications it is // essential.

#ifdef USE_SMOOTHING smoother->Delete(); #endif curve->Delete(); actor->Delete(); mapper->Delete();

snapshot->Delete(); texture->Delete(); aCamera->Delete(); iren->Delete(); renWin->Delete(); aRenderer->Delete(); importer->Delete();

return 0; }

_______________________________________________ Powered by

Visit other Kitware open-source projects at

Please keep messages on-topic and check the VTK FAQ at:

Follow this link to subscribe/unsubscribe: