polygon processing and manipulation library built on Shapely - simplification, repair, merging, overlap resolution, and clearance fixing
Project description
Polyforge
Polyforge is a focused toolkit for cleaning, simplifying, repairing, and merging planar geometries built on top of Shapely. It exposes a small set of high-level functions that combine fast NumPy-based vertex processing with STRtree-powered spatial indexing, so you can run the same code on a handful of polygons or on thousands of building footprints.
Installation
pip install polyforge
Python 3.10+ with Shapely ≥ 2.1 is required.
What You Get
| Area | Highlights |
|---|---|
| Simplify & Clean | simplify_rdp, simplify_vw, collapse_short_edges, remove_small_holes, remove_narrow_holes |
| Clearance Fixing | fix_clearance auto-detects issues (holes too close, spikes, passages) and routes to ops helpers. Individual functions (fix_hole_too_close, fix_narrow_passage, …) now accept either enums or plain strings (e.g. strategy="split"). |
| Overlap & Merge | split_overlap for pairs, remove_overlaps for batches, merge_close_polygons with ops-based strategies ("simple_buffer", "selective_buffer", "vertex_movement", "boundary_extension", "convex_bridges"). |
| Repair & QA | repair_geometry, analyze_geometry, plus the pipeline-driven robust_fix_geometry / robust_fix_batch that iterate validity → clearance → merge → cleanup steps. |
| Core Types | Strategy enums (MergeStrategy, RepairStrategy, OverlapStrategy, …) remain available, but everything also accepts literal strings; GeometryConstraints + shared ops utilities live in polyforge.ops.*. |
Quick Examples
Simplify & Clean
from shapely.geometry import Polygon
from polyforge import simplify_vwp, remove_small_holes
poly = Polygon([(0, 0), (5, 0.1), (10, 0), (10, 10), (0, 10)])
poly = simplify_vwp(poly, threshold=0.2)
poly = remove_small_holes(poly, min_area=1.0)
Fix Narrow Passages Automatically
from polyforge import fix_clearance
improved, info = fix_clearance(complex_poly, min_clearance=1.5, return_diagnosis=True)
print(info.issue, info.fixed)
Merge Buildings into Blocks
from polyforge import merge_close_polygons
merged = merge_close_polygons(
buildings,
margin=2.0,
merge_strategy="boundary_extension",
insert_vertices=True,
)
Remove Overlaps at Scale
from polyforge import remove_overlaps
clean = remove_overlaps(parcel_list, overlap_strategy='split')
Constrain Repairs
from polyforge import robust_fix_geometry
from polyforge.core import GeometryConstraints
constraints = GeometryConstraints(min_clearance=1.0, min_area_ratio=0.9)
fixed, warn = robust_fix_geometry(polygon, constraints)
Design Notes
- Ops-first architecture – low-level helpers live in
polyforge/ops/…(simplify, cleanup, clearance, merge). Public modules are thin wrappers that call these ops so behaviour stays consistent across the library. - Literal-friendly configuration – strategy parameters accept enums or plain strings (
"selective_buffer","smooth", etc.), making it easy to drive Polyforge from config files or CLI flags. - Pipeline-driven repair –
robust_fix_geometrynow runs a simple step list (validity → clearance → merge → cleanup) viapolyforge.pipeline.run_steps, replacing the old transactional stage system. - process_geometry() everywhere – every simplification/cleanup call is just a NumPy function applied to each vertex array, so Z values are preserved automatically.
- STRtree first – overlap removal, merges, and vertex insertion all walk spatial indexes, keeping runtime roughly O(n log n) even for thousands of polygons.
Project Layout (high level)
polyforge/
ops/
simplify_ops.py # coordinate-level simplify helpers
cleanup_ops.py # hole removal, sliver cleanup
clearance/ # clearance fix primitives
merge/ + merge_* # merge strategies & utilities
simplify.py # thin wrappers over ops.simplify
clearance/ # fix_clearance + public wrappers
overlap.py # overlap engine + batch helpers
merge/ # merge orchestrator (calls ops)
repair/ # classic repair + pipeline-based robust fixes
core/ # enums, constraints, geometry/spatial utils
pipeline.py # FixConfig + run_steps helper
Advanced: Using the ops layer directly
Most users should stick to the high-level API (polyforge.simplify, polyforge.clearance, polyforge.merge, polyforge.repair). If you need to compose Polyforge primitives yourself (custom pipelines, batch transforms, etc.), import the ops helpers:
from shapely.geometry import Polygon
from polyforge.process import process_geometry
from polyforge.ops.simplify_ops import snap_short_edges
from polyforge.ops.clearance import fix_hole_too_close
from polyforge.ops.merge import merge_selective_buffer
poly = Polygon([(0, 0), (1, 0.01), (2, 0), (2, 2), (0, 2)])
# Run a raw NumPy transform via process_geometry
collapsed = process_geometry(poly, snap_short_edges, min_length=0.1, snap_mode="midpoint")
# Call clearance helpers directly (accept enums or strings)
fixed = fix_hole_too_close(collapsed, min_clearance=1.0, strategy="shrink")
# Use merge strategies without going through merge_close_polygons
merged = merge_selective_buffer([fixed, fixed.translate(1.5, 0)], margin=0.5, preserve_holes=True)
These ops modules expose the same functions the public API uses internally, so they're ideal for custom workflows or experimentation.
Running Tests
python -m pytest -q
The suite asserts all expected warnings, so any output indicates a regression.
That’s it—import what you need from polyforge and combine the high-level functions to build your own geometry pipelines.
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 Distribution
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 polyforge-0.1.0a2.tar.gz.
File metadata
- Download URL: polyforge-0.1.0a2.tar.gz
- Upload date:
- Size: 127.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
063237ee9020476199101b22cd8ccf585067421427289da51b1670f808c4cd94
|
|
| MD5 |
80fbcc4620265fcd22b5ad7b3b83ca37
|
|
| BLAKE2b-256 |
9f1b43d2915af0c5e5b34ca96178bcf3ef883ad2121d8f7c04ca8c339947868f
|
Provenance
The following attestation bundles were made for polyforge-0.1.0a2.tar.gz:
Publisher:
publish.yml on dwastberg/polyforge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
polyforge-0.1.0a2.tar.gz -
Subject digest:
063237ee9020476199101b22cd8ccf585067421427289da51b1670f808c4cd94 - Sigstore transparency entry: 943886613
- Sigstore integration time:
-
Permalink:
dwastberg/polyforge@bfa805c763bc49564d9fa478e99b880ca8345ba3 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/dwastberg
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@bfa805c763bc49564d9fa478e99b880ca8345ba3 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file polyforge-0.1.0a2-py3-none-any.whl.
File metadata
- Download URL: polyforge-0.1.0a2-py3-none-any.whl
- Upload date:
- Size: 97.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2716249087c19b8ffb4fed1d45b553f1068d4781e0a60386371fe2d14d79d2f6
|
|
| MD5 |
94e90495125e5cb2903032ad62338dcb
|
|
| BLAKE2b-256 |
d34d92a2d9701f9a28a20f3e518229336d5d2eb3e95850b3d7cb81d488682d2b
|
Provenance
The following attestation bundles were made for polyforge-0.1.0a2-py3-none-any.whl:
Publisher:
publish.yml on dwastberg/polyforge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
polyforge-0.1.0a2-py3-none-any.whl -
Subject digest:
2716249087c19b8ffb4fed1d45b553f1068d4781e0a60386371fe2d14d79d2f6 - Sigstore transparency entry: 943886615
- Sigstore integration time:
-
Permalink:
dwastberg/polyforge@bfa805c763bc49564d9fa478e99b880ca8345ba3 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/dwastberg
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@bfa805c763bc49564d9fa478e99b880ca8345ba3 -
Trigger Event:
workflow_dispatch
-
Statement type: