Lofted Surface Voronoi Shell Generator
Generate 3D-printable voronoi shell geometry from parametric inputs. Each run produces a unique shape driven by radius, spacing, seed, and extrusion parameters, exported as STL.
Documentation
| Document | Description |
|---|---|
| docs/README.md | Documentation index (start here for all guides) |
| docs/API.md | Full API: modules, dataclasses, functions, CLI, config JSON |
| docs/PERFORMANCE.md | Pipeline profiling and performance optimisations |
| AGENTS.md | Cursor agent preferences and workspace conventions |
Install
# From PyPI (CLI + library)
pip install enhancement-geometry
# With notebook / interactive viewer extras
pip install "enhancement-geometry[notebook]"
# From source (development)
git clone https://github.com/longevity-genie/enhancement-geometry.git
cd enhancement-geometry
uv sync
Quick start
# Run with default data files
materialize generate
# Run without interactive viewer
materialize generate --no-viewer
# When developing from source, prefix commands with `uv run`
uv run materialize generate
Pipeline
- Lofted surface — 8 circles at different radii stacked along Z, lofted into a surface
- Voronoi cells — random seed points generate bounded voronoi cells
- Intersection curves — voronoi cells intersect the lofted surface, producing polyline curves
- Per-cell solids — each cell patch is scaled, its open edges lofted into walls, and closed into a watertight solid
- Plane face offset — faces at the cutting plane (x=0) are offset by -2mm to prevent thin-wall artifacts
- Assembly — all cell solids are combined, normals oriented outward, and exported as STL via trimesh
- Auto-retry — if the mesh fails volume validation, the pipeline retries with different voronoi seeds (up to 10 attempts)
CLI usage
The package installs a materialize command.
Generate geometry
# From default data files with default parameters
uv run materialize generate
# From a saved config
uv run materialize generate --config configs/20260325_172401.json
# Override parameters
uv run materialize generate --extrusion -0.5 --scale-x 0.7 --scale-y 0.3 --seed 42
# Override seed count and export to a custom directory
uv run materialize generate --seed-count 150 --export-dir my_exports
# Save a screenshot alongside the STL
uv run materialize generate --screenshot preview.png
# Skip viewer and suppress output
uv run materialize generate --no-viewer --quiet
Manage configs
# List all saved configs
uv run materialize list-configs
# Show a config file
uv run materialize show-config configs/20260325_172401.json
# Create a new config (saved into configs/ with timestamp)
uv run materialize new-config --radii "10,15,20,25,20,15,10,12" --seed-count 100 --random-seed 42
# Create a config AND run the pipeline in one step
uv run materialize run --radii "10,15,20,25,20,15,10,12" --seed-count 100 --random-seed 42 --extrusion -0.3 --scale-x 0.6 --scale-y 0.4
View existing STL files
uv run materialize view exports/voronoi_shell_20260325_172143.stl
Interactive notebook
The Jupyter notebook provides an interactive exploration workflow with widget controls:
uv run jupyter lab
# Then open lofted_surface_voronoi_generation.ipynb
The notebook offers slider-based parameter editing, step-by-step visualization of each pipeline stage, curve inspection, and per-cell solid debugging.
Physical scale (units)
| Axis | Max size (units) | Real-world note |
|---|---|---|
| X / Y | 150 | Treat as 150 mm in the plane |
| Z | 150 | Height along Z (7 spacings) |
Circle radius is constrained to 5–75 units.
Parameters
| Parameter | Range / rule |
|---|---|
| Radius | 5.00–75.00 (three decimals), one per circle |
| Spacing | 4.00–21.43 between circles |
| Points | 2–300 voronoi seed points |
| Seed | 0–9999 random seed |
| Extrusion | -3.00 to 3.00 |
| Scale X/Y | 0.10–1.50 non-uniform XY scaling |
Geometric constraints
The pipeline automatically detects and corrects geometry that would produce degenerate results. There are two levels of correction: radii smoothing (pre-loft, adjusts inputs) and extreme cell handling (post-intersection, adjusts per-cell processing).
Radii smoothing (pre-loft)
Before building the loft, consecutive radii are checked for steep transitions. When the larger radius is >= 2.5x the smaller one, the resulting loft slope is nearly vertical and voronoi cell intersections become degenerate.
| Parameter | Value | Description |
|---|---|---|
| Trigger | max(r_i, r_{i+1}) / min(r_i, r_{i+1}) >= 2.5 |
Consecutive radii ratio that activates smoothing |
| Radius fix | Smaller radius raised to larger / 2.0 |
Brings the pair ratio down to 2:1 |
| Spacing fix | Per-interval caps and vertex widening (see below) | Runs in the same pass as the 2.5:1 radius fix once any steep pair exists |
When smoothing activates, every profile segment with a meaningful |Δr| gets a maximum dz so the segment stays at least 25° from vertical (dz ≤ |Δr| / tan(25°)). That can reduce overly large steps. At interior rings that touch a steep interval, if the angle between the two consecutive profile segments would stay below 50°, both adjacent spacings are increased (by VERTEX_WIDEN_FACTOR per iteration, up to each segment’s max dz) so the corner opens—never shrunk for that purpose alone.
The smoothing runs automatically in the CLI pipeline. In the notebook, a dedicated cell shows a side-by-side comparison of the original vs adjusted loft (red vs green), and offers an "Apply adjustments & save config" button to update the sliders and persist the corrected values.
Constants are defined in smoothing.py:
| Constant | Value | Description |
|---|---|---|
MAX_CONSECUTIVE_RATIO |
2.5 | Ratio threshold that triggers smoothing |
TARGET_RATIO |
2.0 | Target ratio after smoothing the smaller radius |
MIN_ANGLE_FROM_VERTICAL_DEG |
25 | Minimum angle between vertical and each profile segment (when ` |
MIN_ANGLE_BETWEEN_SEGMENTS_DEG |
50 | Target minimum angle between consecutive profile segments at vertices touched by steep intervals |
VERTEX_WIDEN_FACTOR |
1.03 | Multiplier applied to both adjacent spacings when widening an acute vertex |
Cell classification
Each cell's intersection curve is analyzed with a best-fit plane and an oriented bounding box in the (U, V, normal) frame of that plane. Every cell is classified into one of three categories based on two metrics:
| Metric | Definition | Purpose |
|---|---|---|
| Volume/length ratio | bbox_volume / curve_length |
Separates large cells (ratio >= population mean) from small cells |
| Bbox aspect ratio | max(u_span, v_span) / min(u_span, v_span) |
Detects elongated cells that would produce spiky geometry |
Classification rules:
| Category | Condition | Surface method |
|---|---|---|
| Large | ratio >= mean AND aspect ratio <= 2.5 | Staged offset lofts (scale 0.5, then 0.45) |
| Small | ratio < mean AND aspect ratio <= 2.5 | Triangle fan from offset center |
| Extreme | aspect ratio > 2.5 (any ratio) | Extreme cell lofts (see below) |
Extreme cell handling
When a cell's bounding box aspect ratio exceeds 2.5, it is classified as extreme regardless of its volume/length ratio. Extreme cells get three corrections to prevent spiky, degenerate geometry:
| Correction | Value | Effect |
|---|---|---|
| Inner curve projection | Projected onto fitted plane | The inner scaled copies are flattened onto the cell's best-fit plane, removing 3D undulation. The original intersection curve stays untouched in 3D. |
| Scale factor | 0.3 (vs 0.5 for normal large cells) | The inner curve is scaled closer to the center, producing thicker walls |
| Extrusion reduction | 0.5x normal extrusion | The offset vector is halved, preventing extreme cells from extending too far outward |
The loft for extreme cells goes: original 3D curve (unchanged) -> flat inner edge (0.3 scale) -> flatter inner edge (0.27 scale). This creates a clean transition from the curved surface to a straight, thick inner wall.
Constants
These values are defined in lofted_surface_voronoi.py:
| Constant | Value | Description |
|---|---|---|
EXTREME_ASPECT_RATIO_THRESHOLD |
2.5 | Bbox aspect ratio above which a cell is classified as extreme |
EXTREME_SCALE_FACTOR |
0.3 | Inner curve scale factor for extreme cells (vs 0.5 default) |
EXTREME_EXTRUSION_FACTOR |
0.5 | Multiplier applied to the extrusion offset for extreme cells |
MIN_RADIUS |
5.0 | Minimum allowed circle radius |
MAX_RADIUS |
75.0 | Maximum allowed circle radius |
MAX_MODEL_SPAN |
150.0 | Maximum extent in any axis |
Project structure
enhancement-geometry/
├── README.md # Overview, quick start, CLI, parameters (this file)
├── AGENTS.md # Cursor agent context
├── docs/
│ ├── README.md # Documentation index
│ ├── API.md # Full API reference
│ └── PERFORMANCE.md # Profiling and optimisations
├── pyproject.toml # Package config, dependencies, CLI entry point
├── data/
│ ├── lofted_surface_inputs.json # Default radii and spacing
│ └── voronoi_points_inputs.json # Default seed count and random seed
├── configs/ # Saved parameter configs (timestamped JSON)
├── exports/ # Timestamped STL outputs (gitignored)
├── src/enhancement_geometry/
│ ├── __init__.py # Public API exports
│ ├── lofted_surface_voronoi.py # Core geometry functions (loft, voronoi, mesh ops)
│ ├── config.py # PipelineConfig dataclass, JSON I/O, config management
│ ├── smoothing.py # Radii/spacing smoothing to prevent steep loft slopes
│ ├── pipeline.py # End-to-end pipeline orchestration and export
│ ├── visualization.py # Camera, bounds, scene rendering, PyVista viewers
│ └── cli.py # Typer CLI (generate, view, config management)
├── lofted_surface_voronoi_generation.ipynb # Interactive notebook with widget controls
└── voronoi_jewelry.ipynb # Separate demo: spherical voronoi filigree pendant
Module overview
lofted_surface_voronoi— All low-level geometry: circle sampling, loft construction, Voronoi cell building, surface intersection, mesh cleanup, naked edge handling, mesh repair, and STL export primitives.config—PipelineConfigdataclass unifying all parameters for a run, with JSON serialization and duplicate-aware saving.smoothing— Pre-loft radii and spacing correction. Detects consecutive radii with >= 2.5:1 ratio and smooths them to 2:1; in the same pass, spacing is capped for 25° from vertical and, where needed, adjacent intervals are widened (up to cap) so consecutive segments reach at least ~50° at rings touched by steep intervals.pipeline—run_pipeline()andrun_pipeline_with_retry()orchestrate the full pipeline from config to trimesh result.export_stl()writes the output.visualization— Camera positioning, bounds helpers, static PNG rendering, and interactive VTK viewer windows.cli— Typer-based CLI withgenerate,view,new-config,show-config, andlist-configscommands.
Python API
from enhancement_geometry import PipelineConfig, run_pipeline, export_stl
config = PipelineConfig(
radii=(10, 15, 20, 25, 20, 15, 10, 12),
z_increment=13.38,
seed_count=100,
random_seed=42,
extrusion_multiplier=-0.2,
scale_x=0.5,
scale_y=0.5,
)
result = run_pipeline(config)
path = export_stl(result, "exports")
print(f"Exported to {path}, volume valid: {result.is_valid_volume}")
License
MIT
Metadata
Release files for enhancement-geometry 0.2.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| enhancement_geometry-0.2.4.tar.gz | 54.2 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| enhancement_geometry-0.2.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 113.1 kB
Release files / enhancement_geometry-0.2.4.tar.gz
| Download URL | enhancement_geometry-0.2.4.tar.gz |
|---|---|
| Size | 54.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
30113ee9f36c62cb33fd211d8636e6f70a13c84e1ba14cae5eb6cd83b94ac26a
|
|
BLAKE2b-256 checksum How to use checksums |
b4a4c211ae3bf77cc130eef99d711631717d806d0b80df85f912ce320a3a4da3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.0 {"installer":{"name":"uv","version":"0.10.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / enhancement_geometry-0.2.4-py3-none-any.whl
| Download URL | enhancement_geometry-0.2.4-py3-none-any.whl |
|---|---|
| Size | 59.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fc5eb00400bad836998d430d462b2cad419bd941dbfaa5310b632123ae802bee
|
|
BLAKE2b-256 checksum How to use checksums |
7b0353dcb1a9b6efbaf00fbefd4ab8091ec10bbced5c4f5dea3d4731b3b52067
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.0 {"installer":{"name":"uv","version":"0.10.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"26.04","id":"resolute","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for enhancement-geometry 0.2.4
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.