Skip to main content

A 2D/3D geometry library for CAD/CAM applications.

Project description

raygeo

PyPI CI

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.

Showcase

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.

CLI Tools

The raygeo command provides subcommands for tracing, inspecting, and profiling adaptive clearing runs.

pip install -e ".[cli]"
raygeo trace /tmp/trace.bin --scenario centre-island
raygeo inspect /tmp/trace.bin

See CLI Tools for full usage documentation.

License

MIT

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

raygeo-0.14.0.tar.gz (26.4 MB view details)

Uploaded Source

Built Distributions

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

raygeo-0.14.0-cp311-abi3-win_amd64.whl (2.1 MB view details)

Uploaded CPython 3.11+Windows x86-64

raygeo-0.14.0-cp311-abi3-manylinux_2_35_x86_64.whl (2.3 MB view details)

Uploaded CPython 3.11+manylinux: glibc 2.35+ x86-64

raygeo-0.14.0-cp311-abi3-macosx_11_0_arm64.whl (2.1 MB view details)

Uploaded CPython 3.11+macOS 11.0+ ARM64

raygeo-0.14.0-cp311-abi3-macosx_10_12_x86_64.whl (2.2 MB view details)

Uploaded CPython 3.11+macOS 10.12+ x86-64

File details

Details for the file raygeo-0.14.0.tar.gz.

File metadata

  • Download URL: raygeo-0.14.0.tar.gz
  • Upload date:
  • Size: 26.4 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for raygeo-0.14.0.tar.gz
Algorithm Hash digest
SHA256 ee5ce2f283bb2116bcaddc2d2bd26015222cd4a3782329c9bd67a1128f209e09
MD5 181ff634f46a1822c7b30e4e180ab50e
BLAKE2b-256 7445de6b80171d651bf4d3ec6f703c2eedc34441a20c1faef81441b8bdceafca

See more details on using hashes here.

Provenance

The following attestation bundles were made for raygeo-0.14.0.tar.gz:

Publisher: release.yml on barebaric/raygeo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file raygeo-0.14.0-cp311-abi3-win_amd64.whl.

File metadata

  • Download URL: raygeo-0.14.0-cp311-abi3-win_amd64.whl
  • Upload date:
  • Size: 2.1 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

Hashes for raygeo-0.14.0-cp311-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 afd40e197bae69411f55577d3592d22a82da80dac4b6e036cf154e2148b77b47
MD5 2e86c2f122997288776d68db6193199e
BLAKE2b-256 87287dc5a30f6c4f4d537d408d458053986f2c44dfe2929f2ab65c23221acff5

See more details on using hashes here.

Provenance

The following attestation bundles were made for raygeo-0.14.0-cp311-abi3-win_amd64.whl:

Publisher: release.yml on barebaric/raygeo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file raygeo-0.14.0-cp311-abi3-manylinux_2_35_x86_64.whl.

File metadata

File hashes

Hashes for raygeo-0.14.0-cp311-abi3-manylinux_2_35_x86_64.whl
Algorithm Hash digest
SHA256 0de72777ce19e41e9fe557b50e5cc14b067577c8b21191b1f37d73dbe6bc1771
MD5 e9e109c3eeb7cf45ef8a0a767cc3967e
BLAKE2b-256 a3639414b96806e571b88780faf10fb9bfd1196e32e4aaf66593ac79ece13403

See more details on using hashes here.

Provenance

The following attestation bundles were made for raygeo-0.14.0-cp311-abi3-manylinux_2_35_x86_64.whl:

Publisher: release.yml on barebaric/raygeo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file raygeo-0.14.0-cp311-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for raygeo-0.14.0-cp311-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 fc4c08c1ae3837173278f55301372192b45961c30620310bede4834b18b71c92
MD5 b4c82aa0e7e540142c4deb65bd90b557
BLAKE2b-256 f28789d84e69cf8e4c66f8468a4c7e350a98b85875fec654a7d6cd3bda3e44d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for raygeo-0.14.0-cp311-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on barebaric/raygeo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file raygeo-0.14.0-cp311-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for raygeo-0.14.0-cp311-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 c47c71b70ffd0b4e1af4c7d4e91450436bf653332cdfcf323332cf150e929a6f
MD5 3b3a1238f5100d50547c5727aa7be1bf
BLAKE2b-256 7d49a65fe1784ce83b4a2f7ff397eeb24d7eb4aec1b30aec61ab20d093632758

See more details on using hashes here.

Provenance

The following attestation bundles were made for raygeo-0.14.0-cp311-abi3-macosx_10_12_x86_64.whl:

Publisher: release.yml on barebaric/raygeo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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