A modern python library for 3D homogenous transforms and coordinate system utilities.
Project description
Polyframe
A fast, flexible, zero-cost Python library for 3D homogeneous transforms and arbitrary coordinate-system conventions.
🚀 Features
-
Arbitrary Cartesian frames
Define any right- or left-handed(x,y,z)basis via a simple enum.
Zero-cost: all “bring your own conventions” work happens at import time. -
Flexible spherical conventions
Compute azimuth/elevation, φ/θ or latitude/longitude with pluggable:- signed vs. unsigned angles
- CW vs. CCW positive rotation
- polar vs. elevation definitions
- custom “up”/“forward”/“lateral” axes
-
Effortless re-framing
Change the basis of aTransformin one call:from polyframe import FrameRegistry, Direction, Transform tr_world = Transform.from_values(translation=[1,2,3]) cs_robot = FrameRegistry.from_directions( Direction.RIGHT, Direction.FORWARD, Direction.UP ) tr_robot = tr_world.change_coordinate_system(cs_robot)
-
Quaternion & Euler support
Apply quaternion or Euler rotations directly:tr = Transform() tr_q = tr.apply_quaternion([0,0,0,1]) # [x,y,z,w] tr_e = tr.apply_euler_rotation(roll, pitch, yaw)
-
Distance & direction utilities
distance_to(),vector_to(),direction_to()
-
Numba-accelerated core routines
Under the hood, heavy linear-algebra paths (look_at, angle computations, quaternion ↔ matrix) are JIT-compiled for max throughput. -
Memory-efficient
Coordinate frames are static types; no per-instance overhead for storing conventions.
📦 Installation
pip install polyframe
🎬 Quickstart
from polyframe import FrameRegistry, Direction, Transform
# 1) identity at origin, facing +X
tr = Transform()
# 2) translate to (1,2,3)
tr = tr.apply_translation([1,2,3])
# 3) rotate via Euler angles
tr = tr.apply_euler_rotation(roll=0, pitch=45, yaw=90)
# 4) apply a quaternion
tr = tr.apply_quaternion([0,0,0,1]) # x,y,z,w
# 5) make it look at a point
tr = tr.look_at([4,5,6])
# 6) compute spherical angles
az, el, rng = tr.az_el_range_to([7,8,9])
# 7) compute φ/θ
phi, theta = tr.phi_theta_to([1,1,0])
# 8) distance/direction helpers
dist = tr.distance_to([2,2,2])
vec = tr.vector_to([2,2,2])
dirn = tr.direction_to([2,2,2])
# 9) re-frame into a robot basis
robot_cs = FrameRegistry.from_directions(
Direction.FORWARD, Direction.DOWN, Direction.LEFT
)
tr_robot = tr.change_coordinate_system(robot_cs)
🔍 Coordinate-System Conventions
Cartesian frames
Choose from any of 48 valid (x_dir,y_dir,z_dir) triples:
from polyframe import Direction, FrameRegistry
# World: X forward, Y left, Z up
world_cs = FrameRegistry.from_directions(
Direction.FORWARD,
Direction.LEFT,
Direction.UP,
)
# Robot: X right, Y forward, Z down
robot_cs = FrameRegistry.from_directions(
Direction.RIGHT,
Direction.FORWARD,
Direction.DOWN,
)
Each frame type exposes .forward / .backward / .left / .right / .up / .down unit vectors.
Spherical coordinates
- Azimuth/Elevation (
az_el_range_to) - Longitude/Latitude (
lat_lon_to) - φ/θ (polar) (
phi_theta_to)
All accept flags:
| Flag | Meaning |
|---|---|
degrees |
degrees (default) or radians |
signed_* |
signed (±180°/π) vs. unsigned (0…360°/2π) |
counterclockwise_* |
CCW-positive vs. CW-positive |
polar (φ/θ only) |
θ as polar (0…π) vs. elevation (±90°) |
flip_* |
flip sign of elevation/latitude/θ |
⚙️ API Highlights
from polyframe import Transform
# Construction
tr = Transform() # identity
tr2 = Transform.from_values(
translation=[1,2,3],
rotation=[[...]], # 3×3
scale=[2,2,2],
)
# Translation / Rotation / Scale
tr_t = tr.apply_translation([1,0,0])
tr_r = tr.apply_rotation(R) # 3×3
tr_q = tr.apply_quaternion(q) # 4-vector [x,y,z,w]
tr_e = tr.apply_euler_rotation(roll,pitch,yaw)
tr_s = tr.apply_scale([2,3,4])
# Inverse / Combine
inv = tr.inverse()
inv_ip = tr.inverse(inplace=True)
C = tr @ tr2 # compose
# Point / Vector
p2 = tr.transform_point([1,2,3])
v2 = tr.transform_vector([1,0,0])
# Re-frame
tr_new = tr.change_coordinate_system(other_frame)
# Look-at
tr_look = tr.look_at([x,y,z])
# Distance & Direction
d = tr.distance_to([x,y,z])
v = tr.vector_to([x,y,z])
dir = tr.direction_to([x,y,z])
# Angles
az, el, rng = tr.az_el_range_to([x,y,z])
phi, th = tr.phi_theta_to([x,y,z])
lat, lon = tr.lat_lon_to([x,y,z])
See the full docs.
🤝 Contributing
- Fork
- Add a branch
- Write tests under
tests/ - PR — must pass CI (including Numba builds)
📄 License
Apache 2.0 — see LICENSE.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file polyframe-0.1.4.tar.gz.
File metadata
- Download URL: polyframe-0.1.4.tar.gz
- Upload date:
- Size: 30.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
47bd6c711c9554ed6ab5584fa8420112f004dda705b983c0ac64966731147ea7
|
|
| MD5 |
7a94c6f872927f09005c5460dcd48caf
|
|
| BLAKE2b-256 |
79d96f27bc782a344a185a734d3245fa8ec4603a5e4b43653aa7cf7487474e6c
|
File details
Details for the file polyframe-0.1.4-py3-none-any.whl.
File metadata
- Download URL: polyframe-0.1.4-py3-none-any.whl
- Upload date:
- Size: 21.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db2f76e9c6ccc826457550648ae058502c930cf99670647f76fdfdf27cc8e673
|
|
| MD5 |
a39d00c85a9bbebb341ddff282d6d248
|
|
| BLAKE2b-256 |
c28116247b4774221332a9a968a2a2215b01e9e753ca69ec8020a5b927c1cae5
|