A 2D/3D geometry library for CAD/CAM applications.
Project description
raygeo
A high-performance 2D/3D geometry library for Python, built in Rust with PyO3.
raygeo provides vector path construction, polygon boolean operations, curve fitting, path transformations, and geometric queries — all backed by a native Rust extension.
Concave hull, arc fitting, nesting, directional bites, raster power modulation, smoothing, linearization, HSM peeling, cylindrical transform, conical helix, 3D polyline offset, and 3D fillet polyline
Installation
pip install raygeo
Requires Python 3.10+ and a compatible platform (Linux, Windows, macOS Intel, or macOS Apple Silicon). Pre-compiled wheels are available on PyPI.
Quick Start
Building Paths
The Geometry class is the core abstraction. It stores a vector path as a
sequence of move, line, arc, and cubic Bezier commands. All mutating methods
return self for chaining:
from raygeo.geo import Geometry
# Create a 10x10 square
g = Geometry()
g.move_to(0, 0)
g.line_to(10, 0)
g.line_to(10, 10)
g.line_to(0, 10)
g.close_path()
print(g.area()) # 100.0
print(g.rect()) # (0.0, 0.0, 10.0, 10.0)
print(g.is_closed()) # True
Builder methods can be chained:
g = Geometry()
g.move_to(0, 0).line_to(10, 0).line_to(10, 10).line_to(0, 10).close_path()
You can also create paths from point lists:
triangle = Geometry.from_points([(0, 0), (10, 0), (5, 8.66)])
Arcs and Bezier Curves
g = Geometry()
g.move_to(0, 0)
g.arc_to(10, 0, i=5, j=0, clockwise=False) # semicircular arc
g.close_path()
# Bezier curves
g2 = Geometry()
g2.move_to(0, 0)
g2.bezier_to(10, 0, c1x=3, c1y=5, c2x=7, c2y=5)
# Convert arcs to Bezier curves (for non-uniform scaling)
g3 = Geometry()
g3.move_to(0, 0)
g3.arc_to_as_bezier(10, 0, i=5, j=0)
g3.upgrade_to_scalable()
Path Analysis
print(g.distance()) # total path length
print(g.area()) # signed enclosed area
print(g.rect()) # bounding box (x_min, y_min, x_max, y_max)
print(g.is_closed()) # path closure check
print(g.segments()) # split into sub-paths
# Find closest point on path
result = g.find_closest_point(5, 5) # (segment_index, t, (x, y)) or None
# Point and tangent at parameter t on a segment
point = g.get_point_at(segment_index=0, t=0.5)
tangent = g.get_tangent_at(segment_index=0, t=0.5)
Transformations
All transformation methods mutate the geometry in place and return self,
allowing chaining. Use .copy() first if you need to preserve the original:
import numpy as np
from raygeo.geo import Geometry
g = Geometry.from_points([(0, 0), (10, 0), (10, 10), (0, 10)])
# Offset (grow/shrink) — mutates in place
g.grow(1.0) # offset outward by 1 unit (each side moves by the amount)
print(g.area()) # 144.0 — 12×12
# Use .copy() to preserve the original
original = Geometry.from_points([(0, 0), (10, 0), (10, 10), (0, 10)])
shrunk = original.copy()
shrunk.grow(-1.0) # offset inward by 1 unit
# Affine transform (4x4 matrix) — mutates in place
matrix = [
[1, 0, 0, 5], # translate x by 5
[0, 1, 0, 3], # translate y by 3
[0, 0, 1, 0],
[0, 0, 0, 1],
]
g.transform(matrix)
# Map geometry into a frame — mutates in place
g.map_to_frame(
origin=(0, 0),
p_width=(100, 0),
p_height=(0, 100),
)
g.flip_x() # negate all x coordinates
g.flip_y() # negate all y coordinates
# Chaining is possible since all methods return self
g2 = Geometry.from_points([(0, 0), (10, 0), (10, 10), (0, 10)])
g2.transform(matrix).flip_x().grow(1.0)
Contour Operations
All contour methods mutate the geometry in place and return self:
# Split into separate closed contours (returns list, does not mutate)
contours = g.split_into_contours()
# Split into disconnected components (returns list, does not mutate)
components = g.split_into_components()
# Separate holes from solids (returns tuple, does not mutate)
inner, outer = g.split_inner_and_outer_contours()
# Normalize winding orders — mutates in place
g.normalize_winding_orders()
# Filter to only external contours — mutates in place
g.filter_to_external_contours()
# Remove shared edges between sub-paths — mutates in place
g.remove_inner_edges()
Polygon Operations
The geo.shape.polygon submodule provides polygon-specific operations powered by Clipper2:
from raygeo.geo import Geometry
from raygeo.geo.shape.polygon import (
get_polygon_area,
get_polygon_bounds,
offset_polygon,
get_polygons_union,
get_polygons_intersection,
get_polygons_difference,
is_point_inside_polygon,
polygons_intersect,
get_polygon_convex_hull,
)
square = [(0, 0), (10, 0), (10, 10), (0, 10)]
circle_approx = [(5 + 5 * math.cos(a), 5 + 5 * math.sin(a))
for a in [i * math.pi / 20 for i in range(40)]]
get_polygon_area(square) # 100.0
get_polygon_bounds(square) # (0.0, 0.0, 10.0, 10.0)
is_point_inside_polygon((5, 5), square) # True
# Boolean operations
union = get_polygons_union([square, circle_approx])
intersection = get_polygons_intersection(square, circle_approx)
difference = get_polygons_difference(square, circle_approx)
# Offset
inflated = offset_polygon(square, 2.0)
# NumPy variants are also available (suffixed with _numpy)
import numpy as np
sq_np = np.array(square)
get_polygon_area(sq_np) # also works with numpy arrays
Curve Fitting
All fitting methods mutate the geometry in place and return self:
from raygeo.geo import Geometry
# Simplify a path
g.simplify(tolerance=0.1)
# Convert curves to line segments
g.linearize(tolerance=0.01)
# Fit arcs and beziers to linear data
g.fit_arcs(tolerance=0.5)
g.fit_curves(tolerance=0.5, beziers=True, arcs=True)
# Convert geometry to polygons (returns list, does not mutate)
polygons = g.to_polygons(tolerance=0.01)
Self-Intersection Detection
g.has_self_intersections() # check for self-intersections
g.intersects_with(other_geometry) # check intersection with another geometry
g.encloses(other_geometry) # check if this fully encloses another
Serialization
# Serialize to dict (JSON-safe)
data = g.to_dict()
# Deserialize from dict
g2 = Geometry.from_dict(data)
# Pickle support (via __reduce_ex__)
import pickle
g3 = pickle.loads(pickle.dumps(g))
Documentation
Full API reference documentation is generated from the source type stubs.
Run make docs to build it locally — this produces Markdown pages in
docs/api/ with inline visual examples.
The docs are also published online with the RayForge Developer Docs.
Development
Prerequisites
- Rust toolchain (latest stable)
- Python 3.10+
- maturin (
pip install maturin) - Node.js (only needed for
make lint-python, which runs pyright via npx)
Quick Start
# Create and activate a virtual environment (Unix)
python -m venv .venv
source .venv/bin/activate # on Windows: .venv\Scripts\activate
# Install build tool and build the extension
pip install maturin pytest
make dev # builds Rust extension and installs into venv
# Run tests
make test
# Full check (lint + test)
make check
Available Make Targets
| Target | Description |
|---|---|
make dev |
Build and install into the active venv |
make build |
Build release wheel to dist/ |
make test |
Run pytest |
make lint |
Lint Rust + Python (including pyright) |
make format |
Auto-format Rust + Python |
make check |
Lint + test |
make stubs |
Regenerate .pyi type stubs |
make docs |
Build API docs with inline visual examples |
make visual |
Launch Streamlit visual test playground |
Visual Testing
The make visual target launches an interactive Streamlit playground
with real-time plots for geometry construction, polygon booleans, curve
fitting, image processing, SVG parsing, tab operations, overscan, lead-
in/out, merging, rasterization, concave hull, and nesting.
pip install -e ".[visual]"
make visual
See Visual Testing for a full walkthrough of every page and its controls.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
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 raygeo-0.11.0.tar.gz.
File metadata
- Download URL: raygeo-0.11.0.tar.gz
- Upload date:
- Size: 22.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
67a3a438339fe54c0ac3f993975a05ea7db437612a52f3692ee79984d124adfa
|
|
| MD5 |
858713206cc3ecd48811124c3f53df75
|
|
| BLAKE2b-256 |
d91785ebb28d914bc6f55cc2d0b0270e90495c299bdb5f8c4042cf85255776e0
|
Provenance
The following attestation bundles were made for raygeo-0.11.0.tar.gz:
Publisher:
release.yml on barebaric/raygeo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
raygeo-0.11.0.tar.gz -
Subject digest:
67a3a438339fe54c0ac3f993975a05ea7db437612a52f3692ee79984d124adfa - Sigstore transparency entry: 1903049945
- Sigstore integration time:
-
Permalink:
barebaric/raygeo@5f79a6c68dff34d1ba2e6ba27bd085f0dc385fea -
Branch / Tag:
refs/tags/v0.11.0 - Owner: https://github.com/barebaric
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5f79a6c68dff34d1ba2e6ba27bd085f0dc385fea -
Trigger Event:
release
-
Statement type:
File details
Details for the file raygeo-0.11.0-cp311-abi3-win_amd64.whl.
File metadata
- Download URL: raygeo-0.11.0-cp311-abi3-win_amd64.whl
- Upload date:
- Size: 1.8 MB
- Tags: CPython 3.11+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f39a46dd6367b37f27c81e1ab45f94e8f101b369cd1c2f8c01a1a4b08dce6e87
|
|
| MD5 |
85c5bd6887789cc23186b4e499cfb7df
|
|
| BLAKE2b-256 |
d1b897e0a7aba3201cf854399b1e91d297d8b49332da5646de3b346dba69ff62
|
Provenance
The following attestation bundles were made for raygeo-0.11.0-cp311-abi3-win_amd64.whl:
Publisher:
release.yml on barebaric/raygeo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
raygeo-0.11.0-cp311-abi3-win_amd64.whl -
Subject digest:
f39a46dd6367b37f27c81e1ab45f94e8f101b369cd1c2f8c01a1a4b08dce6e87 - Sigstore transparency entry: 1903050360
- Sigstore integration time:
-
Permalink:
barebaric/raygeo@5f79a6c68dff34d1ba2e6ba27bd085f0dc385fea -
Branch / Tag:
refs/tags/v0.11.0 - Owner: https://github.com/barebaric
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5f79a6c68dff34d1ba2e6ba27bd085f0dc385fea -
Trigger Event:
release
-
Statement type:
File details
Details for the file raygeo-0.11.0-cp311-abi3-manylinux_2_35_x86_64.whl.
File metadata
- Download URL: raygeo-0.11.0-cp311-abi3-manylinux_2_35_x86_64.whl
- Upload date:
- Size: 2.0 MB
- Tags: CPython 3.11+, manylinux: glibc 2.35+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
224436b73b08c78b167a54a9e4ed794f8eb254a28afd74681921701928c58676
|
|
| MD5 |
c23c2a7c8ea773f923f4840612e0b02d
|
|
| BLAKE2b-256 |
4f198d7df462c896f3da947470e298fb1d65b68a82de851b69c659d452cdfee7
|
Provenance
The following attestation bundles were made for raygeo-0.11.0-cp311-abi3-manylinux_2_35_x86_64.whl:
Publisher:
release.yml on barebaric/raygeo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
raygeo-0.11.0-cp311-abi3-manylinux_2_35_x86_64.whl -
Subject digest:
224436b73b08c78b167a54a9e4ed794f8eb254a28afd74681921701928c58676 - Sigstore transparency entry: 1903050225
- Sigstore integration time:
-
Permalink:
barebaric/raygeo@5f79a6c68dff34d1ba2e6ba27bd085f0dc385fea -
Branch / Tag:
refs/tags/v0.11.0 - Owner: https://github.com/barebaric
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5f79a6c68dff34d1ba2e6ba27bd085f0dc385fea -
Trigger Event:
release
-
Statement type:
File details
Details for the file raygeo-0.11.0-cp311-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: raygeo-0.11.0-cp311-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 1.8 MB
- Tags: CPython 3.11+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c59c419d785590b650def5579b6ad4df1840b9a96103eabd9e8534b4d0fe43cc
|
|
| MD5 |
ebb727d42dd51658e817d14255bb8c12
|
|
| BLAKE2b-256 |
ce6f6d1bbf02bd4c68c8c25dcf9c4d92459948253a5d137159cd4e76a35531bd
|
Provenance
The following attestation bundles were made for raygeo-0.11.0-cp311-abi3-macosx_11_0_arm64.whl:
Publisher:
release.yml on barebaric/raygeo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
raygeo-0.11.0-cp311-abi3-macosx_11_0_arm64.whl -
Subject digest:
c59c419d785590b650def5579b6ad4df1840b9a96103eabd9e8534b4d0fe43cc - Sigstore transparency entry: 1903050090
- Sigstore integration time:
-
Permalink:
barebaric/raygeo@5f79a6c68dff34d1ba2e6ba27bd085f0dc385fea -
Branch / Tag:
refs/tags/v0.11.0 - Owner: https://github.com/barebaric
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5f79a6c68dff34d1ba2e6ba27bd085f0dc385fea -
Trigger Event:
release
-
Statement type:
File details
Details for the file raygeo-0.11.0-cp311-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: raygeo-0.11.0-cp311-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 1.9 MB
- Tags: CPython 3.11+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0beb89f202e1a748c9404524179ab4f4c21f483573459c678170d9429222139e
|
|
| MD5 |
d7c69d0b6f560ea1d6e8ae66ff18b9e3
|
|
| BLAKE2b-256 |
0dd71e3f941ffd21ad591f789238c09f3f80de752011b951e19456838f458d3b
|
Provenance
The following attestation bundles were made for raygeo-0.11.0-cp311-abi3-macosx_10_12_x86_64.whl:
Publisher:
release.yml on barebaric/raygeo
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
raygeo-0.11.0-cp311-abi3-macosx_10_12_x86_64.whl -
Subject digest:
0beb89f202e1a748c9404524179ab4f4c21f483573459c678170d9429222139e - Sigstore transparency entry: 1903050510
- Sigstore integration time:
-
Permalink:
barebaric/raygeo@5f79a6c68dff34d1ba2e6ba27bd085f0dc385fea -
Branch / Tag:
refs/tags/v0.11.0 - Owner: https://github.com/barebaric
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@5f79a6c68dff34d1ba2e6ba27bd085f0dc385fea -
Trigger Event:
release
-
Statement type: