Skip to main content

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

Metadata

Release files for raygeo 1.58.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for raygeo 1.58.2
File Size Uploaded
raygeo-1.58.2.tar.gz 32.2 MB Details

Built distributions (wheels)

Table of built distributions (wheels) for raygeo 1.58.2
File
raygeo-1.58.2-cp311-abi3-win_amd64.whl CPython 3.11 abi3 Windows x86-64 Details
raygeo-1.58.2-cp311-abi3-manylinux_2_35_x86_64.whl CPython 3.11 abi3 Linux glibc 2.35+ x86-64 Details
raygeo-1.58.2-cp311-abi3-manylinux_2_35_aarch64.whl CPython 3.11 abi3 Linux glibc 2.35+ ARM64 Details
raygeo-1.58.2-cp311-abi3-macosx_11_0_arm64.whl CPython 3.11 abi3 macOS 11.0+ ARM64 Details
raygeo-1.58.2-cp311-abi3-macosx_10_12_x86_64.whl CPython 3.11 abi3 macOS 10.12+ x86-64 Details

Total release size: 54.6 MB

Release files / raygeo-1.58.2.tar.gz

Download URL raygeo-1.58.2.tar.gz
Size 32.2 MB
Tags Source
SHA-256 checksum
How to use checksums
b0c1748c35d9842080e8453fd063d193b40e3bb86d7cf60ce866c95649f2bd58
BLAKE2b-256 checksum
How to use checksums
452789a3ad371618ee112c08ed0614bb9eeb95e976439409dcf7b2ca5f92a432
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release files / raygeo-1.58.2-cp311-abi3-win_amd64.whl

Download URL raygeo-1.58.2-cp311-abi3-win_amd64.whl
Size 4.1 MB
Tags CPython 3.11 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
4ed0d60c04c576ffd98664124f87877e0d898d7514d4e8cacc3c1abe0f087bac
BLAKE2b-256 checksum
How to use checksums
530c13940de47e6c4763ba9819a8ab16aa49ef73a3402a9f69f84f8c21cbaad6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release files / raygeo-1.58.2-cp311-abi3-manylinux_2_35_x86_64.whl

Download URL raygeo-1.58.2-cp311-abi3-manylinux_2_35_x86_64.whl
Size 4.8 MB
Tags CPython 3.11 Linux glibc 2.35+ x86-64 abi3
SHA-256 checksum
How to use checksums
9e86f38540329904ea8ffcd5072d82c65d373a92dbad4c9cf9cf3a5ada9e742b
BLAKE2b-256 checksum
How to use checksums
e15ca1f054f2246f1df5f4af71a95d1dbe66d18cf24d60920f481754276c4018
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release files / raygeo-1.58.2-cp311-abi3-manylinux_2_35_aarch64.whl

Download URL raygeo-1.58.2-cp311-abi3-manylinux_2_35_aarch64.whl
Size 4.8 MB
Tags CPython 3.11 Linux glibc 2.35+ ARM64 abi3
SHA-256 checksum
How to use checksums
5dac62db57a931577dcec7cebd96f777bc1a87b423884151ddf4684b184a4770
BLAKE2b-256 checksum
How to use checksums
867c779163155dd9ffb6feaff2a4b41e7c2443c2db17a6b024e02f6adf87704d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release files / raygeo-1.58.2-cp311-abi3-macosx_11_0_arm64.whl

Download URL raygeo-1.58.2-cp311-abi3-macosx_11_0_arm64.whl
Size 4.2 MB
Tags CPython 3.11 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
7c3c35e77b109d6fcad9ada9674da13157af9729cd337ee244f1a052df7ea517
BLAKE2b-256 checksum
How to use checksums
da321d3e997db65e99d33398e913e8fbfa97008eb0cfc88875e3f1104bf5da14
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release files / raygeo-1.58.2-cp311-abi3-macosx_10_12_x86_64.whl

Download URL raygeo-1.58.2-cp311-abi3-macosx_10_12_x86_64.whl
Size 4.5 MB
Tags CPython 3.11 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
8b9786219a66d21a2772432c7205e63d69c5999cd016940030e2cf02ecd01188
BLAKE2b-256 checksum
How to use checksums
eada3b4a8982cb264d4ec9470c5aad8c7fa6fa6b3601ce7ad4329a3c859e12f3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 1, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.58.2 This release

6 release files

1.58.1

6 release files

1.58.0

6 release files

1.57.0

6 release files

1.56.1

5 release files

1.56.0

5 release files

1.55.0

5 release files

1.54.3

5 release files

1.54.2

5 release files

1.54.1

5 release files

1.54.0

5 release files

1.53.3

5 release files

1.53.2

5 release files

1.53.1

5 release files

1.53.0

5 release files

1.52.0

5 release files

1.51.0

5 release files

1.49.0

5 release files

1.48.0

5 release files

1.47.0

5 release files

1.46.0

5 release files

1.45.1

5 release files

1.45.0

5 release files

1.44.0

5 release files

1.43.0

5 release files

1.42.1

5 release files

1.42.0

5 release files

1.41.1

5 release files

1.41.0

5 release files

1.40.3

5 release files

1.40.2

5 release files

1.40.1

5 release files

1.40.0

5 release files

1.39.1

5 release files

1.39.0

5 release files

1.38.3

5 release files

1.38.2

5 release files

1.38.1

5 release files

1.38.0

5 release files

1.37.0

5 release files

1.36.1

5 release files

1.27.1

5 release files

1.27.0

5 release files

1.26.0

5 release files

1.25.6

5 release files

1.25.5

5 release files

1.25.4

5 release files

1.25.3

5 release files

1.25.2

5 release files

1.25.1

5 release files

1.25.0

5 release files

1.24.0

5 release files

1.23.0

5 release files

1.22.0

5 release files

1.21.3

5 release files

1.21.2

5 release files

1.21.1

5 release files

1.21.0

5 release files

1.20.2

5 release files

1.20.1

5 release files

1.20.0

5 release files

1.19.0

5 release files

1.18.0

5 release files

1.17.1

5 release files

1.17.0

5 release files

1.16.0

5 release files

1.15.2

5 release files

1.15.1

5 release files

0.15.0

5 release files

0.13.2

5 release files

0.13.1

5 release files

0.13.0

5 release files

0.12.1

5 release files

0.12.0

5 release files

0.11.0

5 release files

0.10.0

5 release files

0.9.0

5 release files

0.8.0

5 release files

0.7.1

5 release files

0.7.0

5 release files

0.6.3

5 release files

0.6.2

5 release files

0.6.1

5 release files

0.6.0

5 release files

0.5.0

5 release files

0.4.1

5 release files

0.4.0

5 release files

0.3.0

5 release files

0.2.0

5 release files

0.1.9

5 release files

0.1.7

5 release files

0.1.6

5 release files

0.1.5

5 release files

0.1.3

5 release files

0.1.2

5 release files

0.1.1

5 release files

0.1.0

5 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page