# Path: pcloudpy/core/utils/vtkhelpers.py
# def actor_from_imagedata(imagedata):
#     actor = vtkImageActor()
#     actor.SetInputData(imagedata)
#     actor.InterpolateOff()
#     return actor
# 
# def actor_from_polydata(PolyData):
#     """
#     Returns the VTK Actor from vtkPolyData Structure
#     """
#     mapper = vtkPolyDataMapper()
#     mapper.SetInputData(PolyData)
#     actor = vtkActor()
#     actor.SetMapper(mapper)
#     #actor.GetProperty().SetPointSize(2)
#     return actor
# 
# Path: pcloudpy/core/io/converters.py
# def numpy_from_polydata(polydata):
#     """
#     Converts vtkPolyData to Numpy Array
# 
#     Parameters
#     ----------
# 
#     polydata: vtkPolyData
#         Input Polydata
# 
#     """
# 
#     nodes_vtk_array = polydata.GetPoints().GetData()
#     nodes_numpy_array = vtk_to_numpy(nodes_vtk_array)
# 
#     if polydata.GetPointData().GetScalars():
#         nodes_numpy_array_colors = vtk_to_numpy(polydata.GetPointData().GetScalars("colors"))
#         return np.c_[nodes_numpy_array, nodes_numpy_array_colors]
#     else:
#         return nodes_numpy_array
# 
# def polydata_from_numpy(coords):
#     """
#     Converts Numpy Array to vtkPolyData
# 
#     Parameters
#     ----------
#     coords: array, shape= [number of points, point features]
#         array containing the point cloud in which each point has three coordinares [x, y, z]
#         and none, one or three values corresponding to colors.
# 
#     Returns:
#     --------
#     PolyData: vtkPolyData
#         concrete dataset represents vertices, lines, polygons, and triangle strips
# 
#     """
# 
#     Npts, Ndim = np.shape(coords)
# 
#     Points = vtkPoints()
#     ntype = get_numpy_array_type(Points.GetDataType())
#     coords_vtk = numpy_to_vtk(np.asarray(coords[:,0:3], order='C',dtype=ntype), deep=1)
#     Points.SetNumberOfPoints(Npts)
#     Points.SetData(coords_vtk)
# 
#     Cells = vtkCellArray()
#     ids = np.arange(0,Npts, dtype=np.int64).reshape(-1,1)
#     IDS = np.concatenate([np.ones(Npts, dtype=np.int64).reshape(-1,1), ids],axis=1)
#     ids_vtk = numpy_to_vtkIdTypeArray(IDS, deep=True)
# 
#     Cells.SetNumberOfCells(Npts)
#     Cells.SetCells(Npts,ids_vtk)
# 
#     if Ndim == 4:
#         color = [128]*len(coords)
#         color = np.c_[color, color, color]
#     elif Ndim == 6:
#         color = coords[:,3:]
#     else:
#         color = [[128, 128, 128]]*len(coords)
# 
#     color_vtk = numpy_to_vtk(
#             np.ascontiguousarray(color, dtype=get_vtk_to_numpy_typemap()[VTK_UNSIGNED_CHAR]),
#             deep=True)
# 
#     color_vtk.SetName("colors")
# 
#     PolyData = vtkPolyData()
#     PolyData.SetPoints(Points)
#     PolyData.SetVerts(Cells)
#     PolyData.GetPointData().SetScalars(color_vtk)
#     return PolyData
# 
# Path: pcloudpy/core/filters/base.py
# class FilterBase(BaseObject):
#     """
#     Base Class for all Filter Objects
# 
#     Attributes
#     ----------
#     input_: vtkPolyData
#         Input Data  to be filtered
# 
#     output_: vtkPolyData
#         Output Data
# 
#     """
# 
#     def __init__(self):
# 
#         self.input_ = None
#         self.output_ = None
# 
#     def set_input(self, input_data):
# 
#         """
#         set input data
# 
#         Parameters
#         ----------
#         input-data : vtkPolyData
# 
#         Returns
#         -------
#         is_valid: bool
#             Returns True if the input_data is valid for processing
# 
#         """
#         if isinstance(input_data, vtkPolyData):
#             self.input_ = input_data
#             return True
#         else:
#             return False
# 
# 
#     def get_output(self):
# 
#         if self.output_:
#             return self.output_
# 
#     def update(self):
#         pass


import numpy as np
from vtk import vtkPoints, vtkCellArray, vtkPolyData, vtkIdList
from vtk import vtkKdTreePointLocator
from vtk import vtkSphereSource, vtkXMLPolyDataWriter, vtkVertexGlyphFilter
from sklearn.neighbors import KDTree
from ..utils.vtkhelpers import actor_from_imagedata, actor_from_polydata
from ..io.converters import numpy_from_polydata, polydata_from_numpy
from pcloudpy.core.filters.base import FilterBase
            super(vtkPointSetOutlierEstimation, self).set_input(input_data)
            return True
        else:
            return False

    def set_percent_to_remove(self, value):
        self.percent_to_remove = value

    def update(self):

        array_full = numpy_from_polydata(self.input_)

        array = array_full[:,0:3]
        color = array_full[:,3:]

        #KDTree object (sklearn)
        kDTree = KDTree(array)
        dx, _ = kDTree.query(array[:, :], k = 2)
        dx  = dx[:,1:].ravel()

        Indices = np.argsort(dx, axis=0)
        Npts = np.shape(Indices)[0]
        numberToKeep = int( (1 - self.percent_to_remove ) * Npts)

        idx = Indices[0:numberToKeep]

        new_array = np.copy(array[idx])
        new_color = np.copy(color[idx])
        array = np.c_[new_array, new_color]


# Path: pcloudpy/core/utils/vtkhelpers.py
# def actor_from_imagedata(imagedata):
#     actor = vtkImageActor()
#     actor.SetInputData(imagedata)
#     actor.InterpolateOff()
#     return actor
# 
# def actor_from_polydata(PolyData):
#     """
#     Returns the VTK Actor from vtkPolyData Structure
#     """
#     mapper = vtkPolyDataMapper()
#     mapper.SetInputData(PolyData)
#     actor = vtkActor()
#     actor.SetMapper(mapper)
#     #actor.GetProperty().SetPointSize(2)
#     return actor
# 
# Path: pcloudpy/core/io/converters.py
# def numpy_from_polydata(polydata):
#     """
#     Converts vtkPolyData to Numpy Array
# 
#     Parameters
#     ----------
# 
#     polydata: vtkPolyData
#         Input Polydata
# 
#     """
# 
#     nodes_vtk_array = polydata.GetPoints().GetData()
#     nodes_numpy_array = vtk_to_numpy(nodes_vtk_array)
# 
#     if polydata.GetPointData().GetScalars():
#         nodes_numpy_array_colors = vtk_to_numpy(polydata.GetPointData().GetScalars("colors"))
#         return np.c_[nodes_numpy_array, nodes_numpy_array_colors]
#     else:
#         return nodes_numpy_array
# 
# def polydata_from_numpy(coords):
#     """
#     Converts Numpy Array to vtkPolyData
# 
#     Parameters
#     ----------
#     coords: array, shape= [number of points, point features]
#         array containing the point cloud in which each point has three coordinares [x, y, z]
#         and none, one or three values corresponding to colors.
# 
#     Returns:
#     --------
#     PolyData: vtkPolyData
#         concrete dataset represents vertices, lines, polygons, and triangle strips
# 
#     """
# 
#     Npts, Ndim = np.shape(coords)
# 
#     Points = vtkPoints()
#     ntype = get_numpy_array_type(Points.GetDataType())
#     coords_vtk = numpy_to_vtk(np.asarray(coords[:,0:3], order='C',dtype=ntype), deep=1)
#     Points.SetNumberOfPoints(Npts)
#     Points.SetData(coords_vtk)
# 
#     Cells = vtkCellArray()
#     ids = np.arange(0,Npts, dtype=np.int64).reshape(-1,1)
#     IDS = np.concatenate([np.ones(Npts, dtype=np.int64).reshape(-1,1), ids],axis=1)
#     ids_vtk = numpy_to_vtkIdTypeArray(IDS, deep=True)
# 
#     Cells.SetNumberOfCells(Npts)
#     Cells.SetCells(Npts,ids_vtk)
# 
#     if Ndim == 4:
#         color = [128]*len(coords)
#         color = np.c_[color, color, color]
#     elif Ndim == 6:
#         color = coords[:,3:]
#     else:
#         color = [[128, 128, 128]]*len(coords)
# 
#     color_vtk = numpy_to_vtk(
#             np.ascontiguousarray(color, dtype=get_vtk_to_numpy_typemap()[VTK_UNSIGNED_CHAR]),
#             deep=True)
# 
#     color_vtk.SetName("colors")
# 
#     PolyData = vtkPolyData()
#     PolyData.SetPoints(Points)
#     PolyData.SetVerts(Cells)
#     PolyData.GetPointData().SetScalars(color_vtk)
#     return PolyData
# 
# Path: pcloudpy/core/filters/base.py
# class FilterBase(BaseObject):
#     """
#     Base Class for all Filter Objects
# 
#     Attributes
#     ----------
#     input_: vtkPolyData
#         Input Data  to be filtered
# 
#     output_: vtkPolyData
#         Output Data
# 
#     """
# 
#     def __init__(self):
# 
#         self.input_ = None
#         self.output_ = None
# 
#     def set_input(self, input_data):
# 
#         """
#         set input data
# 
#         Parameters
#         ----------
#         input-data : vtkPolyData
# 
#         Returns
#         -------
#         is_valid: bool
#             Returns True if the input_data is valid for processing
# 
#         """
#         if isinstance(input_data, vtkPolyData):
#             self.input_ = input_data
#             return True
#         else:
#             return False
# 
# 
#     def get_output(self):
# 
#         if self.output_:
#             return self.output_
# 
#     def update(self):
#         pass


# Path: pcloudpy/core/filters/vtkPointSetOutlierRemoval.py
import numpy as np
from vtk import vtkPoints, vtkCellArray, vtkPolyData, vtkIdList
from vtk import vtkKdTreePointLocator
from vtk import vtkSphereSource, vtkXMLPolyDataWriter, vtkVertexGlyphFilter
from sklearn.neighbors import KDTree
from ..utils.vtkhelpers import actor_from_imagedata, actor_from_polydata
from ..io.converters import numpy_from_polydata, polydata_from_numpy
from pcloudpy.core.filters.base import FilterBase

            super(vtkPointSetOutlierEstimation, self).set_input(input_data)
            return True
        else:
            return False

    def set_percent_to_remove(self, value):
        self.percent_to_remove = value

    def update(self):

        array_full = numpy_from_polydata(self.input_)

        array = array_full[:,0:3]
        color = array_full[:,3:]

        #KDTree object (sklearn)
        kDTree = KDTree(array)
        dx, _ = kDTree.query(array[:, :], k = 2)
        dx  = dx[:,1:].ravel()

        Indices = np.argsort(dx, axis=0)
        Npts = np.shape(Indices)[0]
        numberToKeep = int( (1 - self.percent_to_remove ) * Npts)

        idx = Indices[0:numberToKeep]

        new_array = np.copy(array[idx])
        new_color = np.copy(color[idx])
        array = np.c_[new_array, new_color]


        output = polydata_from_numpy(array)