ANYgeometry
ANYgeometry is the lightweight, deterministic structural-surface geometry kernel shared by ANYmesher, ANYfem, and ANYstructure. It owns neutral geometry, topology, persistent entity references, semantic groups, geometry evaluation, edits, intersections, and geometry serialization. Meshing, finite-element attributes, materials, loads, solver state, project data, and GUIs stay in their owning packages.
The kernel is intentionally focused on engineering plates, beams, panels, cylinders, cones, frames, and shell intersections. It is not a general solid CAD kernel and does not depend on OpenCASCADE, Gmsh, a GUI toolkit, an FE package, or a solver.
Installation
See compatibility and verification status for supported consumer versions, platform coverage and known limitations, and the coordinate conversion contract for model/world helpers.
ANYgeometry requires Python 3.11 or newer and NumPy. Install the released package or a sibling checkout directly:
python -m pip install ANYgeometry
For editable development:
python -m pip install -e C:\Github\ANYgeometry
Planar clipping and strict planar qualification use the optional Shapely
backend. Install the planar extra for those workflows:
python -m pip install -e "C:\Github\ANYgeometry[planar]"
Quick start
Build topology directly:
from anygeometry import GeometryModel
geometry = GeometryModel()
vertices = geometry.add_points(
[(0, 0, 0), (4, 0, 0), (4, 3, 0), (0, 3, 0)]
)
face_id = geometry.add_plate(vertices)
face_ref = geometry.entity_ref("face", face_id) # local compatibility reference
face_handle = geometry.handle("face", face_id) # model-bound public identity
geometry.add_to_group("deck", [face_ref])
LLM and automation contract
anygeometry.automation is a provider-neutral protocol boundary. An LLM may
translate natural language into its bounded JSON/record algebra, but the
kernel never parses prompts, executes generated code, accepts arbitrary method
names, or imports an LLM/MCP SDK.
from anygeometry.automation import Command, CommandBatch, apply_plan, plan_commands
q = lambda xyz: {"value": xyz, "unit": "m", "frame": "model_local"}
commands = tuple(
Command(f"p{i}", "create_point", {"position": q(point)})
for i, point in enumerate(((0, 0, 0), (4, 0, 0), (4, 3, 0), (0, 3, 0)), 1)
) + (
Command("deck", "create_plate", {"vertices": [f"p{i}.vertex" for i in range(1, 5)]}),
)
batch = CommandBatch(1, "make-deck", geometry.model_id, geometry.revision, commands)
plan = plan_commands(geometry, batch) # no IDs allocated; no revision/cache change
result = apply_plan(geometry, plan) # one owner transaction / one ChangeSet
deck_sheet = result.outputs["deck.sheet"][0]
Selectors cover canonical handles and aliases (point→vertex,
plate→sheet), groups/tags, ownership and incidence, exact metadata,
spatial/range predicates, bounded nearest queries, Boolean composition,
deterministic ordering, pagination, and explicit mutation cardinality.
Positions and transforms require both units and model_local/world frame.
See docs/AUTOMATION_PROTOCOL.md.
Or use a structural generator:
from anygeometry.generators import stiffened_panel
geometry = stiffened_panel(
4.0,
3.0,
longitudinal_spacing=1.0,
transverse_spacing=2.0,
semantic_group="deck",
)
deck_faces = geometry.group("deck")
stiffener_edges = geometry.group("longitudinal_stiffeners")
EntityHandle(model_id, kind, id) is the model-bound cross-package identity.
The legacy EntityRef(kind, id) remains a compact local compatibility value.
IDs are allocated monotonically and are never reused, including after rollback
or compatibility undo. Splitting or fragmenting an entity records descendants,
updates groups, tags, and structural uses, and lets clients resolve a stale
selection explicitly.
Geometry model
Vertex,Edge, andFaceprovide topology with persistent IDs.- Public entity stores and records are read-only. Edits go through atomic model
methods or a nested
GeometryModel.transaction(). - Model identity, revision, tolerance, units, and coordinate arrays are
owner-controlled. Use
set_document_settings(...)for revisioned coordinate or tolerance changes; returned arrays cannot be written in place. Part,Sheet,FaceUse, andCoedgepersist plate ownership/incidence;MemberandMemberEdgeUsepersist a physical beam axis across edge splits.AttachmentandJunctiondistinguish declared beam/plate and beam/beam relationships from mere geometric coincidence.Straight,Arc, and lightweight BezierSplinecurves are topology-owned.Plane,Cylinder,Cone,RuledSurface, and explicit or topology-backed Coons patches provide evaluation and local UV coordinates.- Groups carry geometric meaning such as
shell,deck,bottom,boundaries,longitudinal_stiffeners, andring_stiffeners. - Tags provide lightweight geometry annotations. Materials, sections, thicknesses, loads, supports, and mesh controls must reference geometry from outside this package.
General operations include projection, closest-point queries, transforms,
edge/face splitting, trimming, holes, fragmentation, and shell/shell
intersection imprinting. Analytical line/plane/cylinder intersections cover
common structural cases; a bounded NumPy-only engine qualifies every built-in
Straight/Arc/Spline and Plane/Cylinder/Cone/Ruled/Coons operand family. It
returns complete point, curve, or trim-aware region components with local
parameter evidence and fails closed when a work budget or degeneracy remains
unresolved. Planar crossings and axial
plane/cylinder cuts become real shared edges immediately. A transverse closed
ring through a complete conformal cylinder band is imprinted atomically as
exact shared arcs: the plane becomes an inner disk plus an outer annular face,
and every cylinder patch is split above and below the ring. Stable face
lineage, groups, tags, and exact plane/cylinder surfaces are preserved.
FaceIntersection.edges contains the complete ring while the compatible
FaceIntersection.edge accessor remains its deterministic first edge.
Topology-changing intersections require caller intent, for example
intersect_faces(model, a, b, policy=MutationPolicy.IMPRINT). Query-only
calls use fragment=False; KEEP_SEPARATE_PART retains both inputs without
imprinting. clip_line_to_face returns every planar material interval and
subtracts holes instead of collapsing a concave or holed face to one span.
The qualified closed-ring topology path deliberately requires at least three positive-sweep cylinder patches forming one complete conformal band, a cut strictly inside the cylinder height, and a convex straight-edged plane face without existing holes that fully contains the ring. Oblique cuts, partial or nonconformal bands, and planes needing nested trim classification remain non-mutating intersection-query workflows rather than being approximated with unrelated edges.
Qualified predicates return typed IntersectionResult values that distinguish
crossing, touching, overlap, coincidence, disjoint, and unclassified cases.
Curved components carry IntersectionCertificate evidence and typed parameter
loops/traces; only complete certificates may feed atomic imprinting. An
optional IntersectionQualificationPolicy controls bounded work without
changing model-owned tolerances. Multi-component curve imprints and qualified
full or contained coincident-region CONNECT preserve structural ownership and
are idempotent on immediate reapplication.
The model-owned TolerancePolicy separates computational, merge, angular,
parameter, area, and surface-residual tolerances using local feature extent,
so translating a complete model does not change a local classification.
geometry.strict_audit() performs deterministic fail-closed full-model
qualification with a spatial broad phase. It checks duplicate/crossing/
overlapping edges, T-junctions, sheet manifoldness, structural member intent,
member-face relationships, face overlap, lineage, and unsupported candidates.
Curved candidates use the same public predicate engine in full and
changed-region audit. Any incomplete certificate or unclassified candidate
blocks certification; reports expose subdivision/trace and affected-closure
work counters.
Large beam lattices should use GeometryModel.add_members(...), which builds
all member chains under one part update and one structural validation. Public
remove_member, remove_sheet, remove_part, remove_attachment, and
remove_junction methods enforce dependency order and rollback atomically.
Editable feature history and owner editing
GeometryModel.features stores an ordered, suppressible modelling history.
Feature inputs use FeatureOutputRef so downstream intent does not depend on
the materialized IDs allocated by a later regeneration. EntityHandle is the
model-bound identity for mesh and analysis packages; feature executors and
local compatibility APIs continue to use compact EntityRef values.
from anygeometry import FeatureOutputRef, GeometryModel
geometry = GeometryModel()
first = geometry.features.append(
"geometry.point", parameters={"position": [0.0, 0.0, 0.0]}
)
second = geometry.features.append(
"geometry.point", parameters={"position": [2.0, 0.0, 0.0]}
)
geometry.features.append(
"geometry.line",
inputs={
"start": [FeatureOutputRef(first.feature_id, "point", "vertex")],
"end": [FeatureOutputRef(second.feature_id, "point", "vertex")],
},
)
report = geometry.regenerate_features()
assert report.success
The registry is extensible by namespaced feature kind, allowing consumers to
add executors without a reverse dependency. Regeneration is atomic, retains
replacement lineage, and reserves IDs above the old materialization so a
stale EntityRef can never be silently reused for a different output.
Feature executors also declare a FeatureTopologyRole: independently
AUTHORED geometry, subordinate COMPOSITE topology, or a MODIFIER that
must preserve the earlier owner. feature_entity_owners(geometry) resolves
the active topology of composite features through exact replacement lineage.
It allows model trees and viewers to present a cylinder, cone, panel, or other
generator as one intent-level object without removing the vertices, edges, and
faces needed for geometry and meshing. The query never uses coordinates or
proximity matching; unknown frozen feature kinds conservatively remain
composite.
Flat-face sketches use the built-in geometry.sketch.extrude feature. A
SketchDefinition stores named plane-local points, their ordered path,
distance/coincidence constraints, and the signed normal extrusion distance.
Points are not restricted to the support-face boundary. on_edge and
on_vertex constraints follow the oriented support boundary, and regeneration
returns stable point/*, profile/edge/*, and extrusion/face/* output keys.
The small constraint solver uses minimum-norm corrections and rejects
inconsistent dimensions without changing the live geometry.
High-level owner operations include insert_model, copy_entities, linear
and circular patterns, mirroring, edge/face reversal, deep clone, and typed
measure results. Insertion remaps all topology with fresh IDs, preserves
groups, tags, surfaces, holes, and metadata, and deliberately does not weld
coincident entities.
AffineTransform provides validated translation, axis-angle rotation, scale,
reflection, composition, inverse, and point-array evaluation. In-place
translate_entities / rotate_entities preserve model-bound identities;
copy_translated / copy_rotated allocate fresh identities. Arbitrary
transform lists use pattern_entities, while rectangular_pattern creates a
deterministic one-, two-, or three-axis Cartesian array. Rectangular counts are
copy steps beyond the unchanged original, so counts (1, 1) produce the other
three positions of a 2x2 array. Pattern implementations extract the selected
geometry and structural closure once rather than cloning unrelated model data.
Serialization and CLI
The development head writes deterministic, checksummed geometry schema 5. It preserves model UUID and revision, coordinates/CRS and tolerance policy, allocator high-water marks, support surfaces and optional parameterizations, construction/control ownership, curves/trims, structural ownership and qualified relationships, groups, tags, geometry and structural lineage, extensions, and feature history, including exact elliptic and cylinder-intersection curves. Schemas 1–4 migrate conservatively and one-way; malformed current documents fail closed:
from anygeometry import read_geometry, write_geometry
write_geometry("panel.anygeometry.json", geometry)
restored = read_geometry("panel.anygeometry.json")
Certified output additionally requires a clean strict audit:
write_geometry("panel.certified.anygeometry.json", geometry, certified=True)
certified=True is a validation gate, not a persisted certificate. The audit
report is an ephemeral result bound to the exact model UUID, revision, and
audit policy; schema 5 intentionally stores no reusable certification flag.
Consumers that require a qualified handoff must retain or rerun
strict_audit() for that exact revision.
JSON and gzip-compressed JSON are supported. Mesh and FEM/project serialization remain outside ANYgeometry.
Released ANYgeometry 0.4.4 reads schemas 1–4 and writes schema 4. The development
head reads schemas 1–5 and writes schema 5; older readers reject schema 5.
Automation protocol 1 is unchanged. Consumers of the new curves must update
their geometry owner together with the schema reader. Downstream packages should use the public codecs rather
than parse schema records. Legacy relationship evidence migrates as
UNVERIFIED and never implies exactness or certification.
Trusted importers and local script features that have already materialized
topology through GeometryModel operations can bind that exact last-good
materialization without mutating detached feature records:
geometry.features.adopt_frozen(
geometry,
kind="vendor.script.feature",
outputs={"face": EntityRef("face", face_id)},
)
adopt_frozen accepts only active IDs in the history's owning model; it never
retargets through replacement lineage or geometric proximity. ANYgeometry
computes the closure checksum and publishes the history update atomically.
Callers that already certified a closure may pass expected_checksum= to make
the adoption fail closed if the topology changed.
Feature edits mark the affected record dirty. For additive modelling features, regeneration starts at the earliest dirty record on a clone of the live materialization. The clean prefix keeps its exact entity IDs. A replayed output keeps its prior binding only when its stable output-key set and complete ID-independent topology closure are exactly equal; otherwise its replacement is allocated above the previous ID high-water mark and lineage is extended. This comparison uses no distance, tolerance, or nearest-geometry retargeting.
Ordinary output revalidates complete topological and structural integrity. Certified output adds the full global geometric audit before writing, but the ordinary and certified schema-5 payload shapes are identical. Feature history is owner-observed and validated before writing; direct record tampering is never accepted as a checksummed document.
The package module can create an example or inspect a saved geometry:
python -m anygeometry --version
python -m anygeometry --write-example panel.anygeometry.json
python -m anygeometry panel.anygeometry.json --json
Dependency direction
The intended dependency graph is one-way:
ANYgeometry <- ANYmesher <- ANYfem
^ ^
| |
ANYstructure -------+
ANYgeometry never imports ANYmesher, ANYfem, ANYstructure, ANYsolver, a GUI,
or a finite-element package. See MIGRATION.md when moving code
from the historical anymesher.geometry namespace.
Development
python -m pip install -e ".[dev]"
python -m pytest
python -m build
python -m twine check dist\*
The test suite qualifies persistent identity and history, topology, curves, surfaces, generators, operations, serialization, intersections, CLI behavior, and import boundaries.
The strict-kernel design, invariants, benchmark scope, and completed release
qualification are recorded in
docs/KERNEL_UPDATE_OVERVIEW.md and
KERNEL_UPDATE_REPORT.md.
License
Starting with version 0.4.2, ANYgeometry source code is licensed under the Mozilla Public License 2.0. Earlier releases retain the license terms that applied when they were published. Original project documentation is licensed separately as described in docs/LICENSE.md, and third-party components retain their own terms as recorded in THIRD_PARTY_NOTICES.md.
Metadata
Release files for ANYgeometry 0.4.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| anygeometry-0.4.5.tar.gz | 722.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| anygeometry-0.4.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.2 MB
Release files / anygeometry-0.4.5.tar.gz
| Download URL | anygeometry-0.4.5.tar.gz |
|---|---|
| Size | 722.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3995ff69850d239a8c266874ad6453fb1b6ed3d5c9ff5b75e84a0f0e05384a1c
|
|
BLAKE2b-256 checksum How to use checksums |
66caf2da85cc9ba03e833b3fe7180b941961790277783c64977c7e0fd816f0cb
|
| 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 logRelease files / anygeometry-0.4.5-py3-none-any.whl
| Download URL | anygeometry-0.4.5-py3-none-any.whl |
|---|---|
| Size | 484.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b68066aa44052aeeaf5d3feb8d6bc733ce81bf04752580aebc3c1b7915ce8fad
|
|
BLAKE2b-256 checksum How to use checksums |
d3bb4adbcb88b704d59cd78103504e4c53be50816c2718ead885938c62670f24
|
| 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