Skip to content

Point3D

Represents a single 3D point.

Parameters

FieldTypeDescription
datanp.ndarray | list | tupleArray-like input, converted to a contiguous float32 array of shape (3,): [x, y, z].

Raises

ExceptionCondition
TypeErrordata can't be converted to a float32 array (e.g. ragged nested lists, non-numeric elements)
ValueErrorThe converted array isn't 1-D, its length isn't 3, or it contains a non-finite value (NaN/Inf)

Attributes

AttributeTypeDescription
datanp.ndarrayThe wrapped point, shape (3,). Reading it returns a copy, so mutating the result doesn't affect the Point3D; assigning a new value re-validates it the same way as construction.
shapetuple[int, ...]Always (3,).
ndimintAlways 1.
dtypenp.dtypeAlways float32.
sizeintAlways 3.
shape_specClassVar[tuple[int, ...]]Class-level shape contract, (3,), inherited from Vector3D. Same for every Point3D instance.

Methods

MethodDescription
to_numpy(copy=True)Returns the point as np.ndarray, shape (3,). Pass copy=False to get a reference to the internal array instead — faster, but mutating it mutates the Point3D too.
copy()Returns a new Point3D with an independent copy of the data.
Point3D.coerce(value)Returns value unchanged if it's already a Point3D; wraps a np.ndarray/list/tuple into one otherwise. Raises TypeError for anything else — including a plain Vector3D, since isinstance against Point3D doesn't match its own parent class.

Operators

OperationBehavior
point == otherTrue only if other is also exactly a Point3D (not a Vector3D or any other type, even with identical coordinates) with equal values (NaN counts as equal to NaN). False for anything else.
len(point)Always 3 — the length of axis 0 of the underlying (3,) array, not a "number of points" count.
np.asarray(point)Works directly — NumPy functions accept a Point3D in place of an np.ndarray. Always returns a copy; use to_numpy(copy=False) for a zero-copy view.
point + arr, point - arr, point * arr, point / arrNot implemented on Point3D itself (no __add__/__array_ufunc__). As verified for Point2D: with a NumPy array operand, NumPy coerces the Point3D via __array__ and performs plain elementwise arithmetic — the result is a plain np.ndarray, not a Point3D.
hash(point)Not supported — raises TypeError: unhashable type: 'Point3D'.

Visualization

datatypes.visualize(point, entity_path=..., label=...) logs the point as a single rerun 3D point (rr.Points3D(positions=point.data.reshape(1, 3))) — the same handler also backs Position3D. Pass label as a single str to additionally render a floating text label at the point's position.

Example

python
"""Demonstrates the Telekinesis Point3D datatype."""

import time

import numpy as np
from loguru import logger
import rerun as rr

from telekinesis import datatypes

def point3d_example():
    """Demonstrate creation, access, visualization, update, NumPy arithmetic, and serialization."""

    # ======================= Create ============================================
    point = [1.0, 2.0, 3.0]
    point3d = datatypes.Point3D(point)

    logger.info(f"Original Point3D: {point3d}")

    # ======================= Inspect ===========================================
    data = point3d.data
    shape = point3d.shape
    size = point3d.size
    dtype = point3d.dtype
    ndim = point3d.ndim
    numpy_point3d = point3d.to_numpy()
    point3d_copy = point3d.copy()

    logger.info(f"shape={shape}, size={size}, ndim={ndim}, dtype={dtype}")
    logger.info(f"Underlying data: {data}")
    logger.info(f"NumPy array: {numpy_point3d}")
    logger.info(f"Copy: {point3d_copy}")

    # ======================= Visualize =========================================
    rr.init("point3d_example", spawn=True)
    datatypes.visualize(point3d, entity_path="/Point3D", label="My Point3D")

    # ======================= Update ============================================
    new_data = [4.0, 5.0, 6.0]
    point3d.data = new_data
    logger.info(f"Updated Point3D: {point3d}")
    datatypes.visualize(point3d, entity_path="/Point3D/updated", label="Updated Point3D")

    # ======================= Arithmetic ========================================
    point_sum = point3d + np.array([1.0, 1.0, 1.0])
    point_diff = point3d - np.array([1.0, 1.0, 1.0])
    point_prod = point3d * np.array(2.0)
    point_quot = point3d / np.array(2.0)
    logger.info(f"Sum: {point_sum}, Difference: {point_diff}")
    logger.info(f"Product: {point_prod}, Quotient: {point_quot}")

    # ======================= Serialize / Deserialize ===========================
    start = time.perf_counter()
    serialized = datatypes.serialize(point3d)
    serialization_ms = (time.perf_counter() - start) * 1000

    start = time.perf_counter()
    deserialized = datatypes.deserialize(serialized)["param_0"]
    deserialization_ms = (time.perf_counter() - start) * 1000

    logger.info(f"Deserialized Point3D: {deserialized}")
    logger.info(f"Round-trip successful: {deserialized.data == new_data}")
    logger.info(f"Serialization time: {serialization_ms:.3f} ms")
    logger.info(f"Deserialization time: {deserialization_ms:.3f} ms")


if __name__ == "__main__":
    point3d_example()