Skip to main content

A modern python library for 3D homogenous transforms and coordinate system utilities.

Project description

Polyframe

PyPI version
License

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 a Transform in one call:

    from polyframe.frame_registry import FrameRegistry, Direction
    from polyframe.transform import 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_basis_to(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.frame_registry import FrameRegistry, Direction
from polyframe.transform import 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_basis_to(robot_cs)

🔍 Coordinate-System Conventions

Cartesian frames

Choose from any of 48 valid (x_dir,y_dir,z_dir) triples:

from polyframe.frame_registry 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.transform 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_basis_to(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

  1. Fork
  2. Add a branch
  3. Write tests under tests/
  4. 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

polyframe-0.1.2.tar.gz (30.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

polyframe-0.1.2-py3-none-any.whl (21.1 kB view details)

Uploaded Python 3

File details

Details for the file polyframe-0.1.2.tar.gz.

File metadata

  • Download URL: polyframe-0.1.2.tar.gz
  • Upload date:
  • Size: 30.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for polyframe-0.1.2.tar.gz
Algorithm Hash digest
SHA256 ba90017a2c65dc3dc2f5fe88d8e43327a335266ff3d164bf3c5224f8f5666221
MD5 83ff25029e57379982e150d9e8ce8ec4
BLAKE2b-256 d5057aa3a8cb1958ef92a627c2e9a60f91e7c1b0ac9ce778f8803719c1097323

See more details on using hashes here.

File details

Details for the file polyframe-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: polyframe-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 21.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.9

File hashes

Hashes for polyframe-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 7377541afdf312b4564dc603b12d33c417022a716e1ff79022a01dcc24ae8fe1
MD5 129b6a17e81a71820e67bb48783d991c
BLAKE2b-256 abb44871510cafb093451b90f09ade10e0c22dd1a7edcafc8b65a2c52a860904

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page