Module sverchok.utils.kdtree
Expand source code
# This file is part of project Sverchok. It's copyrighted by the contributors
# recorded in the version control history of the file, available from
# its original location https://github.com/nortikin/sverchok/commit/master
#
# SPDX-License-Identifier: GPL3
# License-Filename: LICENSE
import numpy as np
from mathutils import kdtree
from sverchok.dependencies import scipy
if scipy is not None:
from scipy.spatial import cKDTree
class SvKdTree(object):
SCIPY = 'SCIPY'
BLENDER = 'BLENDER'
@staticmethod
def new(implementation, points, power=2):
if implementation == SvKdTree.SCIPY:
return SvSciPyKdTree(points, power=power)
elif implementation == SvKdTree.BLENDER:
if power == 2:
return SvBlenderKdTree(points)
else:
return SvBruteforceKdTree(points, power=power)
@staticmethod
def best_available_implementation():
if scipy is not None:
return SvKdTree.SCIPY
else:
return SvKdTree.BLENDER
def __init__(self, points):
pass
def query(self, needle, count=1):
raise Exception("Not implemented")
def query_array(self, needle, count=1):
raise Exception("Not implemented")
def query_range(self, needle, radius, **kwargs):
raise Exception("Not implemented")
class SvBlenderKdTree(SvKdTree):
def __init__(self, points):
self.kdtree = kdtree.KDTree(len(points))
for i, v in enumerate(points):
self.kdtree.insert(v, i)
self.kdtree.balance()
def query(self, needle, count=1, **kwargs):
if count == 1:
loc, idx, distance = self.kdtree.find(needle)
if loc is None:
return None
else:
return np.array(loc), idx, distance
else:
res = self.kdtree.find_n(needle, count)
locs = np.array([np.array(loc) for loc, idx, distance in res])
idxs = np.array([idx for loc, idx, distance in res])
distances = np.array([distance for loc, idx, distance in res])
return locs, idxs, distances
def query_array(self, needle, count=1, **kwargs):
res = [self.query(item, count) for item in needle]
locs = [loc for loc, idx, distance in res]
idxs = [idx for loc, idx, distance in res]
distances = [distance for loc, idx, distance in res]
return np.array(locs), np.array(idxs), np.array(distances)
def query_range(self, needle, radius, **kwargs):
res = self.kdtree.find_range(needle, radius)
idxs = [r[1] for r in res]
res = [tuple(r[0]) for r in res]
return idxs, np.array(res)
class SvSciPyKdTree(SvKdTree):
def __init__(self, points, power=2):
self.points = np.asarray(points)
self.kdtree = cKDTree(self.points)
self.power = power
def query(self, needle, count=1, **kwargs):
distance, idx = self.kdtree.query(needle, k=count, p=self.power, **kwargs)
loc = self.points[idx]
return loc, idx, distance
def query_array(self, needle, count=1, **kwargs):
distances, idxs = self.kdtree.query(needle, k=count, p=self.power, **kwargs)
locs = self.points[idxs]
return locs, idxs, distances
def query_range(self, needle, radius, **kwargs):
idxs = self.kdtree.query_ball_point(needle, radius, p=self.power, **kwargs)
return idxs, self.points[idxs]
class SvBruteforceKdTree(SvKdTree):
def __init__(self, points, power=2):
self.points = np.asarray(points)
self.power = power
def query(self, needle, count=1):
dvs = self.points - needle
distances = np.linalg.norm(dvs, axis=1, ord=self.power)
if count == 1:
idx = np.argmin(distances)
loc = self.points[idx]
distance = distances[idx]
return loc, idx, distance
else:
idxs = np.argsort(distances)[:count]
locs = self.points[idxs]
distances = distances[idxs]
return locs, idxs, distances
def query_array(self, needle, count=1):
if count == 1:
return np.vectorize(self.query, signature='(3)->(3),(),()')(needle)
else:
qry = lambda p: self.query(p, count=count)
return np.vectorize(qry, signature='(n,3)->(k,3),(k),(k)')(needle)
Classes
class SvBlenderKdTree (points)
-
Expand source code
class SvBlenderKdTree(SvKdTree): def __init__(self, points): self.kdtree = kdtree.KDTree(len(points)) for i, v in enumerate(points): self.kdtree.insert(v, i) self.kdtree.balance() def query(self, needle, count=1, **kwargs): if count == 1: loc, idx, distance = self.kdtree.find(needle) if loc is None: return None else: return np.array(loc), idx, distance else: res = self.kdtree.find_n(needle, count) locs = np.array([np.array(loc) for loc, idx, distance in res]) idxs = np.array([idx for loc, idx, distance in res]) distances = np.array([distance for loc, idx, distance in res]) return locs, idxs, distances def query_array(self, needle, count=1, **kwargs): res = [self.query(item, count) for item in needle] locs = [loc for loc, idx, distance in res] idxs = [idx for loc, idx, distance in res] distances = [distance for loc, idx, distance in res] return np.array(locs), np.array(idxs), np.array(distances) def query_range(self, needle, radius, **kwargs): res = self.kdtree.find_range(needle, radius) idxs = [r[1] for r in res] res = [tuple(r[0]) for r in res] return idxs, np.array(res)
Ancestors
Methods
def query(self, needle, count=1, **kwargs)
-
Expand source code
def query(self, needle, count=1, **kwargs): if count == 1: loc, idx, distance = self.kdtree.find(needle) if loc is None: return None else: return np.array(loc), idx, distance else: res = self.kdtree.find_n(needle, count) locs = np.array([np.array(loc) for loc, idx, distance in res]) idxs = np.array([idx for loc, idx, distance in res]) distances = np.array([distance for loc, idx, distance in res]) return locs, idxs, distances
def query_array(self, needle, count=1, **kwargs)
-
Expand source code
def query_array(self, needle, count=1, **kwargs): res = [self.query(item, count) for item in needle] locs = [loc for loc, idx, distance in res] idxs = [idx for loc, idx, distance in res] distances = [distance for loc, idx, distance in res] return np.array(locs), np.array(idxs), np.array(distances)
def query_range(self, needle, radius, **kwargs)
-
Expand source code
def query_range(self, needle, radius, **kwargs): res = self.kdtree.find_range(needle, radius) idxs = [r[1] for r in res] res = [tuple(r[0]) for r in res] return idxs, np.array(res)
class SvBruteforceKdTree (points, power=2)
-
Expand source code
class SvBruteforceKdTree(SvKdTree): def __init__(self, points, power=2): self.points = np.asarray(points) self.power = power def query(self, needle, count=1): dvs = self.points - needle distances = np.linalg.norm(dvs, axis=1, ord=self.power) if count == 1: idx = np.argmin(distances) loc = self.points[idx] distance = distances[idx] return loc, idx, distance else: idxs = np.argsort(distances)[:count] locs = self.points[idxs] distances = distances[idxs] return locs, idxs, distances def query_array(self, needle, count=1): if count == 1: return np.vectorize(self.query, signature='(3)->(3),(),()')(needle) else: qry = lambda p: self.query(p, count=count) return np.vectorize(qry, signature='(n,3)->(k,3),(k),(k)')(needle)
Ancestors
Methods
def query(self, needle, count=1)
-
Expand source code
def query(self, needle, count=1): dvs = self.points - needle distances = np.linalg.norm(dvs, axis=1, ord=self.power) if count == 1: idx = np.argmin(distances) loc = self.points[idx] distance = distances[idx] return loc, idx, distance else: idxs = np.argsort(distances)[:count] locs = self.points[idxs] distances = distances[idxs] return locs, idxs, distances
def query_array(self, needle, count=1)
-
Expand source code
def query_array(self, needle, count=1): if count == 1: return np.vectorize(self.query, signature='(3)->(3),(),()')(needle) else: qry = lambda p: self.query(p, count=count) return np.vectorize(qry, signature='(n,3)->(k,3),(k),(k)')(needle)
class SvKdTree (points)
-
Expand source code
class SvKdTree(object): SCIPY = 'SCIPY' BLENDER = 'BLENDER' @staticmethod def new(implementation, points, power=2): if implementation == SvKdTree.SCIPY: return SvSciPyKdTree(points, power=power) elif implementation == SvKdTree.BLENDER: if power == 2: return SvBlenderKdTree(points) else: return SvBruteforceKdTree(points, power=power) @staticmethod def best_available_implementation(): if scipy is not None: return SvKdTree.SCIPY else: return SvKdTree.BLENDER def __init__(self, points): pass def query(self, needle, count=1): raise Exception("Not implemented") def query_array(self, needle, count=1): raise Exception("Not implemented") def query_range(self, needle, radius, **kwargs): raise Exception("Not implemented")
Subclasses
Class variables
var BLENDER
var SCIPY
Static methods
def best_available_implementation()
-
Expand source code
@staticmethod def best_available_implementation(): if scipy is not None: return SvKdTree.SCIPY else: return SvKdTree.BLENDER
def new(implementation, points, power=2)
-
Expand source code
@staticmethod def new(implementation, points, power=2): if implementation == SvKdTree.SCIPY: return SvSciPyKdTree(points, power=power) elif implementation == SvKdTree.BLENDER: if power == 2: return SvBlenderKdTree(points) else: return SvBruteforceKdTree(points, power=power)
Methods
def query(self, needle, count=1)
-
Expand source code
def query(self, needle, count=1): raise Exception("Not implemented")
def query_array(self, needle, count=1)
-
Expand source code
def query_array(self, needle, count=1): raise Exception("Not implemented")
def query_range(self, needle, radius, **kwargs)
-
Expand source code
def query_range(self, needle, radius, **kwargs): raise Exception("Not implemented")
class SvSciPyKdTree (points, power=2)
-
Expand source code
class SvSciPyKdTree(SvKdTree): def __init__(self, points, power=2): self.points = np.asarray(points) self.kdtree = cKDTree(self.points) self.power = power def query(self, needle, count=1, **kwargs): distance, idx = self.kdtree.query(needle, k=count, p=self.power, **kwargs) loc = self.points[idx] return loc, idx, distance def query_array(self, needle, count=1, **kwargs): distances, idxs = self.kdtree.query(needle, k=count, p=self.power, **kwargs) locs = self.points[idxs] return locs, idxs, distances def query_range(self, needle, radius, **kwargs): idxs = self.kdtree.query_ball_point(needle, radius, p=self.power, **kwargs) return idxs, self.points[idxs]
Ancestors
Methods
def query(self, needle, count=1, **kwargs)
-
Expand source code
def query(self, needle, count=1, **kwargs): distance, idx = self.kdtree.query(needle, k=count, p=self.power, **kwargs) loc = self.points[idx] return loc, idx, distance
def query_array(self, needle, count=1, **kwargs)
-
Expand source code
def query_array(self, needle, count=1, **kwargs): distances, idxs = self.kdtree.query(needle, k=count, p=self.power, **kwargs) locs = self.points[idxs] return locs, idxs, distances
def query_range(self, needle, radius, **kwargs)
-
Expand source code
def query_range(self, needle, radius, **kwargs): idxs = self.kdtree.query_ball_point(needle, radius, p=self.power, **kwargs) return idxs, self.points[idxs]