ExtractClusters
Repository source: ExtractClusters
Description¶
This example extracts clusters of points. The points lie on spheres that are randomly placed. Each cluster has a different color. The number of extracted clusters may be less that the number of random spheres, if the points on one sphere are within the specified distance of points on another sphere.
Other languages
See (Cxx)
Question
If you have a question about this example, please use the VTK Discourse Forum
Code¶
ExtractClusters.py
#!/usr/bin/env python3
from pathlib import Path
# noinspection PyUnresolvedReferences
import vtkmodules.vtkInteractionStyle
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingOpenGL2
# noinspection PyUnresolvedReferences
import vtkmodules.vtkRenderingVolumeOpenGL2
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkCommonCore import vtkLookupTable, vtkMinimalStandardRandomSequence
from vtkmodules.vtkFiltersCore import vtkAppendPolyData, vtkGlyph3D
from vtkmodules.vtkFiltersPoints import vtkDensifyPointCloudFilter, vtkEuclideanClusterExtraction
from vtkmodules.vtkFiltersSources import vtkSphereSource, vtkPointSource
from vtkmodules.vtkIOGeometry import (
vtkBYUReader,
vtkOBJReader,
vtkSTLReader
)
from vtkmodules.vtkIOLegacy import vtkPolyDataReader
from vtkmodules.vtkIOPLY import vtkPLYReader
from vtkmodules.vtkIOXML import vtkXMLPolyDataReader
from vtkmodules.vtkRenderingCore import (
vtkActor,
vtkGlyph3DMapper,
vtkRenderer,
vtkRenderWindow,
vtkRenderWindowInteractor, vtkPolyDataMapper
)
def main():
colors = vtkNamedColors()
randomSequence = vtkMinimalStandardRandomSequence(seed=4355412)
# randomSequence.SetSeed(8775070)
limits = 10
radius = 0.5
append = vtkAppendPolyData()
for i in range(0, 30):
points = vtkPointSource()
points.SetNumberOfPoints(800)
points.SetRadius(2.5 * radius)
# A random position.
x = randomSequence.GetRangeValue(-limits, limits)
randomSequence.Next()
y = randomSequence.GetRangeValue(-limits, limits)
randomSequence.Next()
z = randomSequence.GetRangeValue(-limits, limits)
randomSequence.Next()
points.center = (x, y, z)
points.SetDistributionToShell()
append.AddInputConnection(points.GetOutputPort())
cluster = vtkEuclideanClusterExtraction(radius=radius, color_clusters=True)
append >> cluster
# cluster.SetInputConnection(append.GetOutputPort())
cluster.SetExtractionModeToAllClusters()
# cluster.SetRadius(radius)
# cluster.ColorClustersOn()
cluster.update()
print(f'Found {cluster.number_of_extracted_clusters} clusters within radius {radius}')
# Create a lookup table to map point data to colors.
lut = vtkLookupTable()
tableSize = cluster.number_of_extracted_clusters
lut.SetNumberOfTableValues(tableSize)
lut.Build()
# Fill in the lookup table.
for i in range(0, tableSize):
r = randomSequence.GetRangeValue(0.25, 1.0)
randomSequence.Next()
g = randomSequence.GetRangeValue(0.25, 1.0)
randomSequence.Next()
b = randomSequence.GetRangeValue(0.25, 1.0)
randomSequence.Next()
lut.SetTableValue(i, r, g, b, 1.0)
sphere = vtkSphereSource(radius=radius / 2.0)
# sphere.SetRadius(radius / 2.0)
glyphs = vtkGlyph3D(input_connection=cluster.output_port, source_connection=sphere.output_port, scaling=False)
# glyphs.SetInputConnection(cluster.GetOutputPort())
# glyphs.SetSourceConnection(sphere.GetOutputPort())
# glyphs.ScalingOff()
glyphs.Update()
mapper = vtkPolyDataMapper(scalar_range=(0, tableSize - 1), lookup_table=lut)
glyphs >> mapper
actor = vtkActor(mapper=mapper)
# Create the graphics stuff.
ren1 = vtkRenderer(background=colors.GetColor3d('SlateGray'))
renWin = vtkRenderWindow(size=(640, 512), window_name='ExtractClusters')
renWin.AddRenderer(ren1)
iren = vtkRenderWindowInteractor()
iren.render_window = renWin
# Add the actors to the renderer.
ren1.AddActor(actor)
# Generate an interesting view.
ren1.ResetCamera()
ren1.active_camera.Azimuth(120)
ren1.active_camera.Elevation(30)
ren1.active_camera.Dolly(1.5)
ren1.ResetCameraClippingRange()
renWin.Render()
iren.Initialize()
iren.Start()
if __name__ == '__main__':
main()