Contour
Represents one contour: an ordered list of 2D polygon vertices.
Parameters
| Field | Type | Description |
|---|---|---|
points | list[list[int]] | np.ndarray | Contour vertices, converted to a contiguous int64 array of shape (K, 2). K can be 0. |
Raises
| Exception | Condition |
|---|---|
ValueError | points, after conversion to int64, isn't 2-D or its second axis isn't length 2 |
Conversion of points to int64 (np.asarray(points, dtype=np.int64)) isn't wrapped in a try/except; a value NumPy can't cast raises whatever error NumPy itself produces.
Attributes
| Attribute | Type | Description |
|---|---|---|
points | np.ndarray | Defensive copy of the contour vertices, shape (K, 2), int64. |
Methods
| Method | Description |
|---|---|
Contour.coerce(value) | Returns value unchanged if it's already a Contour; wraps a np.ndarray/list into one otherwise. Raises TypeError for anything else. |
Operators
| Operation | Behavior |
|---|---|
contour == other | True only if other is a Contour with an equal points array. NotImplemented (so False) for any other type. |
len(contour) | The vertex count, K. |
hash(contour) | Not supported, despite being immutable after construction (__hash__ = None). |
repr(contour) | Contour(num_points=3) — verified empirically. |
Visualization
datatypes.visualize(contour, entity_path=...) logs the contour as a closed rerun 2D line strip (rr.LineStrips2D([strip])), where strip repeats the contour's first vertex at the end to close the polygon loop. Contour has no registered label handler — passing label= to visualize() for a Contour is silently ignored (no error, no label rendered).
Example
python
"""Demonstrates the Telekinesis Contour datatype."""
import time
import numpy as np
from loguru import logger
import rerun as rr
from telekinesis import datatypes
def contour_example():
"""Demonstrate creation, inspection, visualization, NumPy-based shifting, and serialization."""
# ======================= Create ============================================
contour = datatypes.Contour(
points=np.array([[118, 84], [134, 79], [150, 86], [139, 115]], dtype=np.int64),
)
logger.info(f"Original Contour: {contour}")
# ======================= Inspect ===========================================
points = contour.points
num_points = len(contour)
logger.info(f"Points: {points}")
logger.info(f"Number of points: {num_points}")
# ======================= Visualize =========================================
rr.init("contour_example", spawn=True)
datatypes.visualize(contour, entity_path="/Contour")
# ======================= Shift =============================================
shifted_points = points + np.array([10, 10], dtype=np.int64)
shifted_contour = datatypes.Contour(points=shifted_points)
logger.info(f"Shifted Contour: {shifted_contour}")
datatypes.visualize(shifted_contour, entity_path="/Contour/shifted")
# ======================= Serialize / Deserialize ===========================
start = time.perf_counter()
serialized = datatypes.serialize(shifted_contour)
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 Contour: {deserialized}")
logger.info(f"Round-trip successful: {deserialized == shifted_contour}")
logger.info(f"Serialization time: {serialization_ms:.3f} ms")
logger.info(f"Deserialization time: {deserialization_ms:.3f} ms")
if __name__ == "__main__":
contour_example()
