Source code for upxo.geoEntities.point3d

"""
3D point geometry entities for UPXO.

Provides the :class:`Point3d` full-featured 3D point and the
:class:`p3d_leanest` lightweight variant for performance-critical use.

Classes
-------
Point3d
    Full-featured 3D point with coordinate operations, equality checks,
    distance calculations, and neighbour-finding methods.
p3d_leanest
    Minimal 3D point for performance-critical collections. Intended for
    internal use only.

Usage
-----
::

    from upxo.geoEntities.point3d import Point3d as p3d

@author: Dr. Sunil Anandatheertha
"""

import math
import numpy as np
from copy import deepcopy
from scipy.spatial import cKDTree
import vtk
import upxo._sup.dataTypeHandlers as dth
from upxo.geoEntities.bases import UPXO_Point, UPXO_Edge
from upxo.geoEntities.featmake import make_p2d, make_p3d
from upxo._sup.validation_values import find_spec_of_points
from upxo._sup.validation_values import isinstance_many

class _coord_():
    __slots__ = ('x', 'y', 'z')
    def __init__(self, x, y, z):
        """Store raw 3D coordinate values in ``x``, ``y``, ``z``."""
        self.x, self.y, self.z = x, y, z


[docs] class p3d_leanest(): """ Minimal 3D point class for performance-critical internal use. Notes ----- Intentionally minimal — no methods beyond ``__init__`` and ``__repr__``. Further development should be avoided to keep memory overhead low. Examples -------- .. code-block:: python from upxo.geoEntities.point3d import p3d_leanest pts = [p3d_leanest(1, 2, 0), p3d_leanest(3, 4, 1)] """ __slots__ = ('_x', '_y', '_z') def __init__(self, x, y, z): """Initialise the leanest 3D point with ``x``, ``y``, ``z`` coordinates.""" self._x, self._y, self._z = x, y, z def __repr__(self): """Return string representation of self.""" return f'Lean 3D point at ({self._x}, {self._y}, {self._z}, {id(self)})'
[docs] class Point3d(UPXO_Point): """ 3D point entity for UPXO. Parameters ---------- x : float x-coordinate. y : float y-coordinate. z : float, optional z-coordinate (default 0.0). Notes ----- Inherits from :class:`~upxo.geoEntities.bases.UPXO_Point`. Pydantic validation is intentionally avoided to minimise instantiation cost and memory overhead. Examples -------- .. code-block:: python from upxo.geoEntities.point3d import Point3d as p3d A, B, C = p3d(10, 12, 0), p3d(10, 12, 0), p3d(11, 12, 0) print(A, B, C) print(A == B, A != B, A == C, A != C) A * 2 A + [10, 20, 30] """ ε = 1E-8 __slots__ = UPXO_Point.__slots__ + ('z', ) def __init__(self, x, y, z=0.0): """Initialise a 3D point with Cartesian coordinates ``x``, ``y``, ``z``.""" super().__init__(x, y, z) self.x = x self.y = y self.z = z def __repr__(self): """Return a string representation of point3d instance.""" return f"uxpo-p3d ({self.x},{self.y},{self.z})" def __eq__(self, plist): """ Test equality between self and one or more points. Parameters ---------- plist : point or list of points A single point object, list of point objects, or nested coordinate list. Returns ------- list of bool Element-wise equality results. Examples -------- .. code-block:: python from upxo.geoEntities.point3d import Point3d as p3d, p3d_leanest print(p3d(3, 4, 5) == p3d_leanest(3, 4, 5)) print(p3d(3, 4, 5) == [p3d_leanest(1, 4, 5), p3d_leanest(3, 4, 5)]) print(p3d(3, 4, 5) == p3d(3, 4, 5)) print(p3d(3, 4, 5) == [p3d(1, 2, 5), p3d(3, 4, 5)]) print(p3d(3, 4, 5) == (p3d(1, 4, 5), p3d(3, 4, 5))) print(p3d(3, 4, 5) == [[1, 2, 5], [3, 4, 5], [5, 6, 5]]) print(p3d(3, 4, 5) == [[1, 3, 5], [2, 4, 6]]) print(p3d(3, 4, 5) == [[3, 4, 5]]) print(p3d(3, 4, 5) == [[3], [4], [5]]) """ if not plist: raise ValueError("plist is empty.") spec_found = False # --------------------------------------------------------- point_spec = find_spec_of_points(plist) # --------------------------------------------------------- if point_spec in dth.opt.name_point2d_specs: """We are dealing with a 2D point""" cmp, spec_found = [False], True elif point_spec in dth.opt.name_point3d_specs: """We are dealing with a 3D point""" if point_spec == 'Point3d': cmp, spec_found = [(self.x, self.y, self.z) == (plist.x, plist.y, plist.z)], True # --------------------------------------------------------- if point_spec == '[Point3d]': cmp, spec_found = [(self.x, self.y, self.z) == (p.x, p.y, p.z) for p in plist], True # --------------------------------------------------------- if point_spec == 'p3d_leanest': cmp, spec_found = [(self.x, self.y, self.z) == (plist._x, plist._y, plist._z)], True # --------------------------------------------------------- if point_spec == '[p3d_leanest]': cmp, spec_found = [(self.x, self.y, self.z) == (p._x, p._y, p._z) for p in plist], True # --------------------------------------------------------- if point_spec == 'type-[1,2,3]': cmp, spec_found = [(self.x, self.y, self.z) == tuple(plist)], True # --------------------------------------------------------- if point_spec == 'type-[[1,2,3]]': cmp, spec_found = [(self.x, self.y, self.z) == tuple(plist[0])], True # --------------------------------------------------------- if point_spec == 'type-[[1,2,3],[4,5,6],[7,8,9]]': cmp = [self.x == p[0] and self.y == p[1] and self.z == p[2] for p in plist] spec_found = True # --------------------------------------------------------- if point_spec == 'type-[[1,2,3,4],[1,2,3,4],[1,2,3,4]]': cmp = [self.x == _x and self.y == _y and self.z == _z for _x, _y, _z in zip(plist[0], plist[1], plist[2])] spec_found = True # --------------------------------------------------------- if spec_found: return cmp else: return None def __ne__(self, plist, use_tol=True): """Return ``True`` if self is not equal to any point in ``plist``.""" return not self.__eq__(plist, use_tol=use_tol)
[docs] def eq(self, plist, use_tol=False, tolerance=None): """ Overloaded equality check with optional tolerance. Parameters ---------- plist : point or list of points Points to compare against self. use_tol : bool, optional If True, apply tolerance (not yet implemented). tolerance : float, optional Tolerance threshold (not yet implemented). Returns ------- list of bool Element-wise equality results. Examples -------- .. code-block:: python from upxo.geoEntities.point3d import Point3d as p3d, p3d_leanest print(p3d(3, 4, 5).eq(p3d_leanest(3, 4, 5))) print(p3d(3, 4, 5).eq([p3d_leanest(1, 4, 5), p3d_leanest(3, 4, 5)])) print(p3d(3, 4, 5).eq(p3d(3, 4, 5))) print(p3d(3, 4, 5).eq([p3d(1, 2, 5), p3d(3, 4, 5)])) print(p3d(3, 4, 5).eq((p3d(1, 4, 5), p3d(3, 4, 5)))) print(p3d(3, 4, 5).eq([[1, 2, 5], [3, 4, 5], [5, 6, 5]])) print(p3d(3, 4, 5).eq([[1, 3, 5], [2, 4, 6]])) print(p3d(3, 4, 5).eq([[3, 4, 5]])) print(p3d(3, 4, 5).eq([[3], [4], [5]])) """ if not use_tol: return self.__eq__(plist)
[docs] def eq_fast(self, plist, use_tol=False, point_spec=1): """ Fast equality check with explicit point-type specification. Parameters ---------- plist : point or array-like Points to compare. use_tol : bool, optional Tolerance flag (not yet implemented). point_spec : int, optional Integer code identifying the layout of ``plist``: 1 – ``Point3d``; 2 – ``[Point3d]``; 3 – ``p3d_leanest``; 4 – ``[p3d_leanest]``; 5 – ``[x, y, z]``; 6 – ``[[x, y, z]]``; 7 – ``[[x1,x2,...], [y1,y2,...], [z1,z2,...]]`` (row layout); 8 – ``[[x1,...], [y1,...], [z1,...]]`` (column layout). Returns ------- list of bool or None Element-wise equality results, or ``None`` for unrecognised spec. Examples -------- .. code-block:: python from upxo.geoEntities.point3d import Point3d as p3d, p3d_leanest print(p3d(3, 4, 5).eq_fast(p3d(3, 4, 5), point_spec=1)) print(p3d(3, 4, 5).eq_fast([p3d(1, 2, 5), p3d(3, 4, 5)], point_spec=2)) print(p3d(3, 4, 5).eq_fast((p3d(1, 4, 5), p3d(3, 4, 5)), point_spec=2)) print(p3d(3, 4, 5).eq_fast(p3d_leanest(3, 4, 5), point_spec=3)) print(p3d(3, 4, 5).eq_fast([p3d_leanest(1, 4, 5), p3d_leanest(3, 4, 5)], point_spec=4)) print(p3d(3, 4, 5).eq_fast([1, 2, 5], point_spec=5)) print(p3d(3, 4, 5).eq_fast([[1, 2, 5]], point_spec=6)) print(p3d(3, 4, 5).eq_fast([[1, 2, 5], [3, 4, 5], [5, 6, 5]], point_spec=7)) print(p3d(3, 4, 5).eq_fast([[3], [4], [5]], point_spec=8)) """ cmp = None if point_spec == 1: """1: Point3d""" cmp = [(self.x, self.y, self.z) == (plist.x, plist.y, plist.z)] if point_spec == 2: """2: [Point3d]""" cmp = [(self.x, self.y, self.z) == (p.x, p.y, p.z) for p in plist] if point_spec == 3: """3: p3d_leanest""" cmp = [(self.x, self.y, self.z) == (plist._x, plist._y, plist._z)] if point_spec == 4: """4: [p3d_leanest]""" cmp = [(self.x, self.y, self.z) == (p._x, p._y, p._z) for p in plist] if point_spec == 5: """5: type-[1,2,3]""" cmp = [(self.x, self.y, self.z) == tuple(plist)] if point_spec == 6: """6: type-[[1,2,3]]""" cmp = [(self.x, self.y, self.z) == tuple(plist[0])] if point_spec == 7: """7: type-[[1,2,3],[4,5,6],[7,8,9]]""" cmp = [self.x == p[0] and self.y == p[1] and self.z == p[2] for p in plist] if point_spec == 8: """8: type-[[1,2,3,4],[1,2,3,4],[1,2,3,4]]""" cmp = [self.x == _x and self.y == _y and self.z == _z for _x, _y, _z in zip(plist[0], plist[1], plist[2])] return cmp
[docs] def add(self, d, update=True, throw=False, mydecatlen2NUM='b'): """Add scalar or vector ``d`` to self coordinates. Not yet implemented.""" raise NotImplementedError("add is not yet implemented.")
def __mul__(self, f=1.0, update=True, throw=False): """Scale self coordinates by factor ``f``.""" # Validate f # ---------------------------------- # DEVELOPMENT STAGE - 1 # TARGET: succeffull working when f is a single number if not isinstance(f, dth.dt.NUMBERS): raise TypeError('Invald factor') if update: self.x *= f self.y *= f self.z *= f if update and throw: return deepcopy(self) if not update and throw: return Point3d(self.x*f, self.y*f, self.z*f)
[docs] @classmethod def from_three_planes(cls, plane1, plane2, plane3): """Find the point of intersection of three planes. Parameters ---------- plane1 : Plane First plane. plane2 : Plane Second plane. plane3 : Plane Third plane. Returns ------- Point3d or None Intersection point, or ``None`` if no unique solution exists (parallel or coincident planes). Examples -------- .. code-block:: python from upxo.geoEntities.point3d import Point3d as p3d from upxo.geoEntities.plane import Plane plane1 = Plane(point=(0, 0, 1), normal=(1, 1, 1)) plane2 = Plane(point=(0, 0, 0), normal=(0, 1, 0)) plane3 = Plane(point=(0, 0, 0), normal=(0, 0, 1)) intersection_point = p3d.from_three_planes(plane1, plane2, plane3) print(intersection_point) """ A = np.array([plane1.normal, plane2.normal, plane3.normal]) D = np.array([[plane1.point @ plane1.normal], [plane2.point @ plane2.normal], [plane3.point @ plane3.normal]]) try: X = np.linalg.solve(A, D).flatten() return cls(X[0], X[1], X[2]) # return X.flatten() # Return as a 1D NumPy array except np.linalg.LinAlgError: return None # No solution
@property def coords(self): """Return ``[x, y]`` as a numpy array (2D projection of this 3D point).""" return np.array([self.x, self.y])
[docs] def squared_distance(self, plist=None, point_spec=-1): """ Calculate squared distances between self and one or more points. Parameters ---------- plist : point or array-like Single point, list of points, or coordinate array. The expected layout depends on ``point_spec``. point_spec : int, optional Integer code identifying the type of ``plist`` (default ``-1`` for automatic detection): -1 – auto-detect via :func:`~upxo.geoEntities.featmake.make_p3d`; 1 – ``Point3d``; 2 – ``[Point3d]``; 3 – ``p3d_leanest``; 4 – ``[p3d_leanest]``; 5 – ``(x, y, z)`` tuple; 6 – ``[(x, y, z)]``; 7 – ``[[x,y,z], ...]`` row-major; 8 – ``[[x1,...], [y1,...], [z1,...]]`` column-major or ``(3, n)`` array. Returns ------- float or numpy.ndarray Squared Euclidean distance(s) from self to each input point. Examples -------- .. code-block:: python from upxo.geoEntities.point3d import Point3d as p3d, p3d_leanest import numpy as np p3d(0, 0, 0).squared_distance(p3d(1, 1, 0), point_spec=-1) p3d(0, 0, 0).squared_distance([[1,2,3,4],[1,2,3,4],[1,2,3,4]], point_spec=-1) points = np.random.random((3, 100000)) p3d(0, 0, 0).squared_distance(points) p3d(0, 0, 0).squared_distance(p3d(1, 1, 0), point_spec=1) p3d(0, 0, 0).squared_distance([p3d(1, 1, 0)], point_spec=2) p3d(0, 0, 0).squared_distance(p3d_leanest(1, 1, 0), point_spec=3) p3d(0, 0, 0).squared_distance([p3d_leanest(1, 1, 0)], point_spec=4) p3d(0, 0, 0).squared_distance((1, 1, 0), point_spec=5) p3d(0, 0, 0).squared_distance([(1, 1, 0)], point_spec=6) p3d(0, 0, 0).squared_distance([[1,2,3],[4,5,6],[7,8,9]], point_spec=7) p3d(0, 0, 0).squared_distance([[1,2,3,4],[1,2,3,4],[1,2,3,4]], point_spec=8) p3d(0, 0, 0).squared_distance(np.random.random((3, 100000)), point_spec=8) """ # Validations if plist is None: # Not very apt. Need to change with more developmet. raise ValueError('Invalid list of points') # ------------------------------------------ if point_spec == -1: plist = make_p3d(plist, return_type='leanest') X, Y, Z = np.array([[p._x, p._y, p._z] for p in plist]).T # ------------------------------------------ if point_spec == 1: """ from upxo.geoEntities.point3d import Point3d as p3d # point_spec = 1: Point3d. p3d(0,0,0).squared_distance(p3d(1,1,0), point_spec=1) """ X, Y, Z = plist.x, plist.y, plist.z if point_spec == 2: """ from upxo.geoEntities.point3d import Point3d as p3d # point_spec = 2: [Point3d] p3d(0,0,0).squared_distance([p3d(1,1,0)], point_spec=2) """ X, Y, Z = plist[0].x, plist[0].y, plist[0].z if point_spec == 3: """ from upxo.geoEntities.point3d import Point3d as p3d from upxo.geoEntities.point3d import p3d_leanest # point_spec = 3: p3d_leanest p3d(0,0,0).squared_distance(p3d_leanest(1,1,0), point_spec=3) """ X, Y, Z = plist._x, plist._y, plist._z if point_spec == 4: """ from upxo.geoEntities.point3d import Point3d as p3d from upxo.geoEntities.point3d import p3d_leanest # point_spec = 4: [p3d_leanest] p3d(0,0,0).squared_distance([p3d_leanest(1,1,0)], point_spec=4) """ X, Y, Z = plist[0]._x, plist[0]._y, plist[0]._z if point_spec == 5: """ from upxo.geoEntities.point3d import Point3d as p3d # point_spec = 5: type-[1,2,3] p3d(0,0,0).squared_distance((1,1,0), point_spec=5) """ X, Y, Z = plist if point_spec == 6: """ from upxo.geoEntities.point3d import Point3d as p3d # point_spec = 6: type-[[1,2,3]] p3d(0, 0, 0).squared_distance([(1,1,0)], point_spec=6) """ X, Y, Z = plist[0] if point_spec == 7: """ from upxo.geoEntities.point3d import Point3d as p3d # point_spec = 7: type-[[1,2,3],[4,5,6],[7,8,9]] p3d(0, 0, 0).squared_distance([[1,2,3],[4,5,6],[7,8,9]], point_spec=7) """ X, Y, Z = np.array(plist).T if point_spec == 8: """ from upxo.geoEntities.point3d import Point3d as p3d # point_spec = 8: type-[[1,2,3,4],[1,2,3,4],[1,2,3,4]] p3d(0, 0, 0).squared_distance([[1,2,3,4],[1,2,3,4],[1,2,3,4]], point_spec=8) p3d(0, 0, 0).squared_distance(np.random.random((3, 100000)), point_spec=8) """ X, Y, Z = np.array(plist) return (self.x-X)**2 + (self.y-Y)**2 + (self.z-Z)**2
[docs] def distance(self, plist=None, point_spec=-1): """ Calculate Euclidean distances between self and one or more points. Parameters ---------- plist : point or array-like See :meth:`squared_distance` for accepted formats. point_spec : int, optional Point layout code passed through to :meth:`squared_distance`. Returns ------- float or numpy.ndarray Euclidean distance(s) from self to each input point. Examples -------- .. code-block:: python from upxo.geoEntities.point3d import Point3d as p3d, p3d_leanest import numpy as np p3d(0, 0, 0).distance(p3d(1, 1, 0), point_spec=-1) p3d(0, 0, 0).distance([[1,2,3,4],[1,2,3,4],[1,2,3,4]], point_spec=-1) p3d(0, 0, 0).distance(p3d(1, 1, 0), point_spec=1) p3d(0, 0, 0).distance([p3d(1, 1, 0)], point_spec=2) p3d(0, 0, 0).distance(p3d_leanest(1, 1, 0), point_spec=3) p3d(0, 0, 0).distance([p3d_leanest(1, 1, 0)], point_spec=4) p3d(0, 0, 0).distance((1, 1, 0), point_spec=5) p3d(0, 0, 0).distance([(1, 1, 0)], point_spec=6) p3d(0, 0, 0).distance([[1,2,3],[4,5,6],[7,8,9]], point_spec=7) p3d(0, 0, 0).distance([[1,2,3,4],[1,2,3,4],[1,2,3,4]], point_spec=8) p3d(0, 0, 0).distance(np.random.random((3, 100000)), point_spec=8) """ return np.sqrt(self.squared_distance(plist=plist, point_spec=point_spec))
[docs] def translate(self, *, vector=None, dist=None, update=False, throw=True): """ Translate self along a vector by a given distance. Parameters ---------- vector : array-like Direction vector of translation. dist : float Distance to translate along ``vector``. update : bool, optional If True, modify self in place. throw : bool, optional If True, return the translated point. Returns ------- Point3d or None Translated point if ``throw`` is True, else ``None``. Examples -------- .. code-block:: python from upxo.geoEntities.point3d import Point3d as p3d A = p3d(0, 0, 0) A.translate(vector=[-1, -1, -1], dist=3.4641016151377544, update=True, throw=False) print(A) """ distances = (np.array(vector) / np.linalg.norm(vector)) * dist if update: self.x += distances[0] self.y += distances[1] self.z += distances[2] if update and throw: return deepcopy(self) if not update and throw: return Point3d(self.x+distances[0], self.y+distances[1], self.y+distances[2])
[docs] def translate_to(self, *, point=None, update=False, throw=True): """Translate self to the location of ``point``.""" if not point: raise ValueError('Must provide point object. Could also be coord.') xloc, yloc, zloc = Point3d.validate_single_point_input(point) if update: self.x, self.y, self.z = xloc, yloc, zloc if update and throw: # Retain this here, as the behaviour may change later on return deepcopy(self) if not update and throw: return Point3d(xloc, yloc, zloc)
[docs] @staticmethod def val_points_and_get_coords(points): """Docstring.""" if not points: raise ValueError('Points OR coords not provided.') if type(points) in dth.dt.ITERABLES: if len(set(type(point) for point in points)) != 1: raise ValueError('Points array contains multiple datatypes.') else: if find_spec_of_points(points) not in ('Point2d', 'p2d_leanest'): raise ValueError('Invalid datatype of the proivided single point.') points = [points] # -------------------------------------------------- valid = False if find_spec_of_points(points[0]) in 'Point3d': x, y, valid = [p.x for p in points], [p.y for p in points], True z = [p.z for p in points] if find_spec_of_points(points[0]) == 'p3d_leanest': x, y, valid = [p._x for p in points], [p.y for p in points], True z = [p.z for p in points] if find_spec_of_points(points) == 'type-[1,2,3]': x, y, valid = [points[0]], [points[1]], True z = [p[2] for p in points] if find_spec_of_points(points) == 'type-[[1,2,3]]': x, y, valid = [points[0][0]], [points[0][1]], True z = [points[0][2] for p in points] if find_spec_of_points(points) == 'type-[[1,2,3],[4,5,6],[7,8,9]]': x, y, valid = [p[0] for p in points], [p[1] for p in points], True z = [p[2] for p in points] if find_spec_of_points(points) == 'type-[[1,2,3,4],[1,2,3,4],[1,2,3,4]]': x, y, valid = points[0], points[1], True z = points[2] if not valid: raise ValueError('Invalid points input.') return x, y
[docs] def attach_feature(self, *, feature=None, feature_id=None): """Attach a feature object to ``self.f[feature_id]``.""" if not feature: raise ValueError('feature cannot be empty.') if not feature_id: raise ValueError('feature_id cannot be empty.') fname = feature.__class__.__name__ if not hasattr(self, 'f'): self.f = {} if fname not in self.f: self.f[fname] = {} if feature_id in self.f[fname].keys(): raise KeyError('Cannot attach feature. feature_id: ' f'{feature_id} already in dict {self.f[fname]}.') self.f[fname][feature_id] = feature
[docs] def find_neigh_point_by_distance(self, *, plist=None, plane='xy', r=0, on_boundary=True, threshold_perp_dist=0.0): """ Things to do: 1. validations 2. consider plane in calculations. If plane is None, then all point locatyions within or withon r will be returned. If plane is specified differenyly, then return locations of those points which aactually satisfy both r and contained on or close to the plane. The closeneess sho9uld be determined by threshold_perp_dist, which is sthe threshold perpendicualr distance between a candidate point and yhe plane. """ plist = np.array(plist) if type(r) not in dth.dt.NUMBERS: raise TypeError('Invalid r type.') sd = self.squared_distance(plist) if r <= self.ε: return np.argwhere(sd == sd.min()).squeeze() else: if on_boundary: return np.argwhere(sd <= r) else: return np.argwhere(sd < r)
[docs] def find_neigh_point_by_count(self, *, plist=None, n=None, plane='xy'): """ Find the ``n`` nearest points in ``plist`` by squared distance. Parameters ---------- plist : array-like Pool of candidate points. n : int Number of nearest neighbours to return. plane : str, optional Reserved for plane-filtered searches. Currently unused. Returns ------- tuple of numpy.ndarray Indices of the ``n`` nearest points in ``plist``. Examples -------- .. code-block:: python from upxo.geoEntities.point3d import Point3d as p3d p3d(0, 0, 0).find_neigh_point_by_count( plist=[[1, 2, 0], [10, 12, 0], [0, -5, 0], [0, 0, 0]], n=2) """ # Validate plist # Validate n if not isinstance(n, int) or n == 0: raise TypeError('n must be an int type and non-zero.') if n > len(plist): raise ValueError('n is greater than len(plist).') sd = self.squared_distance(plist) return np.where(np.in1d(sd, np.sort(sd)[:n]))
[docs] def find_neigh_mulpoint_by_distance(self, *, mplist=None, plane='xy', r=0, tolf=-1): """Find neighbouring multi-point objects within radius ``r``. Not yet implemented.""" # Use the ckdtree option. raise NotImplementedError("find_neigh_mulpoint_by_distance is not yet implemented.")
[docs] def find_neigh_edge_by_distance(self, *, elist=None, plane='xy', refloc='starting', r=0): """Find neighbouring edges within radius ``r``. Not yet implemented.""" raise NotImplementedError("find_neigh_edge_by_distance is not yet implemented.")
[docs] def find_neigh_muledge_by_distance(self, *, melist=None, plane='xy', refloc='starting', r=0): """Find neighbouring multi-edges within radius ``r``. Not yet implemented.""" raise NotImplementedError("find_neigh_muledge_by_distance is not yet implemented.")
[docs] def find_neigh_xtal_by_distance(self, *, xlist=None, plane='xy', refloc='starting', r=0): """Find neighbouring crystals within radius ``r``. Not yet implemented.""" raise NotImplementedError("find_neigh_xtal_by_distance is not yet implemented.")
[docs] def set_gmsh_props(self, prop_dict): """Apply GMSH mesh properties from ``prop_dict`` to this point. Not yet implemented.""" raise NotImplementedError("set_gmsh_props is not yet implemented.")
[docs] def array_translation(self, *, ncopies=10, vector=[[0, 0, 0], [0, 0, 1]], spacing='constant'): """Generate an array of translated copies along ``vector``. Not yet implemented.""" raise NotImplementedError("array_translation is not yet implemented.")
[docs] def lies_on_which_line(self, *, llist=None, consider_ends=True): """Return which line(s) in ``llist`` this point lies on. Not yet implemented.""" raise NotImplementedError("lies_on_which_line is not yet implemented.")
[docs] def lies_in_which_xtal(self, *, xlist=None, cosider_boundary=True, consider_boundary_ends=True): """Return which crystal(s) in ``xlist`` contain this point. Not yet implemented.""" raise NotImplementedError("lies_in_which_xtal is not yet implemented.")
[docs] def make_vtk_point(self, z=0): """ Create a VTK point dataset from self. Parameters ---------- z : float, optional Unused; retained for API compatibility. Returns ------- dict Dictionary with keys ``'id'`` (point ID), ``'pd'`` (``vtkPolyData``), and ``'help'`` (usage hint string). Examples -------- .. code-block:: python from upxo.geoEntities.point3d import Point3d as p3d A = p3d(10, 12, 100) vtkobj = A.make_vtk_point() x, y, z = vtkobj['pd'].GetPoint(vtkobj['id']) print(x, y, z) """ points = vtk.vtkPoints() point_id = points.InsertNextPoint(self.x, self.y, self.z) poly_data = vtk.vtkPolyData() poly_data.SetPoints(points) return {'id': point_id, 'pd': poly_data, 'help': "return['pd'].GetPoint(return['id'])"}
[docs] def make_shape(self): """Create a geometric shape representation of this point. Not yet implemented.""" raise NotImplementedError("make_shape is not yet implemented.")
'''def isinstance_many(tocheck, dtype): """ Check if all elements of tocheck belongs to a valid dtype. Arguments --------- tocheck: An iterable of data. dtype: Valid datatype, in dth.dt.ITERABLES Return ------ list of bools. True indicates element belonging to dtype Example ------- from upxo.geoEntities.point3d import p2d_leanest, p3d_leanest a = [p2d_leanest(1, 2), p3d_leanest(1, 2, 1)] isinstance_many(a, p3d_leanest) Author ------ Dr. Sunil Anandatheertha """ if type(tocheck) not in dth.dt.ITERABLES: tocheck = (tocheck, ) return [isinstance(tc, dtype) for tc in tocheck] def all_isinstance(dtype, *args): if len(args) > 0: print(args) return all(isinstance(arg, dtype) for arg in args) '''