molejo 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- molejo-0.1.0/LICENSE +202 -0
- molejo-0.1.0/MANIFEST.in +5 -0
- molejo-0.1.0/NOTICE +2 -0
- molejo-0.1.0/PKG-INFO +169 -0
- molejo-0.1.0/README.md +147 -0
- molejo-0.1.0/molejo/__init__.py +79 -0
- molejo-0.1.0/molejo/_occt.py +653 -0
- molejo-0.1.0/molejo/authoring.py +473 -0
- molejo-0.1.0/molejo/brep.py +164 -0
- molejo-0.1.0/molejo/evaluator.py +1070 -0
- molejo-0.1.0/molejo/spec.py +417 -0
- molejo-0.1.0/molejo.egg-info/PKG-INFO +169 -0
- molejo-0.1.0/molejo.egg-info/SOURCES.txt +16 -0
- molejo-0.1.0/molejo.egg-info/dependency_links.txt +1 -0
- molejo-0.1.0/molejo.egg-info/requires.txt +4 -0
- molejo-0.1.0/molejo.egg-info/top_level.txt +1 -0
- molejo-0.1.0/pyproject.toml +48 -0
- molejo-0.1.0/setup.cfg +4 -0
molejo-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|
molejo-0.1.0/MANIFEST.in
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# The test suite is a repository asset, not a source-distribution one: it
|
|
2
|
+
# reads the shared parity fixtures at `fixtures/`, one level above this
|
|
3
|
+
# package directory and outside anything an sdist may contain. Shipping it
|
|
4
|
+
# would ship a suite that cannot run. Clone the repository to run the tests.
|
|
5
|
+
prune tests
|
molejo-0.1.0/NOTICE
ADDED
molejo-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: molejo
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Analytic flexible parts for mechanical CAD: parametric swept shapes evaluated identically in Python and the browser
|
|
5
|
+
Author-email: Luis Henrique Cassis Fagundes <lhfagundes@gmail.com>
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
Project-URL: Homepage, https://github.com/LibreSolid/molejo
|
|
8
|
+
Project-URL: Documentation, https://molejo.readthedocs.io
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Manufacturing
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
License-File: LICENSE
|
|
17
|
+
License-File: NOTICE
|
|
18
|
+
Requires-Dist: numpy
|
|
19
|
+
Provides-Extra: brep
|
|
20
|
+
Requires-Dist: cadquery-ocp; extra == "brep"
|
|
21
|
+
Dynamic: license-file
|
|
22
|
+
|
|
23
|
+
# molejo
|
|
24
|
+
|
|
25
|
+
*The give in your machine.*
|
|
26
|
+
|
|
27
|
+
**molejo** (Brazilian Portuguese: the springy give of a thing) is an
|
|
28
|
+
analytic representation for the flexible parts of a machine — valve
|
|
29
|
+
springs, timing belts, cable looms, filament — parts whose *shape* is a
|
|
30
|
+
function of machine state, not just their placement.
|
|
31
|
+
|
|
32
|
+
A molejo shape is a serializable **spec**: a planar profile swept along a
|
|
33
|
+
parametric path, whose numeric slots may reference named scalar
|
|
34
|
+
parameters. The spec is the model. Meshes are evaluations of it:
|
|
35
|
+
|
|
36
|
+
- the **Python evaluator** turns a spec plus parameter values into an
|
|
37
|
+
exact triangle mesh (and STL) for build pipelines, geometric tests,
|
|
38
|
+
and collision checks;
|
|
39
|
+
- the **JavaScript evaluator** turns the same spec plus the same values
|
|
40
|
+
into vertex buffers for three.js, cheap enough to re-evaluate every
|
|
41
|
+
animation frame;
|
|
42
|
+
- an optional **B-rep evaluator** (OCCT, via the `brep` extra of the
|
|
43
|
+
Python package) turns the same spec plus the same values into an
|
|
44
|
+
exact solid, for testing architectures that assert on exact shapes.
|
|
45
|
+
|
|
46
|
+
Both evaluators emit the same vertex count in the same order by
|
|
47
|
+
construction — tessellation is fixed and declared in the spec, never
|
|
48
|
+
curvature-adaptive — and are pinned to each other by shared parity
|
|
49
|
+
fixtures.
|
|
50
|
+
|
|
51
|
+
Full documentation: <https://molejo.readthedocs.io>
|
|
52
|
+
|
|
53
|
+
## What it looks like
|
|
54
|
+
|
|
55
|
+
Authoring is Python-first; the JSON spec is the representation it
|
|
56
|
+
serializes to:
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
from molejo import Shape, Circle, Helix, P
|
|
60
|
+
|
|
61
|
+
spring = Shape(
|
|
62
|
+
profile=Circle(radius=2.0),
|
|
63
|
+
path=[Helix(radius=14.0, turns=6.5, height=P.height)],
|
|
64
|
+
path_samples=240, profile_samples=16,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
mesh = spring.evaluate(height=46.8) # numpy vertices and faces
|
|
68
|
+
spring.to_json() # the spec — what a browser gets
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
`P.height` is a plain reference, not an expression: derived values
|
|
72
|
+
(`free_length - lift`) are computed in ordinary Python and bound at
|
|
73
|
+
evaluation. The browser side consumes the serialized spec only:
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
import { evaluate } from 'molejo';
|
|
77
|
+
evaluate(spec, { height: 50.0 - lift(t) }, buffers); // per frame, in place
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Why
|
|
81
|
+
|
|
82
|
+
CAD kernels represent rigid geometry; animation systems interpolate
|
|
83
|
+
placement. A compressing spring, a circulating belt, or a cable loom
|
|
84
|
+
following a print head falls between the two: its geometry at any
|
|
85
|
+
instant is exact, closed-form math over a few scalars (a lift, a
|
|
86
|
+
carriage position), but no kernel evaluates that math in both a build
|
|
87
|
+
pipeline and a browser at frame rate.
|
|
88
|
+
|
|
89
|
+
Sampling the shape (morph targets, frame swapping) works for one
|
|
90
|
+
parameter and dies combinatorially at two or three — a loom that follows
|
|
91
|
+
X, Y and Z would need a sampled grid over all of them. molejo instead
|
|
92
|
+
keeps the shape analytic and moves the *evaluation* to wherever it is
|
|
93
|
+
needed.
|
|
94
|
+
|
|
95
|
+
## Design properties
|
|
96
|
+
|
|
97
|
+
- **Analytic master, evaluations on demand.** The spec defines exact
|
|
98
|
+
curves and surfaces; every mesh is a deterministic sampling of them
|
|
99
|
+
at the declared resolution, and the B-rep evaluator constructs the
|
|
100
|
+
same curves exactly in OCCT. Line- and arc-based sweeps (belts) are
|
|
101
|
+
analytic surfaces; helix and spline sweeps are tolerance-declared
|
|
102
|
+
B-spline surfaces, as in any kernel.
|
|
103
|
+
- **Sweeps only, no booleans.** A closed profile swept along a path is
|
|
104
|
+
watertight by construction; there is no repair pass because no input
|
|
105
|
+
can be broken. Boolean interaction belongs to whatever mesh machinery
|
|
106
|
+
consumes the evaluation.
|
|
107
|
+
- **Parameters are plain named numbers.** molejo does not know where
|
|
108
|
+
they come from — a slider, a kinematic expression, a test instant.
|
|
109
|
+
Expression languages belong to the consumer.
|
|
110
|
+
- **Continuity and self-intersection are the author's obligation.** The
|
|
111
|
+
representation does not police an over-compressed spring; the
|
|
112
|
+
consumer's tests can.
|
|
113
|
+
|
|
114
|
+
## Status
|
|
115
|
+
|
|
116
|
+
Version 0.1.0, implementing spec version 1: profiles (circle, polygon)
|
|
117
|
+
and path primitives (line, arc, helix, spline, wrap). Both packages
|
|
118
|
+
parse and validate the document against shared fixtures; the Python
|
|
119
|
+
package also authors it (`Shape`, `Circle`, …, `P`).
|
|
120
|
+
|
|
121
|
+
Circle and polygon profiles swept along the whole v1 path vocabulary —
|
|
122
|
+
`line`, `arc`, `helix`, `spline` and `wrap` — evaluate in both runtimes,
|
|
123
|
+
singly or chained, capped or closed into a loop and watertight either
|
|
124
|
+
way, from Python as numpy arrays and binary STL, from JavaScript as
|
|
125
|
+
reusable three.js buffers, pinned to each other by shared parity
|
|
126
|
+
fixtures. The spring in the sample above is one of those fixtures rather
|
|
127
|
+
than a promise, and so are a toothed belt around three pulleys whose
|
|
128
|
+
teeth circulate with a parameter and a filament loom whose head follows
|
|
129
|
+
three. The one gap in the v1 vocabulary raises naming itself: closing a
|
|
130
|
+
loop that is not a wrap.
|
|
131
|
+
|
|
132
|
+
The B-rep evaluator installs with `pip install molejo[brep]` and
|
|
133
|
+
evaluates the same documents to closed OCCT solids —
|
|
134
|
+
`molejo.brep.evaluate(spec, values)` or `shape.brep(**values)` — with the
|
|
135
|
+
same refusals, word for word, as the mesh evaluator. Every parity fixture
|
|
136
|
+
is checked through it on volume and area. An install without the extra
|
|
137
|
+
imports and meshes and exports STL exactly as before; asking it for a
|
|
138
|
+
solid raises naming the extra.
|
|
139
|
+
|
|
140
|
+
molejo 0.1 has done real work before being called a release: it is the
|
|
141
|
+
flexible-part representation of [solid-node](https://github.com/LibreSolid/solid-node)
|
|
142
|
+
machine models, where its springs and belts hold up in animated,
|
|
143
|
+
geometrically tested engines and 3D printers (a V8 engine's valve
|
|
144
|
+
springs, a Metamaquina 2's drive belts) rather than only in this
|
|
145
|
+
repository's fixtures.
|
|
146
|
+
|
|
147
|
+
A package version carries the spec version it implements. Both packages
|
|
148
|
+
carry spec v1 at `0.1.0` and release together for a given spec version.
|
|
149
|
+
One document, two implementations: neither runtime is ever published
|
|
150
|
+
against a spec version the other has not caught up to.
|
|
151
|
+
|
|
152
|
+
Publishing to PyPI (`python/`) and npm (`js/`) is the maintainer's
|
|
153
|
+
explicit decision, never a side effect of building: `scripts/check-dist`,
|
|
154
|
+
the release dry-run, packs each package, installs it into a throwaway
|
|
155
|
+
environment outside this repository and evaluates a fixture there — and
|
|
156
|
+
uploads nothing.
|
|
157
|
+
|
|
158
|
+
## Origin
|
|
159
|
+
|
|
160
|
+
molejo was born from [solid-node](https://github.com/LibreSolid/solid-node),
|
|
161
|
+
a Python framework for mechanical CAD projects, which needed springs,
|
|
162
|
+
belts and cable looms in animated, testable machine models. solid-node
|
|
163
|
+
adapts molejo as one leaf-geometry technology among the several it
|
|
164
|
+
supports; molejo itself is independent and consumable by any Python or
|
|
165
|
+
three.js project.
|
|
166
|
+
|
|
167
|
+
## License
|
|
168
|
+
|
|
169
|
+
Apache License 2.0 — see `LICENSE`.
|
molejo-0.1.0/README.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# molejo
|
|
2
|
+
|
|
3
|
+
*The give in your machine.*
|
|
4
|
+
|
|
5
|
+
**molejo** (Brazilian Portuguese: the springy give of a thing) is an
|
|
6
|
+
analytic representation for the flexible parts of a machine — valve
|
|
7
|
+
springs, timing belts, cable looms, filament — parts whose *shape* is a
|
|
8
|
+
function of machine state, not just their placement.
|
|
9
|
+
|
|
10
|
+
A molejo shape is a serializable **spec**: a planar profile swept along a
|
|
11
|
+
parametric path, whose numeric slots may reference named scalar
|
|
12
|
+
parameters. The spec is the model. Meshes are evaluations of it:
|
|
13
|
+
|
|
14
|
+
- the **Python evaluator** turns a spec plus parameter values into an
|
|
15
|
+
exact triangle mesh (and STL) for build pipelines, geometric tests,
|
|
16
|
+
and collision checks;
|
|
17
|
+
- the **JavaScript evaluator** turns the same spec plus the same values
|
|
18
|
+
into vertex buffers for three.js, cheap enough to re-evaluate every
|
|
19
|
+
animation frame;
|
|
20
|
+
- an optional **B-rep evaluator** (OCCT, via the `brep` extra of the
|
|
21
|
+
Python package) turns the same spec plus the same values into an
|
|
22
|
+
exact solid, for testing architectures that assert on exact shapes.
|
|
23
|
+
|
|
24
|
+
Both evaluators emit the same vertex count in the same order by
|
|
25
|
+
construction — tessellation is fixed and declared in the spec, never
|
|
26
|
+
curvature-adaptive — and are pinned to each other by shared parity
|
|
27
|
+
fixtures.
|
|
28
|
+
|
|
29
|
+
Full documentation: <https://molejo.readthedocs.io>
|
|
30
|
+
|
|
31
|
+
## What it looks like
|
|
32
|
+
|
|
33
|
+
Authoring is Python-first; the JSON spec is the representation it
|
|
34
|
+
serializes to:
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from molejo import Shape, Circle, Helix, P
|
|
38
|
+
|
|
39
|
+
spring = Shape(
|
|
40
|
+
profile=Circle(radius=2.0),
|
|
41
|
+
path=[Helix(radius=14.0, turns=6.5, height=P.height)],
|
|
42
|
+
path_samples=240, profile_samples=16,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
mesh = spring.evaluate(height=46.8) # numpy vertices and faces
|
|
46
|
+
spring.to_json() # the spec — what a browser gets
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`P.height` is a plain reference, not an expression: derived values
|
|
50
|
+
(`free_length - lift`) are computed in ordinary Python and bound at
|
|
51
|
+
evaluation. The browser side consumes the serialized spec only:
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
import { evaluate } from 'molejo';
|
|
55
|
+
evaluate(spec, { height: 50.0 - lift(t) }, buffers); // per frame, in place
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Why
|
|
59
|
+
|
|
60
|
+
CAD kernels represent rigid geometry; animation systems interpolate
|
|
61
|
+
placement. A compressing spring, a circulating belt, or a cable loom
|
|
62
|
+
following a print head falls between the two: its geometry at any
|
|
63
|
+
instant is exact, closed-form math over a few scalars (a lift, a
|
|
64
|
+
carriage position), but no kernel evaluates that math in both a build
|
|
65
|
+
pipeline and a browser at frame rate.
|
|
66
|
+
|
|
67
|
+
Sampling the shape (morph targets, frame swapping) works for one
|
|
68
|
+
parameter and dies combinatorially at two or three — a loom that follows
|
|
69
|
+
X, Y and Z would need a sampled grid over all of them. molejo instead
|
|
70
|
+
keeps the shape analytic and moves the *evaluation* to wherever it is
|
|
71
|
+
needed.
|
|
72
|
+
|
|
73
|
+
## Design properties
|
|
74
|
+
|
|
75
|
+
- **Analytic master, evaluations on demand.** The spec defines exact
|
|
76
|
+
curves and surfaces; every mesh is a deterministic sampling of them
|
|
77
|
+
at the declared resolution, and the B-rep evaluator constructs the
|
|
78
|
+
same curves exactly in OCCT. Line- and arc-based sweeps (belts) are
|
|
79
|
+
analytic surfaces; helix and spline sweeps are tolerance-declared
|
|
80
|
+
B-spline surfaces, as in any kernel.
|
|
81
|
+
- **Sweeps only, no booleans.** A closed profile swept along a path is
|
|
82
|
+
watertight by construction; there is no repair pass because no input
|
|
83
|
+
can be broken. Boolean interaction belongs to whatever mesh machinery
|
|
84
|
+
consumes the evaluation.
|
|
85
|
+
- **Parameters are plain named numbers.** molejo does not know where
|
|
86
|
+
they come from — a slider, a kinematic expression, a test instant.
|
|
87
|
+
Expression languages belong to the consumer.
|
|
88
|
+
- **Continuity and self-intersection are the author's obligation.** The
|
|
89
|
+
representation does not police an over-compressed spring; the
|
|
90
|
+
consumer's tests can.
|
|
91
|
+
|
|
92
|
+
## Status
|
|
93
|
+
|
|
94
|
+
Version 0.1.0, implementing spec version 1: profiles (circle, polygon)
|
|
95
|
+
and path primitives (line, arc, helix, spline, wrap). Both packages
|
|
96
|
+
parse and validate the document against shared fixtures; the Python
|
|
97
|
+
package also authors it (`Shape`, `Circle`, …, `P`).
|
|
98
|
+
|
|
99
|
+
Circle and polygon profiles swept along the whole v1 path vocabulary —
|
|
100
|
+
`line`, `arc`, `helix`, `spline` and `wrap` — evaluate in both runtimes,
|
|
101
|
+
singly or chained, capped or closed into a loop and watertight either
|
|
102
|
+
way, from Python as numpy arrays and binary STL, from JavaScript as
|
|
103
|
+
reusable three.js buffers, pinned to each other by shared parity
|
|
104
|
+
fixtures. The spring in the sample above is one of those fixtures rather
|
|
105
|
+
than a promise, and so are a toothed belt around three pulleys whose
|
|
106
|
+
teeth circulate with a parameter and a filament loom whose head follows
|
|
107
|
+
three. The one gap in the v1 vocabulary raises naming itself: closing a
|
|
108
|
+
loop that is not a wrap.
|
|
109
|
+
|
|
110
|
+
The B-rep evaluator installs with `pip install molejo[brep]` and
|
|
111
|
+
evaluates the same documents to closed OCCT solids —
|
|
112
|
+
`molejo.brep.evaluate(spec, values)` or `shape.brep(**values)` — with the
|
|
113
|
+
same refusals, word for word, as the mesh evaluator. Every parity fixture
|
|
114
|
+
is checked through it on volume and area. An install without the extra
|
|
115
|
+
imports and meshes and exports STL exactly as before; asking it for a
|
|
116
|
+
solid raises naming the extra.
|
|
117
|
+
|
|
118
|
+
molejo 0.1 has done real work before being called a release: it is the
|
|
119
|
+
flexible-part representation of [solid-node](https://github.com/LibreSolid/solid-node)
|
|
120
|
+
machine models, where its springs and belts hold up in animated,
|
|
121
|
+
geometrically tested engines and 3D printers (a V8 engine's valve
|
|
122
|
+
springs, a Metamaquina 2's drive belts) rather than only in this
|
|
123
|
+
repository's fixtures.
|
|
124
|
+
|
|
125
|
+
A package version carries the spec version it implements. Both packages
|
|
126
|
+
carry spec v1 at `0.1.0` and release together for a given spec version.
|
|
127
|
+
One document, two implementations: neither runtime is ever published
|
|
128
|
+
against a spec version the other has not caught up to.
|
|
129
|
+
|
|
130
|
+
Publishing to PyPI (`python/`) and npm (`js/`) is the maintainer's
|
|
131
|
+
explicit decision, never a side effect of building: `scripts/check-dist`,
|
|
132
|
+
the release dry-run, packs each package, installs it into a throwaway
|
|
133
|
+
environment outside this repository and evaluates a fixture there — and
|
|
134
|
+
uploads nothing.
|
|
135
|
+
|
|
136
|
+
## Origin
|
|
137
|
+
|
|
138
|
+
molejo was born from [solid-node](https://github.com/LibreSolid/solid-node),
|
|
139
|
+
a Python framework for mechanical CAD projects, which needed springs,
|
|
140
|
+
belts and cable looms in animated, testable machine models. solid-node
|
|
141
|
+
adapts molejo as one leaf-geometry technology among the several it
|
|
142
|
+
supports; molejo itself is independent and consumable by any Python or
|
|
143
|
+
three.js project.
|
|
144
|
+
|
|
145
|
+
## License
|
|
146
|
+
|
|
147
|
+
Apache License 2.0 — see `LICENSE`.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# molejo - analytic flexible parts for mechanical CAD
|
|
2
|
+
# Copyright (C) 2026 Luis Henrique Cassis Fagundes
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
|
|
5
|
+
"""Analytic flexible parts for mechanical CAD.
|
|
6
|
+
|
|
7
|
+
A molejo shape is a serializable spec -- a planar profile swept along a
|
|
8
|
+
parametric path whose numeric slots may reference named scalar
|
|
9
|
+
parameters. This package is the Python side: the authoring layer that
|
|
10
|
+
writes the spec, and the evaluator that turns spec plus parameter values
|
|
11
|
+
into a deterministic triangle mesh::
|
|
12
|
+
|
|
13
|
+
from molejo import Shape, Circle, Line, P
|
|
14
|
+
|
|
15
|
+
tube = Shape(
|
|
16
|
+
profile=Circle(radius=2.0),
|
|
17
|
+
path=[Line(to=(0.0, 0.0, P.length))],
|
|
18
|
+
path_samples=8, profile_samples=32,
|
|
19
|
+
)
|
|
20
|
+
tube.to_json() # the spec -- what a browser gets
|
|
21
|
+
mesh = tube.evaluate(length=46.8) # numpy vertices and faces
|
|
22
|
+
mesh.to_stl() # binary STL bytes
|
|
23
|
+
|
|
24
|
+
Spec version 1 is defined in :mod:`molejo.spec` and evaluated in
|
|
25
|
+
:mod:`molejo.evaluator`, which sweeps a circle or polygon profile along
|
|
26
|
+
the whole v1 path vocabulary -- ``line``, ``arc``, ``helix``, ``spline``
|
|
27
|
+
and ``wrap`` -- open or closed into a loop.
|
|
28
|
+
|
|
29
|
+
:mod:`molejo.brep` evaluates the same documents exactly, to closed OCCT
|
|
30
|
+
solids, for a consumer whose testing architecture asserts on exact
|
|
31
|
+
shapes::
|
|
32
|
+
|
|
33
|
+
tube.brep(length=46.8).volume()
|
|
34
|
+
|
|
35
|
+
It needs the ``brep`` extra (``pip install molejo[brep]``) and is
|
|
36
|
+
imported only when asked for, so a plain install meshes and exports STL
|
|
37
|
+
on numpy alone. See the repository's openspec/ records.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
from .authoring import (
|
|
41
|
+
Arc,
|
|
42
|
+
Circle,
|
|
43
|
+
Helix,
|
|
44
|
+
Line,
|
|
45
|
+
P,
|
|
46
|
+
ParamRef,
|
|
47
|
+
Polygon,
|
|
48
|
+
Shape,
|
|
49
|
+
Spline,
|
|
50
|
+
Teeth,
|
|
51
|
+
Wrap,
|
|
52
|
+
)
|
|
53
|
+
from .evaluator import EvaluationError, Mesh, evaluate
|
|
54
|
+
from .spec import SPEC_VERSION, SpecError, parameter_names, validate
|
|
55
|
+
|
|
56
|
+
__author__ = "Luis Henrique Cassis Fagundes"
|
|
57
|
+
__email__ = "lhfagundes@gmail.com"
|
|
58
|
+
__version__ = "0.1.0"
|
|
59
|
+
|
|
60
|
+
__all__ = [
|
|
61
|
+
"SPEC_VERSION",
|
|
62
|
+
"Arc",
|
|
63
|
+
"Circle",
|
|
64
|
+
"EvaluationError",
|
|
65
|
+
"Helix",
|
|
66
|
+
"Line",
|
|
67
|
+
"Mesh",
|
|
68
|
+
"P",
|
|
69
|
+
"ParamRef",
|
|
70
|
+
"Polygon",
|
|
71
|
+
"Shape",
|
|
72
|
+
"SpecError",
|
|
73
|
+
"Spline",
|
|
74
|
+
"Teeth",
|
|
75
|
+
"Wrap",
|
|
76
|
+
"evaluate",
|
|
77
|
+
"parameter_names",
|
|
78
|
+
"validate",
|
|
79
|
+
]
|