Source code for pyntcloud.scalar_fields.k_neighbors

import numpy as np

from .base import ScalarField
from ..utils.array import cov3D


class KNeighborsScalarField(ScalarField):
    """
    Parameters
    ----------
    k_neighbors: ndarray
        (N, k, 3) The k neighbours associated to each of the N points.
    """

    def __init__(self, *, pyntcloud, k_neighbors):
        super().__init__(pyntcloud=pyntcloud)
        # add each point to its neighborhood
        self.k_neighbors_idx = np.c_[range(len(k_neighbors)), k_neighbors]

    def extract_info(self):
        self.k_neighbors = self.pyntcloud.xyz[self.k_neighbors_idx]


[docs]class EigenValues(KNeighborsScalarField): """Compute the eigen values of each point's neighbourhood. """ def compute(self): cov = cov3D(self.k_neighbors) eigenvalues = np.linalg.eigvals(cov) sort = eigenvalues.argsort() # range from 0-shape[0] to allow indexing along axis 1 and 2 idx_trick = range(eigenvalues.shape[0]) e1 = eigenvalues[idx_trick, sort[:, 2]] e2 = eigenvalues[idx_trick, sort[:, 1]] e3 = eigenvalues[idx_trick, sort[:, 0]] k = self.k_neighbors.shape[1] self.to_be_added["e1({})".format(k)] = e1 self.to_be_added["e2({})".format(k)] = e2 self.to_be_added["e3({})".format(k)] = e3
[docs]class EigenDecomposition(KNeighborsScalarField): """Compute the eigen decomposition of each point's neighbourhood. """ def compute(self): cov = cov3D(self.k_neighbors) eigenvalues, eigenvectors = np.linalg.eig(cov) sort = eigenvalues.argsort() # range from 0-shape[0] to allow indexing along axis 1 and 2 idx_trick = range(eigenvalues.shape[0]) e1 = eigenvalues[idx_trick, sort[:, 2]] e2 = eigenvalues[idx_trick, sort[:, 1]] e3 = eigenvalues[idx_trick, sort[:, 0]] k = self.k_neighbors.shape[1] self.to_be_added["e1({})".format(k)] = e1 self.to_be_added["e2({})".format(k)] = e2 self.to_be_added["e3({})".format(k)] = e3 ev1 = eigenvectors[idx_trick, :, sort[:, 2]] ev2 = eigenvectors[idx_trick, :, sort[:, 1]] ev3 = eigenvectors[idx_trick, :, sort[:, 0]] self.to_be_added["ev1_x({})".format(k)] = ev1[:, 0] self.to_be_added["ev1_y({})".format(k)] = ev1[:, 1] self.to_be_added["ev1_z({})".format(k)] = ev1[:, 2] self.to_be_added["ev2_x({})".format(k)] = ev2[:, 0] self.to_be_added["ev2_y({})".format(k)] = ev2[:, 1] self.to_be_added["ev2_z({})".format(k)] = ev2[:, 2] self.to_be_added["ev3_x({})".format(k)] = ev3[:, 0] self.to_be_added["ev3_y({})".format(k)] = ev3[:, 1] self.to_be_added["ev3_z({})".format(k)] = ev3[:, 2]
class UnorientedNormals(KNeighborsScalarField): """Compute normals using SVD. """ def compute(self): cov = cov3D(self.k_neighbors) u, s, v = np.linalg.svd(cov) normals = u[:, :, -1] k = self.k_neighbors.shape[1] self.to_be_added["nx({})".format(k)] = normals[:, 0] self.to_be_added["ny({})".format(k)] = normals[:, 1] self.to_be_added["nz({})".format(k)] = normals[:, 2]