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: object

Collection 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.pdist for pairwise distances.

Type:

callable

metadata

User/provenance metadata carried with this point cloud.

Type:

dict

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 match self.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' grows self.coords by the supplied rows. Default is 'add'.

Returns:

Modifies self.coords in 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 coords set from point_coords.

Return type:

MPoint3d

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:

MPoint3d

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 applying face_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 bounds and enforce_bounds are 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:

MPoint3d

Raises:

ValueError – If face_clearance is non-zero without bounds, or if enforce_bounds is 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 exactly n points.

  • spacing (float, optional) – Lattice spacing. If omitted, n must 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/a ratio. Ignored for FCC and BCC.

  • metadata (dict, optional) – Additional metadata merged into the generated seed metadata.

Returns:

Lattice seed point cloud.

Return type:

MPoint3d

Raises:

ValueError – If neither spacing nor n is 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:

MPoint3d

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:

MPoint3d

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:

MPoint3d

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:

MPoint3d

Raises:

ValueError – If inputs are invalid or if n seeds cannot be placed within max_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:

MPoint3d

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:
  • bounds (array-like, shape (3, 2), optional) – RVE bounds used when periodic distances are requested. If omitted, bounds are resolved from self.metadata['bounds'] or from the coordinate extents.

  • periodic (bool or iterable of bool, optional) – Periodic boundary flags. If omitted, metadata is used.

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 returns nan for that point.

distances_to_rve_faces(bounds=None)[source]

Return distances to xmin, xmax, ymin, ymax, zmin, zmax faces.

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:
  • bounds (array-like, shape (3, 2), optional) – RVE bounds.

  • threshold (float, optional) – Distance threshold used to classify a seed as near a face. If omitted, self.metadata['face_clearance'] is used when present.

Returns:

Counts for interior_zone, face_zone, edge_zone, and corner_zone together with the applied threshold.

Return type:

dict

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:

dict

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 valid and errors keys.

Return type:

dict

Raises:

ValueError – If throw is 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:
  • x (array-like, shape (N,)) – Coordinate components of the N points.

  • y (array-like, shape (N,)) – Coordinate components of the N points.

  • z (array-like, shape (N,)) – Coordinate components of the N points.

Returns:

New instance with coords of shape (N, 3).

Return type:

MPoint3d

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 coords of shape (N, 3) (transposed from xyz).

Return type:

MPoint3d

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 MPoint2d by appending a constant z-value.

Parameters:
  • mp2d (MPoint2d) – Source 2D multi-point object.

  • zloc (float, optional) – Constant z-coordinate to append.

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_ref maps 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, rot values are interpreted as degrees; if False, as radians. Default is True.

Returns:

New instance with transformed coordinates.

Return type:

MPoint3d

Notes

Rotation is applied as successive Rx → Ry → Rz matrix multiplication about rot_ref. Translation is applied last by centering on translate_ref and adding dxyz. 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 MSline3d endpoint 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 to from_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, rot is in degrees; if False, in radians. Default is True.

Returns:

New instance containing the grid points after the rigid-body transform.

Return type:

MPoint3d

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:

int

property centroid

Mean 3D coordinate of all points.

Returns:

Centroid coordinate with shape (3,).

Return type:

numpy.ndarray

property points

Return point objects built from self.coords.

Returns:

One Point3d object per coordinate row.

Return type:

list of Point3d

property x

x-coordinates of all points.

Returns:

One-dimensional x-coordinate array.

Return type:

numpy.ndarray

property y

y-coordinates of all points.

Returns:

One-dimensional y-coordinate array.

Return type:

numpy.ndarray

property z

z-coordinates of all points.

Returns:

One-dimensional z-coordinate array.

Return type:

numpy.ndarray

property ckd_tree

Build and return a cKDTree for 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.coords to point.

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.coords to point.

Return type:

numpy.ndarray, shape (N,)

squared_distance_to_centroid(points, validate_points=True, points_type='numpy')[source]

Compute squared distances from self.centroid to 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 True the input is validated and converted automatically. When confident that points is an (M, 3) NumPy array, set to False to skip validation overhead. Default is True.

  • 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.centroid to a set of 3-D points.

Parameters:
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 on self.tree. Default is False.

  • throw (bool, optional) – If True, return the tree object. Default is False.

  • balance (bool, optional) – Passed as balanced_tree to cKDTree. Default is True.

Returns:

The built tree when throw=True; otherwise None.

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:

float

get_self_distance_min()[source]

Return the minimum pairwise distance among all points.

Returns:

Minimum pairwise distance in self.coords.

Return type:

float

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 p in self.coords is a first-order neighbour of coord if |p[d] - coord[d]| <= vox_size for all three dimensions d (i.e. it fits within a 3×3×3 cubic stencil centred at coord). The tolerance multiplier k avoids 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.coords in the output. Default is True.

  • return_coords (bool, optional) – Include neighbour coordinate arrays in the output. Default is True.

  • return_input_coord (bool, optional) – Append coord to the return tuple. Default is False.

  • k (float, optional) – Tolerance multiplier applied to vox_size to avoid floating-point boundary misses. Default is 1.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:

tuple

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| <= C where 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 CUBIC suffix indicates this method is designed for cubic lattices only.

Parameters:
  • coord (array-like, shape (3,)) – Coordinate of the voxel to assess. Must be a member of self.coords.

  • vs (float) – Voxel size used to define the 3×3×3 stencil.

Returns:

True if 2–4 same-state neighbours exist (a surface can be formed), False if outside that range, None if coord is not found in self.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)
get_local_tn(coord, k=5)[source]

Find the local tangent plane and normal vector at a coordinate.

Parameters:
  • coord (array-like, shape (3,)) – Query point. Must be a member of self.coords.

  • k (int, optional) – Number of nearest neighbours used to fit the tangent plane. Default is 5.

Returns:

Not yet implemented.

Return type:

None

find_intersection_voxels_with_line(sl3d, cod)[source]

Find all voxels in self.coords that intersect a 3-D line within a cut-off distance.

Parameters:
  • sl3d (Sline3d) – UPXO 3-D straight-line object to intersect against.

  • cod (float) – Cut-off distance; only voxels within this distance of sl3d are considered to intersect.

Returns:

Not yet implemented.

Return type:

None