molejo
The give in your machine.
molejo (Brazilian Portuguese: the springy give of a thing) is an analytic representation for the flexible parts of a machine — valve springs, timing belts, cable looms, filament — parts whose shape is a function of machine state, not just their placement.
A molejo shape is a serializable spec: a planar profile swept along a parametric path, whose numeric slots may reference named scalar parameters. The spec is the model. Meshes are evaluations of it:
- the Python evaluator turns a spec plus parameter values into an exact triangle mesh (and STL) for build pipelines, geometric tests, and collision checks;
- the JavaScript evaluator turns the same spec plus the same values into vertex buffers for three.js, cheap enough to re-evaluate every animation frame;
- an optional B-rep evaluator (OCCT, via the
brepextra of the Python package) turns the same spec plus the same values into an exact solid, for testing architectures that assert on exact shapes.
Both evaluators emit the same vertex count in the same order by construction — tessellation is fixed and declared in the spec, never curvature-adaptive — and are pinned to each other by shared parity fixtures.
Full documentation: https://molejo.readthedocs.io
What it looks like
Authoring is Python-first; the JSON spec is the representation it serializes to:
from molejo import Shape, Circle, Helix, P
spring = Shape(
profile=Circle(radius=2.0),
path=[Helix(radius=14.0, turns=6.5, height=P.height)],
path_samples=240, profile_samples=16,
)
mesh = spring.evaluate(height=46.8) # numpy vertices and faces
spring.to_json() # the spec — what a browser gets
P.height is a plain reference, not an expression: derived values
(free_length - lift) are computed in ordinary Python and bound at
evaluation. The browser side consumes the serialized spec only:
import { evaluate } from 'molejo';
evaluate(spec, { height: 50.0 - lift(t) }, buffers); // per frame, in place
Why
CAD kernels represent rigid geometry; animation systems interpolate placement. A compressing spring, a circulating belt, or a cable loom following a print head falls between the two: its geometry at any instant is exact, closed-form math over a few scalars (a lift, a carriage position), but no kernel evaluates that math in both a build pipeline and a browser at frame rate.
Sampling the shape (morph targets, frame swapping) works for one parameter and dies combinatorially at two or three — a loom that follows X, Y and Z would need a sampled grid over all of them. molejo instead keeps the shape analytic and moves the evaluation to wherever it is needed.
Design properties
- Analytic master, evaluations on demand. The spec defines exact curves and surfaces; every mesh is a deterministic sampling of them at the declared resolution, and the B-rep evaluator constructs the same curves exactly in OCCT. Line- and arc-based sweeps (belts) are analytic surfaces; helix and spline sweeps are tolerance-declared B-spline surfaces, as in any kernel.
- Sweeps only, no booleans. A closed profile swept along a path is watertight by construction; there is no repair pass because no input can be broken. Boolean interaction belongs to whatever mesh machinery consumes the evaluation.
- Parameters are plain named numbers. molejo does not know where they come from — a slider, a kinematic expression, a test instant. Expression languages belong to the consumer.
- Continuity and self-intersection are the author's obligation. The representation does not police an over-compressed spring; the consumer's tests can.
Status
Version 0.2.0, implementing spec version "0.2": profiles (circle,
polygon) and path primitives (line, arc, helix, spline, wrap). Both
packages parse and validate the document against shared fixtures; the
Python package also authors it (Shape, Circle, …, P). Spec version
"0.1" documents are read unchanged — "0.2" only adds vocabulary — and
an author writes the lowest version a document needs, so a shape that
asks nothing of "0.2" emits the "0.1" document it always did.
Circle and polygon profiles swept along the whole path vocabulary —
line, arc, helix, spline and wrap — evaluate in both runtimes,
singly or chained, capped or closed into a loop and watertight either
way, from Python as numpy arrays and binary STL, from JavaScript as
reusable three.js buffers, pinned to each other by shared parity
fixtures. The spring in the sample above is one of those fixtures rather
than a promise, and so are a toothed belt around three pulleys whose
teeth circulate with a parameter, a belt bent backwards over a drive
pulley with its teeth facing outward to meet it, and a filament loom
whose head follows three. The one gap in the vocabulary raises naming
itself: closing a loop that is not a wrap.
The B-rep evaluator installs with pip install molejo[brep] and
evaluates the same documents to closed OCCT solids —
molejo.brep.evaluate(spec, values) or shape.brep(**values) — with the
same refusals, word for word, as the mesh evaluator. Every parity fixture
is checked through it on volume and area. An install without the extra
imports and meshes and exports STL exactly as before; asking it for a
solid raises naming the extra.
molejo 0.1 has done real work before being called a release: it is the flexible-part representation of solid-node machine models, where its springs and belts hold up in animated, geometrically tested engines and 3D printers (a V8 engine's valve springs, a Metamaquina 2's drive belts) rather than only in this repository's fixtures.
A spec version is the MAJOR.MINOR of the release that introduced it,
written as a JSON string — one number to remember rather than two. Before
1.0, a release that changes the spec mints a spec version equal to its
own MAJOR.MINOR, and a release that does not keeps the one it
inherited. So 0.1.0 carries spec "0.1" and 0.2.0 carries spec
"0.2", and both packages release together for a given spec version.
One document, two implementations: neither runtime is ever published
against a spec version the other has not caught up to.
molejo 0.1.0 shipped before this rule and wrote the integer 1 where
its successors write "0.1". The name changed; the spec did not. A
document still carrying the integer is refused by name rather than
guessed at.
Publishing to PyPI (python/) and npm (js/) is the maintainer's
explicit decision, never a side effect of building: scripts/check-dist,
the release dry-run, packs each package, installs it into a throwaway
environment outside this repository and evaluates a fixture there — and
uploads nothing.
Origin
molejo was born from solid-node, a Python framework for mechanical CAD projects, which needed springs, belts and cable looms in animated, testable machine models. solid-node adapts molejo as one leaf-geometry technology among the several it supports; molejo itself is independent and consumable by any Python or three.js project.
License
Apache License 2.0 — see LICENSE.
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 molejo-0.2.0.tar.gz.
File metadata
- Download URL: molejo-0.2.0.tar.gz
- Upload date:
- Size: 46.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
83741eda6305641d9e57550c50f791710d4370797d25d1969b03284696607f3b
|
|
| MD5 |
d9d812e28960015b7664c76a178ebbf2
|
|
| BLAKE2b-256 |
cf536f276f089e2da15040cb3763b7db224bb6d9aaa3e3e01646bf22775f468f
|
File details
Details for the file molejo-0.2.0-py3-none-any.whl.
File metadata
- Download URL: molejo-0.2.0-py3-none-any.whl
- Upload date:
- Size: 46.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
680162a10bbb27848e47653ad4241a1d8300343611aaf215269802c31c7cf189
|
|
| MD5 |
7f265d5557634e8af92c85ee023a22b0
|
|
| BLAKE2b-256 |
3e4a35b2ca23263d2cbced875a2dc2e2b57dd78765c68c7856b114bdf77ebb65
|