upxo.geoEntities.mulpoint3d module
Multi-point 3D geometric entity module for UPXO.
Provides MPoint3d, a collection class for N 3-D points stored as a
single (N, 3) NumPy array. Supports construction from coordinate arrays,
separated x/y/z lists, regular grids, and other UPXO point collections;
rigid-body operations (translation, rotation); spatial queries (kd-tree,
nearest neighbours, distance computations); and surface-topology checks for
voxel-based meshes.
Classes
- MPoint3d
Collection of 3-D points backed by an
(N, 3)NumPy array.
Usage
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d
@author: Dr. Sunil Anandatheertha
- class upxo.geoEntities.mulpoint3d.MPoint3d(coords=None, metadata=None)[source]
Bases:
objectCollection of N 3-D points stored as a single
(N, 3)NumPy array.Provides construction class-methods, rigid-body operations (translation, rotation), spatial-query helpers (kd-tree, neighbour search, distance calculations), and surface-topology checks for voxel-based meshes.
- coords
Row-major array of 3-D coordinates: each row is
[x, y, z].- Type:
numpy.ndarray, shape (N, 3)
- tree
Spatial index, populated on demand by
maketree().- Type:
scipy.spatial.cKDTree or None
- pdist
Reference to
scipy.spatial.distance.pdistfor pairwise distances.- Type:
callable
Notes
The stored coordinate convention is always row-major
[x, y, z]. Construction helpers may add provenance metadata for downstream Voronoi seed workflows.Standard coordinate format
coords = np.array([[0, 0, 0], [1, 1, 1], [2, 3, 3], [4, 5, 6]])
- coords
- tree
- pdist
- metadata
- add(toadd=None, operation='add')[source]
Add to or append coordinates in
self.coords.- Parameters:
toadd (scalar, list, or numpy.ndarray, optional) –
Value(s) to add or append. Accepted shapes / types:
scalar number — broadcast-added to every coordinate.
[x, y, z]— added to every row as a 3-element offset.[[x, y, z]]— same as above, single-row list.(N, 3)array — element-wise add; must matchself.n.(3, N)array (transposed) — transposed before adding.
When
operation='append', the same shapes are supported but the rows are appended instead of added.operation ({'add', 'append'}, optional) –
'add'modifies coordinates in place;'append'growsself.coordsby the supplied rows. Default is'add'.
- Returns:
Modifies
self.coordsin place.- Return type:
None
Examples
Example 1 — scalar broadcast addition:
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d mulpoint3d = mp3d.from_coords(np.random.random((10, 3))) mulpoint3d.add(toadd=10, operation='add')
Example 2 — 3-element offset vector:
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d mulpoint3d = mp3d.from_coords(np.random.random((10, 3))) mulpoint3d.add(toadd=[-10, 20, 0], operation='add')
Example 3 — element-wise
(N, 3)array addition:from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d mulpoint3d = mp3d.from_coords(np.random.random((10, 3))) mulpoint3d.add(toadd=np.random.random((mulpoint3d.n, 3)), operation='add')
Example 4 — transposed
(3, N)array addition:from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d mulpoint3d = mp3d.from_coords(np.random.random((10, 3))) mulpoint3d.add(toadd=np.random.random((mulpoint3d.n, 3)).T, operation='add')
Example 5 — append rows:
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d mulpoint3d = mp3d.from_coords(np.random.random((10, 3))) mulpoint3d.add(toadd=np.random.random((10, 3)), operation='append')
- classmethod from_coords(point_coords, metadata=None)[source]
Instantiate from an
(N, 3)array or list of coordinate triples.- Parameters:
point_coords (array-like, shape (N, 3)) – Each row is a 3-D coordinate
[x, y, z].- Returns:
New instance with
coordsset frompoint_coords.- Return type:
Examples
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d point_coords = np.array([[0, 0, 0], [1, 1, 1], [2, 3, 3], [4, 5, 6]]) MULPOINT3D = mp3d.from_coords(point_coords) print(MULPOINT3D.coords)
- classmethod from_random_uniform(bounds=((0, 1), (0, 1), (0, 1)), n=100, seed=None, boundary='aperiodic', face_clearance=0.0, metadata=None)[source]
Generate uniformly distributed random 3D Voronoi seed points.
- Parameters:
bounds (array-like, shape (3, 2), optional) – Axis-aligned RVE bounds as
((xmin, xmax), (ymin, ymax), (zmin, zmax)). Default is the unit cube.n (int, optional) – Number of seed points to generate. Default is 100.
seed (int or None, optional) – Random seed for reproducibility. Default is None.
boundary ({'aperiodic', 'periodic'}, optional) – Intended downstream Voronoi boundary condition. The point coordinates are generated the same way, but the metadata carries periodic flags for tessellation code. Default is ‘aperiodic’.
face_clearance (float, optional) – Minimum Euclidean distance from every seed point to any RVE face. For an axis-aligned box this is implemented by sampling within the inner box obtained by offsetting all faces inward by this value. Default is 0.0.
metadata (dict or None, optional) – Extra metadata to merge into the generated seed metadata.
- Returns:
Seed point cloud with generation metadata attached.
- Return type:
- classmethod from_custom_seeds(coords, bounds=None, boundary='aperiodic', face_clearance=0.0, enforce_bounds=True, metadata=None)[source]
Create Voronoi seed points from user-supplied coordinates.
- Parameters:
coords (array-like, shape (N, 3)) – User-provided seed coordinates.
bounds (array-like, shape (3, 2), optional) – RVE bounds as
((xmin, xmax), (ymin, ymax), (zmin, zmax)). If provided, the coordinates may be checked against the effective bounds after applyingface_clearance.boundary ({'aperiodic', 'periodic'}, optional) – Boundary-condition label to store in seed metadata.
face_clearance (float, optional) – Minimum distance expected between seeds and RVE faces. This is used for metadata and, when
boundsandenforce_boundsare provided, for bounds validation.enforce_bounds (bool, optional) – If True, require all coordinates to lie within the effective bounds.
metadata (dict, optional) – Additional metadata merged into the generated seed metadata.
- Returns:
Point cloud containing the custom seed coordinates and provenance metadata.
- Return type:
- Raises:
ValueError – If
face_clearanceis non-zero without bounds, or ifenforce_boundsis True and coordinates fall outside the effective bounds.
- classmethod from_lattice(lattice, bounds=((0, 1), (0, 1), (0, 1)), n=None, spacing=None, seed=None, boundary='aperiodic', face_clearance=0.0, jitter=0.0, ca_ratio=numpy.sqrt, metadata=None)[source]
Generate FCC, BCC, or HCP Voronoi seed lattice points.
- Parameters:
lattice ({'fcc', 'bcc', 'hcp'}) – Lattice family used to place candidate seed points.
bounds (array-like, shape (3, 2), optional) – RVE bounds as
((xmin, xmax), (ymin, ymax), (zmin, zmax)).n (int, optional) – Number of seed points to return. If provided with
spacing=None, spacing is estimated and candidates are down-selected to exactlynpoints.spacing (float, optional) – Lattice spacing. If omitted,
nmust be supplied.seed (int or None, optional) – Random seed used for down-selection and jitter.
boundary ({'aperiodic', 'periodic'}, optional) – Boundary-condition label stored in metadata.
face_clearance (float, optional) – Inward offset from every RVE face used to define the effective lattice-generation bounds.
jitter (float, optional) – Uniform random perturbation magnitude applied independently to generated lattice coordinates.
ca_ratio (float, optional) – HCP
c/aratio. Ignored for FCC and BCC.metadata (dict, optional) – Additional metadata merged into the generated seed metadata.
- Returns:
Lattice seed point cloud.
- Return type:
- Raises:
ValueError – If neither
spacingnornis supplied, if spacing is invalid, or if too few lattice candidates can be generated.
- classmethod from_fcc_lattice(**kwargs)[source]
Generate FCC lattice Voronoi seed points.
- Parameters:
**kwargs – Keyword arguments forwarded to
from_lattice().- Returns:
FCC lattice seed point cloud.
- Return type:
- classmethod from_bcc_lattice(**kwargs)[source]
Generate BCC lattice Voronoi seed points.
- Parameters:
**kwargs – Keyword arguments forwarded to
from_lattice().- Returns:
BCC lattice seed point cloud.
- Return type:
- classmethod from_hcp_lattice(**kwargs)[source]
Generate HCP lattice Voronoi seed points.
- Parameters:
**kwargs – Keyword arguments forwarded to
from_lattice().- Returns:
HCP lattice seed point cloud.
- Return type:
- classmethod from_hard_core_random(bounds=((0, 1), (0, 1), (0, 1)), n=100, min_distance=0.05, seed=None, boundary='aperiodic', face_clearance=0.0, max_attempts=100000, metadata=None)[source]
Generate random seeds with a minimum seed-to-seed distance.
- Parameters:
bounds (array-like, shape (3, 2), optional) – RVE bounds as
((xmin, xmax), (ymin, ymax), (zmin, zmax)).n (int, optional) – Number of accepted seed points to generate.
min_distance (float, optional) – Minimum permitted Euclidean distance between any two seeds.
seed (int or None, optional) – Random seed for reproducible rejection sampling.
boundary ({'aperiodic', 'periodic'}, optional) – Boundary-condition label stored in metadata. Fully periodic clouds use minimum-image distance checks.
face_clearance (float, optional) – Inward offset from every RVE face used to define the effective sampling bounds.
max_attempts (int, optional) – Maximum number of candidate draws before failing.
metadata (dict, optional) – Additional metadata merged into the generated seed metadata.
- Returns:
Hard-core random seed point cloud.
- Return type:
- Raises:
ValueError – If inputs are invalid or if
nseeds cannot be placed withinmax_attempts.
- classmethod from_cvt(bounds=((0, 1), (0, 1), (0, 1)), n=100, seed=None, boundary='aperiodic', face_clearance=0.0, iterations=20, samples_per_seed=40, batch_size=20000, metadata=None)[source]
Generate approximate centroidal Voronoi tessellation seed points.
- Parameters:
bounds (array-like, shape (3, 2), optional) – RVE bounds as
((xmin, xmax), (ymin, ymax), (zmin, zmax)).n (int, optional) – Number of seed points to generate.
seed (int or None, optional) – Random seed for reproducible initialization and sampling.
boundary ({'aperiodic', 'periodic'}, optional) – Boundary-condition label stored in metadata. Fully periodic clouds use minimum-image assignments during Lloyd updates.
face_clearance (float, optional) – Inward offset from every RVE face used to define the effective sampling bounds.
iterations (int, optional) – Number of Monte-Carlo Lloyd iterations.
samples_per_seed (int, optional) – Number of random sample points per seed and iteration.
batch_size (int, optional) – Batch size used for nearest-seed assignment.
metadata (dict, optional) – Additional metadata merged into the generated seed metadata.
- Returns:
Approximate CVT seed point cloud.
- Return type:
- Raises:
ValueError – If count, iteration, sampling, bounds, or batch parameters are invalid.
- nearest_neighbour_distances(bounds=None, periodic=None)[source]
Return nearest-neighbour distance for every seed point.
- Parameters:
- Returns:
Nearest-neighbour distance for each seed point.
- Return type:
numpy.ndarray, shape (N,)
Notes
Periodic distances use the minimum-image convention inside
bounds. A single-point cloud returnsnanfor that point.
- distances_to_rve_faces(bounds=None)[source]
Return distances to
xmin, xmax, ymin, ymax, zmin, zmaxfaces.- Parameters:
bounds (array-like, shape (3, 2), optional) – RVE bounds. If omitted, bounds are resolved from metadata or from coordinate extents.
- Returns:
Distance from each seed to the six RVE faces, ordered as
xmin, xmax, ymin, ymax, zmin, zmax.- Return type:
numpy.ndarray, shape (N, 6)
- minimum_face_distances(bounds=None)[source]
Return minimum distance from each seed to any RVE face.
- Parameters:
bounds (array-like, shape (3, 2), optional) – RVE bounds.
- Returns:
Minimum face distance for each seed.
- Return type:
numpy.ndarray, shape (N,)
- distances_to_rve_corners(bounds=None)[source]
Return distances from every seed to the 8 RVE corners.
- Parameters:
bounds (array-like, shape (3, 2), optional) – RVE bounds.
- Returns:
Distances from each seed to all RVE corners.
- Return type:
numpy.ndarray, shape (N, 8)
- minimum_corner_distances(bounds=None)[source]
Return minimum distance from each seed to any RVE corner.
- Parameters:
bounds (array-like, shape (3, 2), optional) – RVE bounds.
- Returns:
Minimum corner distance for each seed.
- Return type:
numpy.ndarray, shape (N,)
- distances_to_rve_edges(bounds=None)[source]
Return distances from every seed to the 12 finite RVE edges.
- Parameters:
bounds (array-like, shape (3, 2), optional) – RVE bounds.
- Returns:
Distances from each seed to the finite RVE edges.
- Return type:
numpy.ndarray, shape (N, 12)
- minimum_edge_distances(bounds=None)[source]
Return minimum distance from each seed to any RVE edge.
- Parameters:
bounds (array-like, shape (3, 2), optional) – RVE bounds.
- Returns:
Minimum edge distance for each seed.
- Return type:
numpy.ndarray, shape (N,)
- boundary_zone_counts(bounds=None, threshold=None)[source]
Count seeds close to no faces, one face, two faces, or three faces.
- Parameters:
- Returns:
Counts for
interior_zone,face_zone,edge_zone, andcorner_zonetogether with the applied threshold.- Return type:
Notes
This directly exposes the different practical effects of a face clearance near RVE faces, edges, and corners.
- seed_quality_summary(bounds=None, periodic=None, min_distance=None, face_clearance=None)[source]
Return compact seed-cloud QA statistics as a dictionary.
- Parameters:
bounds (array-like, shape (3, 2), optional) – RVE bounds used for boundary-distance diagnostics.
periodic (bool or iterable of bool, optional) – Periodic boundary flags used for nearest-neighbour distances.
min_distance (float, optional) – Minimum seed-to-seed distance to check.
face_clearance (float, optional) – Minimum distance from seeds to RVE faces to check. If omitted, metadata is used when available.
- Returns:
Summary containing nearest-neighbour statistics, face/edge/corner distances, zone counts, and violation counts.
- Return type:
- validate_seed_cloud(bounds=None, periodic=None, min_distance=None, face_clearance=None, throw=False)[source]
Validate seed cloud spacing and face clearance constraints.
- Parameters:
bounds (array-like, shape (3, 2), optional) – RVE bounds used for boundary-distance diagnostics.
periodic (bool or iterable of bool, optional) – Periodic boundary flags used for nearest-neighbour distances.
min_distance (float, optional) – Minimum seed-to-seed distance to enforce.
face_clearance (float, optional) – Minimum distance from seeds to RVE faces to enforce.
throw (bool, optional) – If True, raise an exception when validation fails.
- Returns:
Seed-quality summary augmented with
validanderrorskeys.- Return type:
- Raises:
ValueError – If
throwis True and one or more validation checks fail.
- classmethod from_x_y_z(x, y, z, metadata=None)[source]
Instantiate from separate x, y, and z coordinate arrays.
- Parameters:
- Returns:
New instance with
coordsof shape (N, 3).- Return type:
Examples
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d x, y, z = np.array([[0, 0, 0], [1, 1, 1], [2, 3, 3], [4, 5, 6]]).T MULPOINT3D = mp3d.from_x_y_z(x, y, z) print(MULPOINT3D.coords)
- classmethod from_xyz(xyz, metadata=None)[source]
Instantiate from a
(3, N)coordinate matrix.- Parameters:
xyz (numpy.ndarray, shape (3, N)) – Row 0 is x-coords, row 1 is y-coords, row 2 is z-coords.
- Returns:
New instance with
coordsof shape (N, 3) (transposed fromxyz).- Return type:
Examples
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d xyz = np.array([[0, 0, 0], [1, 1, 1], [2, 3, 3], [4, 5, 6]]).T MULPOINT3D = mp3d.from_xyz(xyz) print(MULPOINT3D.coords)
- classmethod from_mulpoint2d(mp2d, zloc=0.0)[source]
Construct from a
MPoint2dby appending a constant z-value.- Parameters:
- Raises:
NotImplementedError – Always raised because this constructor is not implemented.
- classmethod from_mulpoint3d(mulpoint3d=None, dxyz=[0.0, 0.0, 0.0], translate_ref=[0.0, 0.0, 0.0], rot=[0.0, 0.0, 0.0], rot_ref=[0.0, 0.0, 0.0], degree=True)[source]
Instantiate by applying rotation and translation to an existing
MPoint3d.- Parameters:
mulpoint3d (MPoint3d) – Source point collection to transform.
dxyz (list of float, optional) – Translation offsets
[dx, dy, dz]applied after rotation. Default is[0.0, 0.0, 0.0].translate_ref (list of float, optional) – Reference point for the translation step; the cloud is shifted so that
translate_refmaps to the origin before rotation. Default is[0.0, 0.0, 0.0].rot (list of float, optional) – Rotation angles
[rx, ry, rz]about the x, y, and z axes (CCW positive about positive axes). Default is[0.0, 0.0, 0.0].rot_ref (list of float, optional) – Centre of rotation in 3-D space. Default is
[0.0, 0.0, 0.0].degree (bool, optional) – If
True,rotvalues are interpreted as degrees; ifFalse, as radians. Default isTrue.
- Returns:
New instance with transformed coordinates.
- Return type:
Notes
Rotation is applied as successive Rx → Ry → Rz matrix multiplication about
rot_ref. Translation is applied last by centering ontranslate_refand addingdxyz. Refer to the examples for a concrete demonstration of each degree of freedom.Examples
Example 1 — no rotation, no translation (identity):
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d point_coords = np.array([[0, 0, 0], [1, 1, 1], [2, 2, 2], [3, 3, 3]]) mulpoint3d = mp3d.from_coords(point_coords) MULPOINT3D = mp3d.from_mulpoint3d(mulpoint3d=mulpoint3d, dxyz=[0.0, 0.0, 0.0], translate_ref=mulpoint3d.centroid, rot=[0.0, 0.0, 0.0], rot_ref=[0.0, 0.0, 0.0], degree=True) mulpoint3d.plot(MULPOINT3D.coords)
Example 2 — 45° rotation about x-axis, centred at origin:
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d point_coords = np.array([[0, 0, 0], [0, 1, 1], [0, 2, 2], [0, 3, 3]]) mulpoint3d = mp3d.from_coords(point_coords) MULPOINT3D = mp3d.from_mulpoint3d(mulpoint3d=mulpoint3d, dxyz=[0.0, 0.0, 0.0], translate_ref=mulpoint3d.centroid, rot=[45, 0.0, 0.0], rot_ref=[0.0, 0.0, 0.0], degree=True) mulpoint3d.plot(MULPOINT3D.coords)
Example 3 — 45° rotation about x-axis, non-origin rotation centre:
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d point_coords = np.array([[0, 0, 0], [0, 1, 1], [0, 2, 2], [0, 3, 3]]) mulpoint3d = mp3d.from_coords(point_coords) MULPOINT3D = mp3d.from_mulpoint3d(mulpoint3d=mulpoint3d, dxyz=[0.0, 0.0, 0.0], translate_ref=[0.0, 0.0, 0.0], rot=[45, 0.0, 0.0], rot_ref=[2.0, 0.0, 0.0], degree=True) mulpoint3d.plot(MULPOINT3D.coords)
Example 4 — rotation about x with centroid as both translate_ref and rot_ref:
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d point_coords = np.array([[0, 0, 0], [0, 1, 1], [0, 2, 2], [0, 3, 3]]) mulpoint3d = mp3d.from_coords(point_coords) MULPOINT3D = mp3d.from_mulpoint3d(mulpoint3d=mulpoint3d, dxyz=[0.0, 0.0, 0.0], translate_ref=mulpoint3d.centroid, rot=[45, 0.0, 0.0], rot_ref=[2.0, 0.0, 0.0], degree=True) mulpoint3d.plot(MULPOINT3D.coords)
Example 5 — rotation with rot_ref at centroid:
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d point_coords = np.array([[0, 0, 0], [0, 1, 1], [0, 2, 2], [0, 3, 3]]) mulpoint3d = mp3d.from_coords(point_coords) MULPOINT3D = mp3d.from_mulpoint3d(mulpoint3d=mulpoint3d, dxyz=[0.0, 0.0, 0.0], translate_ref=mulpoint3d.centroid, rot=[45, 0.0, 0.0], rot_ref=mulpoint3d.centroid, degree=True) mulpoint3d.plot(MULPOINT3D.coords)
Example 6 — combined rotation and x-translation:
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d point_coords = np.array([[0, 0, 0], [0, 1, 1], [0, 2, 2], [0, 3, 3]]) mulpoint3d = mp3d.from_coords(point_coords) MULPOINT3D = mp3d.from_mulpoint3d(mulpoint3d=mulpoint3d, dxyz=[1.0, 0.0, 0.0], translate_ref=mulpoint3d.centroid, rot=[45, 0.0, 0.0], rot_ref=mulpoint3d.centroid, degree=True) mulpoint3d.plot(MULPOINT3D.coords)
Example 7 — 3-axis translation, no rotation:
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d point_coords = np.array([[0, 0, 0], [0, 1, 1], [0, 2, 2], [0, 3, 3]]) mulpoint3d = mp3d.from_coords(point_coords) MULPOINT3D = mp3d.from_mulpoint3d(mulpoint3d=mulpoint3d, dxyz=[1.0, 1.0, -0.5], translate_ref=mulpoint3d.centroid, rot=[0, 0.0, 0.0], rot_ref=mulpoint3d.centroid, degree=True) mulpoint3d.plot(MULPOINT3D.coords)
- classmethod from_mulsline3d(msline3d)[source]
Construct from a
MSline3dendpoint collection.- Parameters:
msline3d (MSline3d) – Source 3D multi-line object.
- Raises:
NotImplementedError – Always raised because this constructor is not implemented.
- classmethod from_xyz_grid(xspec=[0, 1, 0.25], yspec=[0, 1, 0.25], zspec=[0, 1, 0.25], dxyz=[0.0, 0.0, 0.0], translate_ref=[0.0, 0.0, 0.0], rot=[0.0, 0.0, 0.0], rot_ref=[0.0, 0.0, 0.0], degree=True, metadata=None)[source]
Instantiate from a regular 3-D Cartesian grid with optional rigid-body transform.
Builds a meshgrid from the three axis specifications, flattens it to an
(N, 3)array, then delegates tofrom_mulpoint3d()to apply the requested rotation and translation.- Parameters:
xspec (list of float, optional) –
[xstart, xend, xincrement]for the x-axis grid. Default is[0, 1, 0.25].yspec (list of float, optional) –
[ystart, yend, yincrement]for the y-axis grid. Default is[0, 1, 0.25].zspec (list of float, optional) –
[zstart, zend, zincrement]for the z-axis grid. Default is[0, 1, 0.25].dxyz (list of float, optional) – Translation offsets
[dx, dy, dz]. Default is[0.0, 0.0, 0.0].translate_ref (list of float or str, optional) – Reference point for translation. Pass
'centroid'to use the grid centroid, or a[x, y, z]coordinate list. Default is[0.0, 0.0, 0.0].rot (list of float, optional) – Rotation angles
[rx, ry, rz]about x, y, z axes (CCW positive). Default is[0.0, 0.0, 0.0].rot_ref (list of float, optional) – Centre of rotation. Default is
[0.0, 0.0, 0.0].degree (bool, optional) – If
True,rotis in degrees; ifFalse, in radians. Default isTrue.
- Returns:
New instance containing the grid points after the rigid-body transform.
- Return type:
Examples
Example 1 — two grids, one base and one rotated by (5°, 5°, 5°):
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d xspec, yspec, zspec = [0, 1, 0.1], [0, 1, 0.1], [0, 1, 0.1] dxyz, translate_ref = [0.0, 0.0, 0.0], [0.0, 0.0, 0.0] mulpoint3d = mp3d.from_xyz_grid(xspec=xspec, yspec=yspec, zspec=zspec, dxyz=dxyz, translate_ref=translate_ref, rot=[0.0, 0.0, 0.0], rot_ref=[0.0, 0.0, 0.0], degree=True) MULPOINT3D = mp3d.from_xyz_grid(xspec=xspec, yspec=yspec, zspec=zspec, dxyz=dxyz, translate_ref=translate_ref, rot=[5.0, 5.0, 5.0], rot_ref=[0.0, 0.0, 0.0], degree=True) MULPOINT3D.plot(mulpoint3d.coords, primary_ms=50, secondary_ms=5)
- property n
Number of points in the collection.
- Returns:
Number of coordinate rows in
self.coords.- Return type:
- property centroid
Mean 3D coordinate of all points.
- Returns:
Centroid coordinate with shape
(3,).- Return type:
- property points
Return point objects built from
self.coords.
- property x
x-coordinates of all points.
- Returns:
One-dimensional x-coordinate array.
- Return type:
- property y
y-coordinates of all points.
- Returns:
One-dimensional y-coordinate array.
- Return type:
- property z
z-coordinates of all points.
- Returns:
One-dimensional z-coordinate array.
- Return type:
- property ckd_tree
Build and return a
cKDTreefor fast nearest-neighbour queries.- Returns:
Cached or newly built KD-tree over
self.coords.- Return type:
scipy.spatial.cKDTree
- squared_distances_to_point(point)[source]
Return squared Euclidean distances from all points to
point.- Parameters:
point (Point3d or array-like) – Target point. Validated via
val_point_and_get_coord.- Returns:
Squared distance from each point in
self.coordstopoint.- Return type:
numpy.ndarray, shape (N,)
- distances_to_point(point)[source]
Return Euclidean distances from all points to
point.- Parameters:
point (Point3d or array-like) – Target point.
- Returns:
Euclidean distance from each point in
self.coordstopoint.- Return type:
numpy.ndarray, shape (N,)
- squared_distance_to_centroid(points, validate_points=True, points_type='numpy')[source]
Compute squared distances from
self.centroidto a set of 3-D points.- Parameters:
points (list of Point3d or numpy.ndarray, shape (M, 3)) – Target points to measure from
self.centroid.validate_points (bool, optional) – When
Truethe input is validated and converted automatically. When confident thatpointsis an(M, 3)NumPy array, set toFalseto skip validation overhead. Default isTrue.points_type ({'numpy', 'upxo', 'shapely', 'coord', 'coord_pair'}, optional) – Type hint used only when
validate_points=False. Use'numpy'for plain NumPy arrays. Default is'numpy'.
- Returns:
Squared Euclidean distances from each target point to
self.centroid.- Return type:
numpy.ndarray, shape (M,)
Examples
Example 1 — validated UPXO point objects:
from upxo.geoEntities.mulpoint3d import MPoint3d MULPOINT3D = MPoint3d.from_coords(np.random.random((10, 3))) POINTS = make_p3d(2 + np.random.random((10, 3)), return_type='p3d') MULPOINT3D.squared_distance_to_centroid(POINTS, validate_points=True)
Example 2 — raw NumPy array, validation skipped:
POINTS = 2 + np.random.random((10, 3)) MULPOINT3D.squared_distance_to_centroid(POINTS, validate_points=False, points_type='numpy')
- distance_to_centroid(points, validate_points=True, points_type='numpy')[source]
Compute Euclidean distances from
self.centroidto a set of 3-D points.- Parameters:
points (list of Point3d or numpy.ndarray, shape (M, 3)) – Target points.
validate_points (bool, optional) – See
squared_distance_to_centroid(). Default isTrue.points_type (str, optional) – See
squared_distance_to_centroid(). Default is'numpy'.
- Returns:
Euclidean distances from each target point to
self.centroid.- Return type:
numpy.ndarray, shape (M,)
Examples
from upxo.geoEntities.mulpoint3d import MPoint3d MULPOINT3D = MPoint3d.from_coords(np.random.random((10, 3))) POINTS = 2 + np.random.random((10, 3)) MULPOINT3D.distance_to_centroid(POINTS, validate_points=False, points_type='numpy')
- convex_hull()[source]
Compute the convex hull of the 3D point set.
- Raises:
NotImplementedError – Always raised because convex-hull construction is not implemented.
- maketree(treeType='ckdtree', saa=False, throw=False, balance=True)[source]
Build a spatial index tree over
self.coords.- Parameters:
treeType ({'ckdtree', 'kdtree'}, optional) – Type of spatial index. Currently only
'ckdtree'is implemented. Default is'ckdtree'.saa (bool, optional) – If
True, store the built tree onself.tree. Default isFalse.throw (bool, optional) – If
True, return the tree object. Default isFalse.balance (bool, optional) – Passed as
balanced_treetocKDTree. Default isTrue.
- Returns:
The built tree when
throw=True; otherwiseNone.- Return type:
scipy.spatial.cKDTree or None
Examples
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d mulpoint3d = mp3d.from_coords(np.random.random((25, 3))) tree = mulpoint3d.maketree(treeType='ckdtree', throw=True) print(tree.data.shape)
- get_self_distance_max()[source]
Return the maximum pairwise distance among all points.
- Returns:
Maximum pairwise distance in
self.coords.- Return type:
- get_self_distance_min()[source]
Return the minimum pairwise distance among all points.
- Returns:
Minimum pairwise distance in
self.coords.- Return type:
- find_first_order_neigh_CUBIC(coord, vox_size, return_indices=True, return_coords=True, return_input_coord=False, k=1.000001)[source]
Find first-order (face+edge+vertex) neighbours of a voxel on a cubic lattice.
A point
pinself.coordsis a first-order neighbour ofcoordif|p[d] - coord[d]| <= vox_sizefor all three dimensions d (i.e. it fits within a 3×3×3 cubic stencil centred atcoord). The tolerance multiplierkavoids floating-point boundary misclassification.- Parameters:
coord (array-like, shape (3,)) – Centre voxel coordinate. Must be a member of
self.coords.vox_size (float) – Voxel edge length; defines the stencil half-width.
return_indices (bool, optional) – Include neighbour indices into
self.coordsin the output. Default isTrue.return_coords (bool, optional) – Include neighbour coordinate arrays in the output. Default is
True.return_input_coord (bool, optional) – Append
coordto the return tuple. Default isFalse.k (float, optional) – Tolerance multiplier applied to
vox_sizeto avoid floating-point boundary misses. Default is1.000001.
- Returns:
Contents depend on the flag combination:
(return_indices=True, return_coords=False)→(indices,)or(indices, coord)(return_indices=False, return_coords=True)→(coords,)or(coords, coord)(return_indices=True, return_coords=True)→(indices, coords, coord)or(indices, coords)
- Return type:
Notes
Designed for cubic lattices only. A voxel
[x, y, z]is a first-order neighbour of[cx, cy, cz]when|x-cx| <= A,|y-cy| <= B,|z-cz| <= Cwhere A = B = C =vox_size. This includes up to 26 neighbours in a full 3×3×3 grid.Examples
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d vs = 0.1 xspec, yspec, zspec = [0, 1, vs], [0, 1, vs], [0, 1, vs] X, Y, Z = np.meshgrid(np.arange(xspec[0], xspec[1], xspec[2]), np.arange(yspec[0], yspec[1], yspec[2]), np.arange(zspec[0], zspec[1], zspec[2])) mp = mp3d.from_coords(np.vstack((X.ravel(), Y.ravel(), Z.ravel())).T) mp.find_first_order_neigh_CUBIC((0.5, 0.5, 0.5), vs)
- check_if_point_can_host_a_single_surface_CUBIC(coord, vs)[source]
Check whether a voxel can have a single non-self-intersecting surface through it.
Given that the 3×3×3 neighbourhood contains 27 voxels in various ON/OFF states, a single surface can pass through the centre voxel and all ON-state neighbours only when the number of ON-state neighbours is at most 4 (empirical threshold; equivalent to at most 5 points including the centre).
The
CUBICsuffix indicates this method is designed for cubic lattices only.- Parameters:
- Returns:
Trueif 2–4 same-state neighbours exist (a surface can be formed),Falseif outside that range,Noneifcoordis not found inself.coords.- Return type:
bool or None
Examples
from upxo.geoEntities.mulpoint3d import MPoint3d as mp3d vs = 0.1 xspec, yspec, zspec = [0, 1, vs], [0, 1, vs], [0, 1, vs] X, Y, Z = np.meshgrid(np.arange(xspec[0], xspec[1], xspec[2]), np.arange(yspec[0], yspec[1], yspec[2]), np.arange(zspec[0], zspec[1], zspec[2])) mp = mp3d.from_coords(np.vstack((X.ravel(), Y.ravel(), Z.ravel())).T) coords = mp.find_first_order_neigh_CUBIC((0.5, 0.5, 0.5), vs, return_indices=False, return_coords=True, return_input_coord=False)[0] coord = np.array([0.5, 0.5, 0.5]) coord_loc = np.argwhere(np.all(coords == coord, axis=1)).squeeze() rand_4_locs = np.sort(np.random.choice(range(coords.shape[0]), 4, replace=False)) points_5_locs = np.unique(np.hstack((coord_loc, rand_4_locs))) coords_ON_state = coords[points_5_locs] fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.scatter(coords[:, 0], coords[:, 1], coords[:, 2], c='c', marker='o', alpha=0.1, s=200, edgecolors='black') ax.scatter(coords_ON_state[:, 0], coords_ON_state[:, 1], coords_ON_state[:, 2], c='b', marker='o', alpha=0.8, s=50, edgecolors='black') result = mp.check_if_point_can_host_a_single_surface_CUBIC(coord, vs) print("Can host single surface:", result)