# Vtk point cloud display multiple points (cluster)

**URL:** https://discourse.vtk.org/t/vtk-point-cloud-display-multiple-points-cluster/10162
**Category:** Support
**Tags:** python
**Created:** [December 11, 2022, 6:22pm UTC](https://discourse.vtk.org/t/vtk-point-cloud-display-multiple-points-cluster/10162 "2022-12-11T18:22:10Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![nikhilmakkar2345](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/n/f07891/32.png) [@nikhilmakkar2345](https://discourse.vtk.org/u/nikhilmakkar2345)
#### Post date: [December 11, 2022, 6:22pm UTC](https://discourse.vtk.org/t/vtk-point-cloud-display-multiple-points-cluster/10162/1 "2022-12-11T18:22:10Z")

</div>

Cannot visualize the points around one of the selected points in point cloud. Not sure what I am missing. I used the below code. What it does is just takes a pointcloud and convert it into polydata and visualize it. After visualizing the pointcloud, I use mouse to select one point and calculate points around that particular point in a given radius. I am able to calculate those points but not able to visualize those. Also moving further I select 1000 random points in data and calculate their clusters too, calculate Hausdorff distances of each with original cluster and visualize the minimum distance cluster. In all this I am not able to visualize any cluster.

```auto
import vtk
import numpy as np
import open3d as o3d
import math
from numpy import random
from scipy.spatial.distance import directed_hausdorff

import vtkmodules.vtkRenderingOpenGL2
from vtkmodules.vtkCommonColor import vtkNamedColors
from vtkmodules.vtkCommonCore import vtkIdTypeArray
from vtkmodules.vtkCommonDataModel import (
    vtkSelection,
    vtkSelectionNode,
    vtkUnstructuredGrid
)
from vtkmodules.vtkFiltersCore import vtkTriangleFilter
from vtkmodules.vtkFiltersExtraction import vtkExtractSelection
from vtkmodules.vtkFiltersSources import vtkPlaneSource
from vtkmodules.vtkInteractionStyle import vtkInteractorStyleTrackballCamera
from vtkmodules.vtkRenderingCore import (
    vtkActor,
    vtkCellPicker,
    vtkDataSetMapper,
    vtkPolyDataMapper,
    vtkRenderWindow,
    vtkRenderWindowInteractor,
    vtkRenderer
)

class VtkPointCloud:

    def __init__ (self, zMin=-10.0, zMax=10.0, maxNumPoints=2e6):
        # c = vtkNamedColors()
        self.maxNumPoints = maxNumPoints
        self.vtkPolyData = vtk.vtkPolyData()
        self.clearPoints()
        mapper = vtk.vtkPolyDataMapper()
        mapper.SetInputData(self.vtkPolyData)
        mapper.SetColorModeToDefault()
        mapper.SetScalarRange(zMin, zMax)
        mapper.SetScalarVisibility(1)
        self.vtkActor = vtk.vtkActor()
        # self.vtkActor.GetProperty().SetColor(1,1,1)
        # self.vtkActor.GetProperty().SetColor(c.GetColor3d('Yellow'))
        self.vtkActor.SetMapper(mapper)

    def addPoint(self, point):
        if self.vtkPoints.GetNumberOfPoints() < self.maxNumPoints:
            pointId = self.vtkPoints.InsertNextPoint(point[:])
            self.vtkDepth.InsertNextValue(point[2])
            self.vtkCells.InsertNextCell(1)
            self.vtkCells.InsertCellPoint(pointId)
        else:
            r = random.randint(0, self.maxNumPoints)
            self.vtkPoints.SetPoint(r, point[:])
        self.vtkCells.Modified()
        self.vtkPoints.Modified()
        self.vtkDepth.Modified()

    def clearPoints(self):
        self.vtkPoints = vtk.vtkPoints()
        self.vtkCells = vtk.vtkCellArray()
        self.vtkDepth = vtk.vtkDoubleArray()
        self.vtkDepth.SetName('DepthArray')
        self.vtkPolyData.SetPoints(self.vtkPoints)
        self.vtkPolyData.SetVerts(self.vtkCells)
        self.vtkPolyData.GetPointData().SetScalars(self.vtkDepth)
        self.vtkPolyData.GetPointData().SetActiveScalars('DepthArray')

# Catch mouse events
class MouseInteractorStyle(vtkInteractorStyleTrackballCamera):
    def __init__ (self, data):
        self.AddObserver('LeftButtonPressEvent', self.left_button_press_event)
        self.AddObserver('RightButtonPressEvent', self.right_button_press_event)
        self.data = data
        self.selected_mapper = vtkDataSetMapper()
        self.selected_actor = vtkActor()

        self.selected_mapper2 = vtkDataSetMapper()
        self.selected_actor2 = vtkActor()

        self.vtk_list = vtk.vtkIdList()
        self.locator = vtk.vtkPointLocator()
        self.locator.SetDataSet(self.data)
        self.locator.BuildLocator()

        self.colors = vtkNamedColors()
    def left_button_press_event(self, obj, event):
                

        pos = self.GetInteractor().GetEventPosition()

        picker = vtkCellPicker()
        picker.SetTolerance(0.001)

        # Pick from this location.
        picker.Pick(pos[0], pos[1], 0, self.GetDefaultRenderer())

        world_position = picker.GetPickPosition()
        print(f'Cell id is: {picker.GetCellId()}')
        
        # print(world_position)

        self.locator.FindPointsWithinRadius(0.02,world_position, self.vtk_list)
        print(self.vtk_list)

        if picker.GetCellId() != -1:
            print(f'Pick position is: ({world_position[0]:.6g}, {world_position[1]:.6g}, {world_position[2]:.6g})')

            ids = vtkIdTypeArray()
            ids.SetNumberOfComponents(1)
            ids.InsertNextValue(picker.GetCellId())
            # print(ids,'\n')

            selection_node = vtkSelectionNode()
            selection_node.SetFieldType(vtkSelectionNode.CELL)
            selection_node.SetContentType(vtkSelectionNode.INDICES)
            selection_node.SetSelectionList(ids)

            selection = vtkSelection()
            selection.AddNode(selection_node)

            extract_selection = vtkExtractSelection()
            extract_selection.SetInputData(0, self.data)
            extract_selection.SetInputData(1, selection)
            extract_selection.Update()

            # In selection
            selected = vtkUnstructuredGrid()
            selected.ShallowCopy(extract_selection.GetOutput())

            print(f'Number of points in the selection: {selected.GetNumberOfPoints()}')
            # print(f'Number of cells in the selection : {selected.GetNumberOfCells()}\n')

            print('########################\n') 

            self.selected_mapper.SetInputData(selected)
            self.selected_actor.SetMapper(self.selected_mapper)
            # self.selected_actor.GetProperty().EdgeVisibilityOn()
            self.selected_actor.GetProperty().SetColor(self.colors.GetColor3d('Black'))
            self.selected_actor.GetProperty().SetPointSize(10)
            self.selected_actor.GetProperty().SetLineWidth(3)
            # print(self.selected_actor)

            self.GetInteractor().GetRenderWindow().GetRenderers().GetFirstRenderer().AddActor(self.selected_actor)
            

        # Forward events
        self.OnLeftButtonDown()

    def right_button_press_event(self, obj, event):
    
        if self.vtk_list.GetNumberOfIds() == 0:
            return
        else:
            ids2 = vtkIdTypeArray()
            ids2.SetNumberOfComponents(1)
            for i in range(self.vtk_list.GetNumberOfIds()):
                # print(i)
                ids2.InsertNextValue(i)
            # print(ids2)
            selection_node2 = vtkSelectionNode()
            selection_node2.SetFieldType(vtkSelectionNode.CELL)
            selection_node2.SetContentType(vtkSelectionNode.INDICES)
            selection_node2.SetSelectionList(ids2)

            selection2 = vtkSelection()
            selection2.AddNode(selection_node2)

            extract_selection2 = vtkExtractSelection()
            extract_selection2.SetInputData(0, self.data)
            extract_selection2.SetInputData(1, selection2)
            extract_selection2.Update()
            

    # # In selection
    
            selected2 = vtkUnstructuredGrid()
            selected2.ShallowCopy(extract_selection2.GetOutput())

            print(f'Number of neighboring points: {selected2.GetNumberOfPoints()}')
    # # print(f'Number of neighboring cells: {selected2.GetNumberOfCells()}\n')
            print('########################\n') 

            self.selected_mapper2.SetInputData(selected2)
            self.selected_actor2.SetMapper(self.selected_mapper2)
            # self.selected_actor.GetProperty().EdgeVisibilityOn()
            self.selected_actor2.GetProperty().SetColor(self.colors.GetColor3d("tan"))
            self.selected_actor2.GetProperty().SetPointSize(10)
            self.selected_actor2.GetProperty().SetLineWidth(3)
            # print(self.selected_actor2)

            self.GetInteractor().GetRenderWindow().GetRenderers().GetFirstRenderer().AddActor(self.selected_actor2)

            print('Randomly Selecting 1000 points in the data........')
            point_indices = []
            cluster_points = np.zeros((self.vtk_list.GetNumberOfIds(),3))
            # print(cluster_points)
            print('Calculating the clusters around the centers ......')
            for i in range(self.vtk_list.GetNumberOfIds()):
            
                point_indices.append(self.vtk_list.GetId(i))
            
                cluster_points[i]=pointCloud.vtkPolyData.GetPoint(self.vtk_list.GetId(i))
            
            point_indices = np.asarray(point_indices)

            new_points= np.delete(points,point_indices, axis=0)

            random_array = np.random.randint(0,new_points.shape[0],(1000))
            
            min_haus = 1000000000.0
            for i in range(random_array.shape[0]):
                new_list=vtk.vtkIdList()
                new_center = new_points[random_array[i]]
            # print('new center to find cluster:',new_center)
                self.locator.FindPointsWithinRadius(0.02,new_center, new_list)
                new_cluster_points = np.zeros((new_list.GetNumberOfIds(),3))
                for x in range(new_list.GetNumberOfIds()):
                    new_cluster_points[x]=pointCloud.vtkPolyData.GetPoint(new_list.GetId(x))
                    haus = directed_hausdorff(cluster_points,new_cluster_points)[0]
                    if haus<min_haus:
                        min_haus = haus
                        idx = random_array[i]
                        min_center = new_points[random_array[i]]

                # print('haus:',haus)
            print('min haus:',min_haus)
            print('idx of min haus:',idx)
            print('center of the min haus cluster:',min_center)

            min_list = vtk.vtkIdList()
            self.locator.FindPointsWithinRadius(0.02,min_center, min_list)
            print('Min list for min center', min_list)
    
    # # Forward events
        self.OnRightButtonDown()

# Initialize point clouds
pointCloud = VtkPointCloud()

pointCloud2 = VtkPointCloud()
# print(type(pointCloud))

# Loading Point cloud using open3d
pt_cloud = o3d.io.read_point_cloud('fused_cloud_normal.ply')
points = np.asarray(pt_cloud.points)

pt_cloud2 = o3d.io.read_point_cloud('all_projected_pts.ply')
points2 = np.asarray(pt_cloud2.points)

# Adding the points into polydata
for row in points:
    pointCloud.addPoint(row)

for row in points2:
    pointCloud2.addPoint(row)

# Intialize actor
c = vtkNamedColors()
actor = pointCloud.vtkActor
actor.GetProperty().SetPointSize(10)
actor.GetProperty().SetColor(c.GetColor3d('Yellow'))

# actor.GetProperty().SetColor(0,0,0)
# Renderer
renderer = vtk.vtkRenderer()
renderer.AddActor(actor)
# renderer.AddActor(pointCloud2.vtkActor)
renderer.SetBackground(.1, .1, .4)
renderer.ResetCamera()

# Render Window
renderWindow = vtk.vtkRenderWindow()
renderWindow.AddRenderer(renderer)

style = MouseInteractorStyle(pointCloud.vtkPolyData)
style.SetDefaultRenderer(renderer)

# Interactor
renderWindowInteractor = vtk.vtkRenderWindowInteractor()
renderWindowInteractor.SetRenderWindow(renderWindow)
renderWindowInteractor.SetInteractorStyle(style)

# Begin Interaction
renderWindow.Render()
renderWindowInteractor.Start()

```

---

<div class="post-metadata">

### Author: ![marcomusy](https://discourse.vtk.org/user_avatar/discourse.vtk.org/marcomusy/32/95_2.png) [@marcomusy](https://discourse.vtk.org/u/marcomusy)
#### Post date: [December 12, 2022, 1:45pm UTC](https://discourse.vtk.org/t/vtk-point-cloud-display-multiple-points-cluster/10162/2 "2022-12-12T13:45:32Z")

</div>

the picker doesn’t seem to pick anything though… maybe using `vtkPropPicker` (?), this is the way i would do it in vedo, in case you’re interested:

```python
import numpy as np
from vedo import Points, Text2D, Plotter

def func(evt):
    if not evt.actor:
        return
    pt = evt.picked3d
    ids = evt.actor.closest_point(pt, radius=1.0, return_point_id=True)
    selpts = Points(points1[ids]).pickable(False).c("red5").ps(12)
    selpts.name = "nearpoints"
    d = selpts.hausdorff_distance(vpoints2)
    txt.text(f"n = {len(ids)}, d = {d}")
    plt.remove("nearpoints").add(selpts)

# vpoints1 = Points("fused_cloud_normal.ply").ps(10)
# points1 = vpoints1.points()
points1 = np.random.randn(1000,3) + [0,0,0]
points2 = np.random.randn(1000,3) + [7,0,0]
vpoints1 = Points(points1).ps(10)
vpoints2 = Points(points2).ps(10).pickable(False).c("blue2")
txt = Text2D("Hover mouse", font="Calco")

plt = Plotter()
plt.add_callback("hover", func)
plt.show(vpoints1, vpoints2, txt, axes=1).close()

```

 ![Screenshot 2022-12-12 at 14.14.53](https://discourse.vtk.org/uploads/default/original/2X/e/ea055c4ba42d21e1fffeb86437da519a54b267a7.png)

---

<div class="post-metadata">

### Author: ![nikhilmakkar2345](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/n/f07891/32.png) [@nikhilmakkar2345](https://discourse.vtk.org/u/nikhilmakkar2345)
#### Post date: [December 12, 2022, 4:53pm UTC](https://discourse.vtk.org/t/vtk-point-cloud-display-multiple-points-cluster/10162/3 "2022-12-12T16:53:42Z")

</div>

I made it work in some way. There was a bug in line,  
`ids2.InsertNextValue(i)`  
It should be,  
`ids2.InsertNextValue(self.vtk_list.GetId(i))`.  
Looks like it was visualizing but colors were not helpful.

It is still not perfect as I am not able to change the colors of points according to selection or cluster but this is a small problem which I am planning to solve later.

 ![Capture](https://discourse.vtk.org/uploads/default/original/2X/e/e9ba43fd76e7838679ed36606c8cd331a69d4a64.png)
