code: def alignICP(source, target, iters=100, rigid=False):
      
      if isinstance(source, Actor):
          source = source.polydata()
      if isinstance(target, Actor):
          target = target.polydata()
  
      icp = vtk.vtkIterativeClosestPointTransform()
      icp.SetSource(source)
      icp.SetTarget(target)
      icp.SetMaximumNumberOfIterations(iters)
      if rigid:
          icp.GetLandmarkTransform().SetModeToRigidBody()
      icp.StartByMatchingCentroidsOn()
      icp.Update()
      icpTransformFilter = vtk.vtkTransformPolyDataFilter()
      icpTransformFilter.SetInputData(source)
      icpTransformFilter.SetTransform(icp)
      icpTransformFilter.Update()
      poly = icpTransformFilter.GetOutput()
      actor = Actor(poly)
  
      # actor.info['transform'] = icp.GetLandmarkTransform() # not working!
      # do it manually...
      sourcePoints = vtk.vtkPoints()
      targetPoints = vtk.vtkPoints()
      for i in range(10):
          p1 = [0, 0, 0]
          source.GetPoints().GetPoint(i, p1)
          sourcePoints.InsertNextPoint(p1)
          p2 = [0, 0, 0]
          poly.GetPoints().GetPoint(i, p2)
          targetPoints.InsertNextPoint(p2)
  
      # Setup the transform
      landmarkTransform = vtk.vtkLandmarkTransform()
      landmarkTransform.SetSourceLandmarks(sourcePoints)
      landmarkTransform.SetTargetLandmarks(targetPoints)
      if rigid:
          landmarkTransform.SetModeToRigidBody()
      actor.info["transform"] = landmarkTransform
  
      return actor
docs: Return a copy of source actor which is aligned to
      target actor through the `Iterative Closest Point` algorithm.
  
      The core of the algorithm is to match each vertex in one surface with
      the closest surface point on the other, then apply the transformation
      that modify one surface to best match the other (in the least-square sense).
  
      .. hint:: |align1| |align1.py|_
  
          |align2| |align2.py|_