ClusteredVTK
VTKExamples/Cxx/InfoVis/ClusteredVTK
Code¶
ClusteredVTK.cxx
//https://www.vtk.org/pipermail/vtkusers/2011-March/066675.html #include <vtkSmartPointer.h> #include <vtkActor.h> #include <vtkChartXY.h> #include <vtkDoubleArray.h> #include <vtkFloatArray.h> #include <vtkIntArray.h> #include <vtkInteractorStyleTrackballCamera.h> #include <vtkKMeansStatistics.h> #include <vtkLookupTable.h> #include <vtkMultiBlockDataSet.h> #include <vtkNamedColors.h> #include <vtkOrientationMarkerWidget.h> #include <vtkPlotPoints.h> #include <vtkPointData.h> #include <vtkPoints.h> #include <vtkPolyData.h> #include <vtkPolyDataMapper.h> #include <vtkPolyDataReader.h> #include <vtkPolyDataWriter.h> #include <vtkProperty.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkRenderer.h> #include <vtkTable.h> #include <vtkUnstructuredGridReader.h> #include <vtkVertexGlyphFilter.h> #include <vtkXMLPolyDataWriter.h> #include <sstream> int main(int argc, char* argv[]) { // Get the points into the format which is needed for KMeans clustering auto point = vtkSmartPointer<vtkPolyData>::New(); auto reader = vtkSmartPointer<vtkPolyDataReader>::New(); reader->SetFileName(argv[1]); reader->Update(); point = reader->GetOutput(); auto inputData = vtkSmartPointer<vtkTable>::New(); for (auto c = 0; c < 3; ++c) { std::stringstream colName; colName << "coord " << c; auto doubleArray = vtkSmartPointer<vtkDoubleArray>::New(); doubleArray->SetNumberOfComponents(1); doubleArray->SetName(colName.str().c_str()); doubleArray->SetNumberOfTuples(point->GetNumberOfPoints()); for (auto r = 0; r < point->GetNumberOfPoints(); ++r) { double p[3]; point->GetPoint(r, p); doubleArray->SetValue(r, p[c]); } inputData->AddColumn(doubleArray); } auto kMeansStatistics = vtkSmartPointer<vtkKMeansStatistics>::New(); kMeansStatistics->SetInputData(vtkStatisticsAlgorithm::INPUT_DATA, inputData); kMeansStatistics->SetColumnStatus(inputData->GetColumnName(0), 1); kMeansStatistics->SetColumnStatus(inputData->GetColumnName(1), 1); kMeansStatistics->SetColumnStatus(inputData->GetColumnName(2), 1); kMeansStatistics->RequestSelectedColumns(); kMeansStatistics->SetAssessOption(true); kMeansStatistics->SetDefaultNumberOfClusters(6); kMeansStatistics->Update(); //Group the points according to ID number auto clusterArray = vtkSmartPointer<vtkIntArray>::New(); clusterArray->SetNumberOfComponents(1); clusterArray->SetName("ClusterId"); for (auto r = 0; r < kMeansStatistics->GetOutput()->GetNumberOfRows(); r++) { auto v = kMeansStatistics->GetOutput()->GetValue(r, kMeansStatistics->GetOutput()->GetNumberOfColumns() - 1); clusterArray->InsertNextValue(v.ToInt()); } // Create a lookup table to map cell data to colors auto lut = vtkSmartPointer<vtkLookupTable>::New(); auto tableSize = kMeansStatistics->GetDefaultNumberOfClusters() + 1; lut->SetNumberOfTableValues(tableSize); lut->Build(); std::cout << tableSize << std::endl; std::cout << kMeansStatistics << std::endl; // Fill in a few known colors, the rest will be generated if needed //ColorCells tutorial https://lorensen.github.io/VTKExamples/site/Cxx/PolyData/ColorCells/ auto colors = vtkSmartPointer<vtkNamedColors>::New(); lut->SetTableValue(0, colors->GetColor4d("Black").GetData()); lut->SetTableValue(1, colors->GetColor4d("Banana").GetData()); lut->SetTableValue(2, colors->GetColor4d("Tomato").GetData()); lut->SetTableValue(3, colors->GetColor4d("Peacock").GetData()); lut->SetTableValue(4, colors->GetColor4d("Lavender").GetData()); lut->SetTableValue(5, colors->GetColor4d("Flesh").GetData()); lut->SetTableValue(6, colors->GetColor4d("Raspberry").GetData()); lut->SetTableValue(7, colors->GetColor4d("Salmon").GetData()); lut->SetTableValue(8, colors->GetColor4d("Mint").GetData()); lut->SetTableValue(9, colors->GetColor4d("Wheat").GetData()); auto polydata = vtkSmartPointer<vtkPolyData>::New(); polydata = point; polydata->GetPointData()->AddArray(clusterArray); polydata->GetPointData()->SetScalars(clusterArray); // Display auto glyphFilter = vtkSmartPointer<vtkVertexGlyphFilter>::New(); glyphFilter->SetInputData(polydata); glyphFilter->Update(); // Create a mapper and actor auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper->SetInputConnection(glyphFilter->GetOutputPort()); mapper->SetScalarRange(0, tableSize); mapper->SetLookupTable(lut); auto actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); actor->GetProperty()->SetPointSize(5); // Create a renderer, render window, and interactor auto renderer = vtkSmartPointer<vtkRenderer>::New(); auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New(); renderWindow->AddRenderer(renderer); renderWindow->SetSize(640, 480); auto renderWindowInteractor = vtkSmartPointer<vtkRenderWindowInteractor>::New(); renderWindowInteractor->SetRenderWindow(renderWindow); // Add the actor to the scene renderer->AddActor(actor); renderer->SetBackground(colors->GetColor3d("SlateGray").GetData()); auto style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New(); renderWindowInteractor->SetInteractorStyle(style); // Render and interact renderWindow->Render(); renderWindowInteractor->Start(); return EXIT_SUCCESS; }
CMakeLists.txt¶
cmake_minimum_required(VERSION 2.8) PROJECT(ClusteredVTK) find_package(VTK REQUIRED) include(${VTK_USE_FILE}) add_executable(ClusteredVTK MACOSX_BUNDLE ClusteredVTK.cxx ) target_link_libraries(ClusteredVTK ${VTK_LIBRARIES})
Download and Build ClusteredVTK¶
Click here to download ClusteredVTK and its CMakeLists.txt file. Once the tarball ClusteredVTK.tar has been downloaded and extracted,
cd ClusteredVTK/build
If VTK is installed:
cmake ..
If VTK is not installed but compiled on your system, you will need to specify the path to your VTK build:
cmake -DVTK_DIR:PATH=/home/me/vtk_build ..
Build the project:
make
and run it:
./ClusteredVTK
WINDOWS USERS
Be sure to add the VTK bin directory to your path. This will resolve the VTK dll's at run time.