<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<style type="text/css" style="display:none;"><!-- P {margin-top:0;margin-bottom:0;} --></style>
</head>
<body dir="ltr">
<div id="divtagdefaultwrapper" style="font-size:12pt;color:#000000;font-family:Calibri,Helvetica,sans-serif;" dir="ltr">
<p style="margin-top:0;margin-bottom:0">Hi, </p>
<p style="margin-top:0;margin-bottom:0">I would like to show my polydata with points and mark with colours after the KmeansClustering process.</p>
<p style="margin-top:0;margin-bottom:0">However, I could only get the values of the points without the visualization of the data.</p>
<p style="margin-top:0;margin-bottom:0">Can anyone please advice?</p>
<p style="margin-top:0;margin-bottom:0">Thank you so much.</p>
<p style="margin-top:0;margin-bottom:0"><br>
</p>
<p style="margin-top:0;margin-bottom:0">Polly</p>
<p style="margin-top:0;margin-bottom:0">--------------------------------------------------------------------------------------</p>
<p style="margin-top:0;margin-bottom:0">My code is as below:</p>
<p style="margin-top:0;margin-bottom:0"></p>
<div>int main(int argc, char* argv[])</div>
<div>{</div>
<div><span style="white-space:pre"></span>// Get the points into the format needed for KMeans</div>
<div><span style="white-space:pre"></span></div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkPolyData> point =</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkPolyData>::New();</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkPolyDataReader> reader =</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkPolyDataReader>::New();</div>
<div><span style="white-space:pre"></span>reader->SetFileName(argv[1]);</div>
<div><span style="white-space:pre"></span>reader->Update();</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>point = reader->GetOutput();</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkTable> inputData =</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkTable>::New();</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>for (int c = 0; c < 3; ++c)</div>
<div><span style="white-space:pre"></span>{</div>
<div><span style="white-space:pre"></span>std::stringstream colName;</div>
<div><span style="white-space:pre"></span>colName << "coord " << c;</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkDoubleArray> doubleArray =</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkDoubleArray>::New();</div>
<div><span style="white-space:pre"></span>doubleArray->SetNumberOfComponents(1);</div>
<div><span style="white-space:pre"></span>doubleArray->SetName(colName.str().c_str());</div>
<div><span style="white-space:pre"></span>doubleArray->SetNumberOfTuples(point->GetNumberOfPoints());</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>for (int r = 0; r < point->GetNumberOfPoints(); ++r)</div>
<div><span style="white-space:pre"></span>{</div>
<div><span style="white-space:pre"></span>double p[3];</div>
<div><span style="white-space:pre"></span>point->GetPoint(r, p);</div>
<div><span style="white-space:pre"></span>doubleArray->SetValue(r, p[c]);</div>
<div><span style="white-space:pre"></span>}</div>
<div><span style="white-space:pre"></span>inputData->AddColumn(doubleArray);</div>
<div><span style="white-space:pre"></span>}</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkKMeansStatistics> kMeansStatistics =</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkKMeansStatistics>::New();</div>
<div><br>
</div>
<div>#if VTK_MAJOR_VERSION <= 5</div>
<div><span style="white-space:pre"></span>kMeansStatistics->SetInput(vtkStatisticsAlgorithm::INPUT_DATA, inputData);</div>
<div>#else</div>
<div><span style="white-space:pre"></span>kMeansStatistics->SetInputData(vtkStatisticsAlgorithm::INPUT_DATA, inputData);</div>
<div>#endif</div>
<div><span style="white-space:pre"></span>kMeansStatistics->SetColumnStatus(inputData->GetColumnName(0), 1);</div>
<div><span style="white-space:pre"></span>kMeansStatistics->SetColumnStatus(inputData->GetColumnName(1), 1);</div>
<div><span style="white-space:pre"></span>kMeansStatistics->SetColumnStatus(inputData->GetColumnName(2), 1);</div>
<div><span style="white-space:pre"></span>kMeansStatistics->RequestSelectedColumns();</div>
<div><span style="white-space:pre"></span>kMeansStatistics->SetAssessOption(true);</div>
<div><span style="white-space:pre"></span>kMeansStatistics->SetDefaultNumberOfClusters(5);</div>
<div><span style="white-space:pre"></span>//kMeansStatistics->SetMaxNumIterations(1);</div>
<div><span style="white-space:pre"></span>kMeansStatistics->Update();</div>
<div><span style="white-space:pre"></span></div>
<div><span style="white-space:pre"></span>//double mean0[3];</div>
<div><span style="white-space:pre"></span>//kMeansStatistics->GetMean(0, mean0);</div>
<div><span style="white-space:pre"></span></div>
<div><span style="white-space:pre"></span>// Display the results</div>
<div><span style="white-space:pre"></span>kMeansStatistics->GetOutput()->Dump();</div>
<div><span style="white-space:pre"></span></div>
<div><span style="white-space:pre"></span>//Group the points according to ID number</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkIntArray> clusterArray =</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkIntArray>::New();</div>
<div><span style="white-space:pre"></span>clusterArray->SetNumberOfComponents(1);</div>
<div><span style="white-space:pre"></span>clusterArray->SetName("ClusterId");</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>for (int r = 0; r < kMeansStatistics->GetOutput()->GetNumberOfRows(); r++)</div>
<div><span style="white-space:pre"></span>{</div>
<div><span style="white-space:pre"></span>vtkVariant v = kMeansStatistics->GetOutput()->GetValue(r, kMeansStatistics->GetOutput()->GetNumberOfColumns() - 1);</div>
<div><span style="white-space:pre"></span>//std::cout << "Point " << r << " is in cluster " << v.ToInt() << std::endl;</div>
<div><span style="white-space:pre"></span>clusterArray->InsertNextValue(v.ToInt());</div>
<div><span style="white-space:pre"></span>}<span style="white-space:pre"> </span>
</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>// Create a lookup table to map cell data to colors</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkLookupTable> lut =</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkLookupTable>::New();</div>
<div><span style="white-space:pre"></span>int tableSize = (kMeansStatistics + 1, 10);</div>
<div><span style="white-space:pre"></span>lut->SetNumberOfTableValues(tableSize);</div>
<div><span style="white-space:pre"></span>lut->Build();</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>// Fill in a few known colors, the rest will be generated if needed </div>
<div><span style="white-space:pre"></span>//ColorCells tutorial https://lorensen.github.io/VTKExamples/site/Cxx/PolyData/ColorCells/</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkNamedColors> colors =</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkNamedColors>::New();</div>
<div><span style="white-space:pre"></span>lut->SetTableValue(0, colors->GetColor4d("Black").GetData());</div>
<div><span style="white-space:pre"></span>lut->SetTableValue(1, colors->GetColor4d("Banana").GetData());</div>
<div><span style="white-space:pre"></span>lut->SetTableValue(2, colors->GetColor4d("Tomato").GetData());</div>
<div><span style="white-space:pre"></span>lut->SetTableValue(3, colors->GetColor4d("Peacock").GetData());</div>
<div><span style="white-space:pre"></span>lut->SetTableValue(4, colors->GetColor4d("Lavender").GetData());</div>
<div></div>
<div><br>
</div>
<div><span style="white-space:pre"></span>// Output the cluster centers</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>vtkMultiBlockDataSet* outputMetaDS = vtkMultiBlockDataSet::SafeDownCast(kMeansStatistics->GetOutputDataObject(vtkStatisticsAlgorithm::OUTPUT_MODEL));</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkTable> outputMeta = vtkTable::SafeDownCast(outputMetaDS->GetBlock(0));</div>
<div><span style="white-space:pre"></span>//vtkSmartPointer<vtkTable> outputMeta = vtkTable::SafeDownCast( outputMetaDS->GetBlock( 1 ) );</div>
<div><span style="white-space:pre"></span>vtkDoubleArray* coord0 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("coord 0"));</div>
<div><span style="white-space:pre"></span>vtkDoubleArray* coord1 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("coord 1"));</div>
<div><span style="white-space:pre"></span>vtkDoubleArray* coord2 = vtkDoubleArray::SafeDownCast(outputMeta->GetColumnByName("coord 2"));</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>for (unsigned int i = 0; i < coord0->GetNumberOfTuples(); ++i)</div>
<div><span style="white-space:pre"></span>{</div>
<div><span style="white-space:pre"></span>std::cout << coord0->GetValue(i) << " " << coord1->GetValue(i) << " " << coord2->GetValue(i) << std::endl;</div>
<div><span style="white-space:pre"></span></div>
<div><span style="white-space:pre"></span>}</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkPolyData> polydata =</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkPolyData>::New();<span style="white-space:pre">
</span></div>
<div><span style="white-space:pre"></span>//polydata->SetPoints(point);</div>
<div><span style="white-space:pre"></span>polydata->GetPointData()->AddArray(clusterArray);</div>
<div><span style="white-space:pre"></span>polydata->GetPointData()->SetScalars(clusterArray);</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>// Display</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkVertexGlyphFilter> glyphFilter =</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkVertexGlyphFilter>::New();</div>
<div>#if VTK_MAJOR_VERSION <= 5</div>
<div><span style="white-space:pre"></span>glyphFilter->SetInputConnection(polydata->GetProducerPort());</div>
<div>#else</div>
<div><span style="white-space:pre"></span>glyphFilter->SetInputData(polydata);</div>
<div>#endif</div>
<div><span style="white-space:pre"></span>glyphFilter->Update();</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>// Create a mapper and actor</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkPolyDataMapper> mapper =</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkPolyDataMapper>::New();</div>
<div><span style="white-space:pre"></span>mapper->SetInputConnection(glyphFilter->GetOutputPort());</div>
<div><span style="white-space:pre"></span>mapper->SetScalarRange(0, tableSize - 1);</div>
<div><span style="white-space:pre"></span>mapper->SetLookupTable(lut);</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkActor> actor =</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkActor>::New();</div>
<div><span style="white-space:pre"></span>actor->SetMapper(mapper);<span style="white-space:pre">
</span></div>
<div><span style="white-space:pre"></span>actor->GetProperty()->SetPointSize(5);</div>
<div><br>
</div>
<div><span style="white-space:pre"></span></div>
<div><span style="white-space:pre"></span>// Create a renderer, render window, and interactor</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkRenderer> renderer =</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkRenderer>::New();</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkRenderWindow> renderWindow =</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkRenderWindow>::New();</div>
<div><span style="white-space:pre"></span>renderWindow->AddRenderer(renderer);</div>
<div><span style="white-space:pre"></span>renderWindow->SetSize(800, 800);</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkRenderWindowInteractor>::New();</div>
<div><span style="white-space:pre"></span>renderWindowInteractor->SetRenderWindow(renderWindow);</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>// Add the actor to the scene</div>
<div><span style="white-space:pre"></span>renderer->AddActor(actor);</div>
<div><span style="white-space:pre"></span>renderer->SetBackground(colors->GetColor3d("SlateGray").GetData());</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkInteractorStyleTrackballCamera> style =</div>
<div><span style="white-space:pre"></span>vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();</div>
<div><span style="white-space:pre"></span>renderWindowInteractor->SetInteractorStyle(style);</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>// Render and interact</div>
<div><span style="white-space:pre"></span>renderWindow->Render();</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>vtkWindowToImageFilter *windowToImageFilter = vtkWindowToImageFilter::New();</div>
<div><span style="white-space:pre"></span>windowToImageFilter->SetInput(renderWindow);</div>
<div><span style="white-space:pre"></span>windowToImageFilter->Update();</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>vtkJPEGWriter *writer = vtkJPEGWriter::New();</div>
<div><span style="white-space:pre"></span>writer->SetInputConnection(windowToImageFilter->GetOutputPort());</div>
<div><span style="white-space:pre"></span>writer->SetFileName("10nosepoints.jpg");</div>
<div><span style="white-space:pre"></span>writer->Write();</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>renderWindowInteractor->Start();</div>
<div><br>
</div>
<div><span style="white-space:pre"></span>return EXIT_SUCCESS;</div>
<div>}</div>
<br>
<p></p>
</div>
</body>
</html>