@code3d/core 0.0.1-alpha.0 → 0.0.1-alpha.2
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.
- package/README.md +223 -786
- package/THIRD_PARTY.md +40 -0
- package/bld/THIRD_PARTY_NOTICES.txt +182 -0
- package/bld/chunks/chunk-5E6VXJU2.js +30 -0
- package/bld/chunks/chunk-5E6VXJU2.js.map +7 -0
- package/bld/chunks/chunk-63ZUQWQ2.js +19 -0
- package/bld/chunks/chunk-63ZUQWQ2.js.map +7 -0
- package/bld/chunks/chunk-AWYI64EE.js +31 -0
- package/bld/chunks/chunk-AWYI64EE.js.map +7 -0
- package/bld/chunks/chunk-F53RTQPT.js +24787 -0
- package/bld/chunks/chunk-F53RTQPT.js.map +7 -0
- package/bld/chunks/chunk-TJIN6S4R.js +1 -0
- package/bld/chunks/chunk-TJIN6S4R.js.map +7 -0
- package/bld/library/cached.d.ts +33 -0
- package/bld/library/cached.d.ts.map +1 -0
- package/bld/library/font.d.ts +39 -0
- package/bld/library/font.d.ts.map +1 -0
- package/bld/library/google-font.d.ts +14 -0
- package/bld/library/google-font.d.ts.map +1 -0
- package/bld/library/index.d.ts +8 -2
- package/bld/library/index.d.ts.map +1 -1
- package/bld/library/index.js +60 -3
- package/bld/library/index.js.map +7 -1
- package/bld/library/kernel-artifact-codec.d.ts.map +1 -1
- package/bld/library/kernel-cache.d.ts +17 -6
- package/bld/library/kernel-cache.d.ts.map +1 -1
- package/bld/library/material.d.ts +1 -1
- package/bld/library/material.d.ts.map +1 -1
- package/bld/library/open-cascade.d.ts +4 -0
- package/bld/library/open-cascade.d.ts.map +1 -0
- package/bld/library/replicad.d.ts +3 -2
- package/bld/library/replicad.d.ts.map +1 -1
- package/bld/library/replicad.js +10 -24
- package/bld/library/replicad.js.map +7 -1
- package/bld/library/retained-memory.d.ts.map +1 -1
- package/bld/library/runtime.d.ts +144 -80
- package/bld/library/runtime.d.ts.map +1 -1
- package/bld/library/sketch-solver.d.ts +1 -1
- package/bld/library/sketch-solver.d.ts.map +1 -1
- package/bld/library/sketch.d.ts +9 -1
- package/bld/library/sketch.d.ts.map +1 -1
- package/bld/library/text.d.ts +53 -0
- package/bld/library/text.d.ts.map +1 -0
- package/bld/library/three.js +3 -3
- package/bld/library/three.js.map +7 -1
- package/bld/node/index.d.ts.map +1 -1
- package/bld/node/index.js +62 -14
- package/bld/node/index.js.map +7 -1
- package/bld/node/replicad.js +13 -3
- package/bld/node/replicad.js.map +7 -1
- package/bld/tooling/index.d.ts +17 -15
- package/bld/tooling/index.d.ts.map +1 -1
- package/bld/tooling/index.js +147 -19
- package/bld/tooling/index.js.map +7 -1
- package/package.json +18 -6
- package/src/library/cached.ts +132 -0
- package/src/library/font.ts +186 -0
- package/src/library/google-font.ts +97 -0
- package/src/library/index.ts +8 -3
- package/src/library/kernel-artifact-codec.ts +129 -20
- package/src/library/kernel-cache.ts +111 -33
- package/src/library/material.ts +3 -4
- package/src/library/open-cascade.ts +13 -0
- package/src/library/replicad.ts +5 -5
- package/src/library/retained-memory.ts +6 -1
- package/src/library/runtime.ts +2049 -1728
- package/src/library/sketch-solver.ts +3 -1
- package/src/library/sketch.ts +81 -13
- package/src/library/text.ts +477 -0
- package/src/library/tsconfig.json +2 -1
- package/src/node/index.ts +14 -3
- package/src/node/tsconfig.json +2 -1
- package/src/tooling/index.ts +48 -46
- package/src/tooling/tsconfig.json +2 -1
- package/bld/library/alignment-geometry.js +0 -322
- package/bld/library/alignment-geometry.js.map +0 -1
- package/bld/library/bound-solver.js +0 -252
- package/bld/library/bound-solver.js.map +0 -1
- package/bld/library/extrude.js +0 -28
- package/bld/library/extrude.js.map +0 -1
- package/bld/library/kernel-artifact-codec.js +0 -148
- package/bld/library/kernel-artifact-codec.js.map +0 -1
- package/bld/library/kernel-cache.js +0 -245
- package/bld/library/kernel-cache.js.map +0 -1
- package/bld/library/kernel-shapes.js +0 -108
- package/bld/library/kernel-shapes.js.map +0 -1
- package/bld/library/loft.js +0 -161
- package/bld/library/loft.js.map +0 -1
- package/bld/library/material.js +0 -176
- package/bld/library/material.js.map +0 -1
- package/bld/library/model-color.js +0 -36
- package/bld/library/model-color.js.map +0 -1
- package/bld/library/open-cascade-error.js +0 -22
- package/bld/library/open-cascade-error.js.map +0 -1
- package/bld/library/relation-solver.js +0 -258
- package/bld/library/relation-solver.js.map +0 -1
- package/bld/library/retained-memory.js +0 -27
- package/bld/library/retained-memory.js.map +0 -1
- package/bld/library/runtime.js +0 -2954
- package/bld/library/runtime.js.map +0 -1
- package/bld/library/shell.js +0 -221
- package/bld/library/shell.js.map +0 -1
- package/bld/library/sketch-curve-intersections.js +0 -117
- package/bld/library/sketch-curve-intersections.js.map +0 -1
- package/bld/library/sketch-curves.js +0 -89
- package/bld/library/sketch-curves.js.map +0 -1
- package/bld/library/sketch-drag-rules.js +0 -522
- package/bld/library/sketch-drag-rules.js.map +0 -1
- package/bld/library/sketch-face.js +0 -72
- package/bld/library/sketch-face.js.map +0 -1
- package/bld/library/sketch-incidence.js +0 -114
- package/bld/library/sketch-incidence.js.map +0 -1
- package/bld/library/sketch-precision.js +0 -55
- package/bld/library/sketch-precision.js.map +0 -1
- package/bld/library/sketch-regions.js +0 -193
- package/bld/library/sketch-regions.js.map +0 -1
- package/bld/library/sketch-solver.js +0 -578
- package/bld/library/sketch-solver.js.map +0 -1
- package/bld/library/sketch.js +0 -650
- package/bld/library/sketch.js.map +0 -1
- package/bld/library/spatial.js +0 -195
- package/bld/library/spatial.js.map +0 -1
- package/bld/library/topology-id.js +0 -67
- package/bld/library/topology-id.js.map +0 -1
- package/bld/library/topology-inspection.js +0 -267
- package/bld/library/topology-inspection.js.map +0 -1
- package/bld/library/topology.js +0 -455
- package/bld/library/topology.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,824 +1,261 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
3
|
-
The code3d authoring runtime. Model projects install this package directly and
|
|
4
|
-
may execute the same ESM TypeScript source in code3d or a supported Node.js
|
|
5
|
-
runtime.
|
|
6
|
-
|
|
7
|
-
The App also offers zero-install authoring with built-in core and screws. When
|
|
8
|
-
the project's root `package.json` declares `@code3d/core`, the App uses the
|
|
9
|
-
project's installed packages exclusively, including their declarations; missing
|
|
10
|
-
dependencies are errors rather than a reason to substitute built-in packages.
|
|
11
|
-
Direct Node execution requires installing the project dependencies.
|
|
12
|
-
|
|
13
|
-
The public API includes solid primitives and Boolean operations, first-class
|
|
14
|
-
planar face models (`circle`, `ellipse`, `rectangle`, `regularPolygon`), 3D
|
|
15
|
-
curve models (`line`, `arc`, `bezier`, `spline`), point models, face extrusion, and
|
|
16
|
-
through-section or spine-guided `loft`. Every geometric model is immutable,
|
|
17
|
-
renderable, and relation-aware. Topology capabilities follow dimension:
|
|
18
|
-
vertices provide `.vertex(id)`, edges add `.edge(id)`, and faces and solids
|
|
19
|
-
add `.surface(id)`; only solids provide `fillet`, `chamfer`, and `shell`. Groups retain
|
|
20
|
-
the common relation, expose, and material capabilities without pretending to
|
|
21
|
-
contain geometry. Stable topology references can be used as geometric relation anchors.
|
|
22
|
-
`Vertex`, `Edge`, and `Surface` references expose readonly `kind` and `id`
|
|
23
|
-
properties. For example, `model.edges().map(edge => edge.id)` collects edge IDs
|
|
24
|
-
for a later operation on that model. Their `kind` values are `vertex`, `edge`,
|
|
25
|
-
and `surface`; IDs belong to that model and topology kind. Plain named anchors
|
|
26
|
-
such as `model.up` do not expose these topology properties.
|
|
27
|
-
`TopologyId` is a number or a flat numeric path. Topology-changing operations
|
|
28
|
-
prefix one-to-one descendants with their one-based input index, so an input's
|
|
29
|
-
`E3` becomes `[1, 3]`, or `[2, 3]` for the second input. New/ambiguous elements
|
|
30
|
-
start at numeric `1` in each result. Fillet/chamfer/shell also add input index `1`;
|
|
31
|
-
transforms preserve complete paths. Select a path with `.edge([1, 3])`, or a
|
|
32
|
-
mixed collection with `.edges([1, [1, 3], [2, 3]])`. Loft caps use their endpoint
|
|
33
|
-
section paths; Boolean operations inherit from all inputs. Splits and merges
|
|
34
|
-
retire ambiguous source paths. Full rules are in the
|
|
35
|
-
[topology guide](../web/src/content/docs/docs/guides/topology.md).
|
|
36
|
-
`relate()` records placement for composition with other values; inspecting or
|
|
37
|
-
rendering the resulting value by itself uses its own local geometry.
|
|
38
|
-
|
|
39
|
-
## Runtime defaults
|
|
40
|
-
|
|
41
|
-
Dimension-based primitives keep required TypeScript signatures while supplying
|
|
42
|
-
runtime defaults for omitted or `undefined` arguments. For example, `box()`
|
|
43
|
-
produces the same geometry as `box(10, 10, 10)`, but TypeScript still requires all
|
|
44
|
-
three dimensions. Explicit invalid values keep their normal errors. These
|
|
45
|
-
defaults work in ordinary JavaScript execution as well as App previews.
|
|
46
|
-
The [Modeling API](../web/src/content/docs/docs/reference/core.md#runtime-defaults-while-editing)
|
|
47
|
-
lists the defaults for all supported primitives. The App displays them as
|
|
48
|
-
placeholders without inserting arguments into source.
|
|
49
|
-
|
|
50
|
-
## Face extrusion
|
|
51
|
-
|
|
52
|
-
`face.extrude(distance)` and `extrude(face, distance)` produce a `SolidModel`
|
|
53
|
-
from one planar face model. The finite, non-zero signed distance follows the
|
|
54
|
-
face's local normal, including any prior rotation. The starting face stays in
|
|
55
|
-
place: an unrotated profile extruded by `3` spans Y = 0 to 3; `-3` spans -3 to 0.
|
|
56
|
-
Origin offsets and input geometry are preserved, and the result supports ordinary
|
|
57
|
-
solid operations. To extrude multiple faces, map them explicitly.
|
|
1
|
+
# @code3d/core
|
|
58
2
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
export const plate = rectangle(30, 20).extrude(3).fillet(0.5);
|
|
63
|
-
export const pin = extrude(circle(2), -10);
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
## Editable sketches
|
|
3
|
+
The TypeScript modeling runtime used by Code3D. Compose solids, profiles, curves,
|
|
4
|
+
points, and editable sketches; inspect their geometry and reuse the same models
|
|
5
|
+
in the App or a supported Node.js runtime.
|
|
67
6
|
|
|
68
|
-
|
|
7
|
+
## Start with a model
|
|
69
8
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
The editor inserts the array only when the first drawing is completed; cancelling
|
|
73
|
-
leaves the call unchanged, and undo restores the original call and its comments.
|
|
74
|
-
|
|
75
|
-
```ts
|
|
76
|
-
import {sketch} from '@code3d/core';
|
|
77
|
-
|
|
78
|
-
const sketch1 = sketch(
|
|
79
|
-
[
|
|
80
|
-
['point', 1, [0, 0]],
|
|
81
|
-
['point', 2, [30, 0]],
|
|
82
|
-
['line', 3, [1, 2]],
|
|
83
|
-
],
|
|
84
|
-
{
|
|
85
|
-
constraints: [
|
|
86
|
-
['fixed', 1],
|
|
87
|
-
['horizontal', 3],
|
|
88
|
-
['length', 3, 30],
|
|
89
|
-
],
|
|
90
|
-
},
|
|
91
|
-
);
|
|
92
|
-
const sketch2 = sketch1.derive([
|
|
93
|
-
['point', 1, [10, 20]],
|
|
94
|
-
['line', 2, [sketch1.point(2), 1]],
|
|
95
|
-
]);
|
|
9
|
+
```sh
|
|
10
|
+
npm install @code3d/core
|
|
96
11
|
```
|
|
97
12
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
independent positive-integer ID space shared by its geometry entities. Definitions
|
|
101
|
-
may be empty, open, or contain crossing lines; crossings do not automatically
|
|
102
|
-
split entities. Missing point references are errors.
|
|
13
|
+
```ts
|
|
14
|
+
import {box, cylinder, group} from '@code3d/core';
|
|
103
15
|
|
|
104
|
-
|
|
16
|
+
const base = box(40, 4, 24).fillet(1);
|
|
17
|
+
const post = cylinder(3, 18).relate(self => self.on(base.up));
|
|
105
18
|
|
|
106
|
-
|
|
107
|
-
const circles = sketch(
|
|
108
|
-
[
|
|
109
|
-
['point', 1, [0, 0]],
|
|
110
|
-
['circle', 2, [1, 15]],
|
|
111
|
-
['circle', 3, [1, 8]],
|
|
112
|
-
],
|
|
113
|
-
{constraints: [['radius', 3, 8]]},
|
|
114
|
-
);
|
|
19
|
+
export default group([base, post]);
|
|
115
20
|
```
|
|
116
21
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
22
|
+
Open this source in Code3D and select an expression to inspect its value. Node
|
|
23
|
+
loads the modeling kernel through the package's Node entry automatically; normal
|
|
24
|
+
model authors do not initialize it or manage evaluation caches themselves.
|
|
25
|
+
|
|
26
|
+
The App includes Core, [Materials](../materials/README.md), and
|
|
27
|
+
[Screws](../screws/README.md) for zero-install projects. When the active model's
|
|
28
|
+
package scope or an ancestor `package.json` declares `@code3d/core`, the App uses that project's installed
|
|
29
|
+
packages and declarations exclusively. Missing dependencies are errors. See
|
|
30
|
+
[project package installation](../web/src/content/docs/docs/getting-started/files.md#install-packages-in-browser-storage)
|
|
31
|
+
and the [agent file workflow](../../docs/agents/files.md).
|
|
32
|
+
|
|
33
|
+
## Model values and coordinates
|
|
34
|
+
|
|
35
|
+
Operations produce new model values. Building another result must not change an
|
|
36
|
+
already-observable model's geometry, material, topology, or relations.
|
|
37
|
+
|
|
38
|
+
A model's local geometry and its placement in a composition are separate.
|
|
39
|
+
`relate()` records how a part is placed when composed with other parts; observing
|
|
40
|
+
that part alone shows its local geometry. `originOffset()` changes geometry
|
|
41
|
+
coordinates without changing the shape. Position arrays use `[x, y, z]`; scalar
|
|
42
|
+
angles use degrees. Read [local coordinates](../web/src/content/docs/docs/concepts/local-coordinates.md)
|
|
43
|
+
and [relations](../web/src/content/docs/docs/guides/relations.mdx) before mixing
|
|
44
|
+
origin changes, alignment, and rotation.
|
|
45
|
+
|
|
46
|
+
Build readable models from named intermediate values and public operations. A
|
|
47
|
+
profile followed by extrusion, or solids combined with Boolean operations,
|
|
48
|
+
keeps the construction understandable and editable by both people and agents.
|
|
49
|
+
|
|
50
|
+
## Find the modeling API
|
|
51
|
+
|
|
52
|
+
| Task | Start here |
|
|
53
|
+
| ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
|
|
54
|
+
| Solids, planar profiles, curves, points, Boolean operations, extrusion and loft | [Modeling reference](../web/src/content/docs/docs/reference/core.md) |
|
|
55
|
+
| Place parts with bounds or align underlying geometry | [Relations](../web/src/content/docs/docs/guides/relations.mdx) |
|
|
56
|
+
| Change origins and rotate parts | [Origins and rotation](../web/src/content/docs/docs/guides/origins-and-rotation.mdx) |
|
|
57
|
+
| Hollow a solid or choose openings | [Shells](../web/src/content/docs/docs/guides/shells.mdx) |
|
|
58
|
+
| Select vertices, edges and surfaces, or expose named elements | [Topology](../web/src/content/docs/docs/guides/topology.md) |
|
|
59
|
+
| Build reusable model functions | [Reusable models](../web/src/content/docs/docs/guides/reusable-models.mdx) |
|
|
60
|
+
| Give functions editing tools and example arguments | [Model tools](../web/src/content/docs/docs/guides/model-tools.mdx) |
|
|
61
|
+
| Extend the runtime with Replicad geometry | [Custom primitives](../web/src/content/docs/docs/guides/custom-primitives.mdx) |
|
|
62
|
+
| Known boundaries | [Current limitations](../web/src/content/docs/docs/reference/limitations.md) |
|
|
63
|
+
|
|
64
|
+
Dimension-based primitives and numeric modeling methods retain required TypeScript
|
|
65
|
+
signatures while providing runtime defaults for omitted or `undefined` values.
|
|
66
|
+
Rotations and displacements default to zero, scaling to one, extrusion distance
|
|
67
|
+
to ten, and fillet radius, chamfer distance and shell thickness to one. Relation
|
|
68
|
+
rotation chains use the same angle defaults; `pivot()` defaults to local zero.
|
|
69
|
+
Explicit invalid values retain their normal errors. These defaults work in
|
|
70
|
+
ordinary JavaScript execution as well as App previews.
|
|
71
|
+
|
|
72
|
+
The App displays defaults as placeholders without inserting source arguments.
|
|
73
|
+
Committing a spatial drag fills all remaining omitted defaults in that operation;
|
|
74
|
+
for example, dragging the X ring of `rotate()` writes `rotate(angle, 0, 0)`. The
|
|
75
|
+
edit and completion share one undo step. Use explicit dimensions in finished
|
|
76
|
+
models; the [reference](../web/src/content/docs/docs/reference/core.md#runtime-defaults-while-editing)
|
|
77
|
+
lists the actual defaults.
|
|
78
|
+
|
|
79
|
+
Topology capabilities follow dimension: vertices expose vertex selection, edges
|
|
80
|
+
add edge selection, and faces and solids add surface selection. Only solids
|
|
81
|
+
provide `fillet`, `chamfer`, and `shell`. Groups compose values and support
|
|
82
|
+
relations, exposed elements, and materials without pretending to be geometry.
|
|
83
|
+
|
|
84
|
+
Groups are model values and can be nested directly with `group([inner, other])`,
|
|
85
|
+
including in mixed `Model[]` collections. Nesting preserves each group's hierarchy;
|
|
86
|
+
`expose()` adds named references when callers need to address members.
|
|
87
|
+
|
|
88
|
+
A topology ID belongs to its owning model and element kind. It is a number or a
|
|
89
|
+
flat numeric path, such as `.edge([1, 3])`. Operations track unambiguous ancestry;
|
|
90
|
+
transforms preserve complete paths. Inspect the result after topology changes
|
|
91
|
+
instead of assuming IDs from a different model still apply.
|
|
122
92
|
|
|
123
|
-
|
|
93
|
+
## Editable sketches
|
|
94
|
+
|
|
95
|
+
Sketches are immutable 2D definitions, separate from B-Rep model values. Entries
|
|
96
|
+
carry positive IDs within a layer; constraints express what should stay true.
|
|
97
|
+
A derived layer can reference its upstream geometry.
|
|
124
98
|
|
|
125
99
|
```ts
|
|
126
|
-
|
|
100
|
+
import {sketch} from '@code3d/core';
|
|
101
|
+
|
|
102
|
+
const profile = sketch(
|
|
127
103
|
[
|
|
128
104
|
['point', 1, [0, 0]],
|
|
129
|
-
['
|
|
130
|
-
['point', 3, [0, 10]],
|
|
131
|
-
['arc', 4, [1, 10, 2, 3, 'ccw']],
|
|
105
|
+
['circle', 2, [1, 8]],
|
|
132
106
|
],
|
|
133
107
|
{
|
|
134
108
|
constraints: [
|
|
135
|
-
['
|
|
136
|
-
['
|
|
109
|
+
['fixed', 1],
|
|
110
|
+
['radius', 2, 8],
|
|
137
111
|
],
|
|
138
112
|
},
|
|
139
113
|
);
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
`ccw` selects the counterclockwise arc in sketch coordinates; `cw` selects the
|
|
143
|
-
clockwise arc, including major arcs. Native arc equations keep both endpoints
|
|
144
|
-
on the circle; point coordinates and radius may move to satisfy them.
|
|
145
|
-
The radius is ordinary current data, not an implicit radius constraint.
|
|
146
|
-
To initialize inconsistent data, endpoints are projected along their supplied
|
|
147
|
-
directions to the supplied radius, or to an explicit radius dimension when one
|
|
148
|
-
already exists. This avoids projecting satisfied endpoints outward and then
|
|
149
|
-
allowing an underconstrained solve to translate the arc while shrinking it back.
|
|
150
|
-
Shared endpoints average simultaneous
|
|
151
|
-
proposals, without giving one arc ownership; locked/upstream, fixed and explicitly
|
|
152
|
-
positioned axes are not overwritten. The resulting seed is then solved against
|
|
153
|
-
all structural equations and explicit constraints. Thus an isolated arc with
|
|
154
|
-
radius 15 and endpoints initially at distances 10 starts at radius 15; if the
|
|
155
|
-
center and endpoints are explicitly fixed at radius 10, its radius solves to 10.
|
|
156
|
-
No extra lock, soft objective or degree of freedom is introduced.
|
|
157
|
-
Center and endpoints
|
|
158
|
-
can each reference a named upstream point. Zero-radius and coincident-endpoint arcs
|
|
159
|
-
are errors; use `circle` for a full circle.
|
|
160
|
-
The independent `sweep` constraint uses `['sweep', arcId, degrees]`, strictly greater than
|
|
161
|
-
0 and less than 360. Its positive magnitude follows the tuple's `cw`/`ccw`
|
|
162
|
-
direction, so 270 means a major arc in either direction. It does not fix the arc's
|
|
163
|
-
orientation: with a fixed center and radius, dragging an endpoint can rotate both
|
|
164
|
-
endpoints while preserving the sweep.
|
|
165
|
-
|
|
166
|
-
Geometry tuples hold current data; `constraints` specify what must remain true.
|
|
167
|
-
Constraints use `['kind', target, value?]` and have no persistent IDs. Point coordinates have the same runtime
|
|
168
|
-
meaning whether computed from an expression or written as literals. They may
|
|
169
|
-
move during solving unless constrained. `fixed` locks one point at its supplied
|
|
170
|
-
coordinates; `horizontal` / `vertical` target one local line. `length` targets
|
|
171
|
-
one local line and takes its value in the third field. `['angle', line, degrees]`
|
|
172
|
-
sets its orientation relative to +X, named Orientation in the editor.
|
|
173
|
-
`['angle', [line1, line2], degrees]` sets the signed angle from the first line's
|
|
174
|
-
authored start-to-end direction to the second, positive counterclockwise and
|
|
175
|
-
equivalent modulo 360. `['parallel', [line1, line2]]` and
|
|
176
|
-
`['perpendicular', [line1, line2]]` relate two local lines independently of their
|
|
177
|
-
endpoint order; the finite lines need not intersect. Point constraints
|
|
178
|
-
`x` / `y` likewise target one point with a third-field coordinate value, and
|
|
179
|
-
`coincident` takes `[pointRef, pointRef]`. `midpoint` takes `[midpointRef, startRef, endRef]`
|
|
180
|
-
and places the first point halfway between the other two, with no line entity required.
|
|
181
|
-
A point reference may name locked upstream
|
|
182
|
-
geometry. Lines must have nonzero length; length constraints must be positive.
|
|
183
|
-
PlaneGCS solves each layer without modifying upstream values. The snapshot
|
|
184
|
-
reports degrees of freedom and redundant constraint indices. Conflicts are
|
|
185
|
-
located at their source tuples when inline source is available.
|
|
186
|
-
|
|
187
|
-
In the App, select a sketch expression or variable to open its 2D editor. Draw
|
|
188
|
-
continuous lines, drag literal-coordinate points, and delete local entities.
|
|
189
|
-
In Select, an ordinary click or box selection replaces the selection, Ctrl
|
|
190
|
-
toggles elements, and Shift only adds them. Drag left-to-right to select fully
|
|
191
|
-
enclosed geometry or right-to-left to select intersecting geometry. With multiple
|
|
192
|
-
elements selected, constraint tools can remove any editable local relation on
|
|
193
|
-
the selected elements; adding a constraint requires the entire selection to
|
|
194
|
-
satisfy its prerequisites. Parallel accepts two or more local lines and creates
|
|
195
|
-
pairwise relations; Perpendicular and Angle between lines require exactly two.
|
|
196
|
-
Circle takes a center (with optional X/Y input), followed by a radius or a
|
|
197
|
-
circumference click. Entered Radius creates a persistent radius constraint;
|
|
198
|
-
blank Radius follows the pointer and remains free. Drag a circle edge to change
|
|
199
|
-
its radius, or its center to move it. Expression radii remain source-edited;
|
|
200
|
-
gesture locks, numeric writeback and rounded-source replay use the same pipeline
|
|
201
|
-
as point coordinates. Circle creation, deletion and associated constraint changes
|
|
202
|
-
are single undo steps; deleting a circle retains shared and upstream centers,
|
|
203
|
-
and removes only newly disconnected local points.
|
|
204
|
-
Arc takes a center (optional X/Y), a start point (optional Radius), and an end
|
|
205
|
-
point projected to that radius. New drawings default to clockwise (CW); press R to
|
|
206
|
-
reverse the preview. Completing or canceling restores CW for the next drawing;
|
|
207
|
-
existing arcs keep their explicit direction.
|
|
208
|
-
Entered Radius and end-point Sweep become independent persistent
|
|
209
|
-
constraints; blank fields remain free. R preserves the entered sweep magnitude.
|
|
210
|
-
All points, the arc and
|
|
211
|
-
constraints are one source transaction/undo. Drag its edge to edit a literal
|
|
212
|
-
radius, or drag its ordinary center or endpoints;
|
|
213
|
-
or select an interval and Delete to trim it. Radius and sweep labels lie on the
|
|
214
|
-
directed arc; sweep guides connect its center and endpoints. Arc radius expressions
|
|
215
|
-
use the same source protection and gesture-only locks as circle radii.
|
|
216
|
-
Deletion also recognizes ordinary points lying on finite curves, not just explicit
|
|
217
|
-
references, and preserves points still connected to other curves.
|
|
218
|
-
Circles and finite arcs can delimit line trims, including upstream curves; the
|
|
219
|
-
cutting curves and their expressions/constraints stay unchanged. Tangencies
|
|
220
|
-
provide one boundary and arc gaps provide none. Circles and arcs use the same
|
|
221
|
-
interval selection and Trim tool. Circles have cyclic intervals without an
|
|
222
|
-
artificial zero-angle seam; zero or one boundary means whole-circle deletion.
|
|
223
|
-
Trimming a circle leaves a CW arc with the same ID. End trims retain an arc ID;
|
|
224
|
-
interior trims retire it and allocate two fresh IDs, preserving direction.
|
|
225
|
-
Center/radius expressions and radius constraints follow surviving arcs; original
|
|
226
|
-
whole-arc sweep constraints are removed. Coincident intervals are trimmed
|
|
227
|
-
together, sharing cut points and one undo transaction.
|
|
228
|
-
Endpoints are created or reused by Line; there is no standalone Point tool.
|
|
229
|
-
Type X/Y for the start, then length/angle for each segment. Tab switches fields
|
|
230
|
-
and Enter accepts the next endpoint. Each segment is one undo step and reuses
|
|
231
|
-
its endpoint for the next segment. Escape ends the chain without removing
|
|
232
|
-
completed segments; press it again to exit the tool. Blank fields follow the
|
|
233
|
-
pointer. Snap uses points, the origin, a dense adaptive grid and horizontal/vertical
|
|
234
|
-
directions; hold Alt to bypass it.
|
|
235
|
-
After choosing the start point, press X for a horizontal axis lock or Y for
|
|
236
|
-
vertical; press the same key again to unlock. This also works in numeric fields.
|
|
237
|
-
The pointer chooses either direction along the locked axis; Length still applies.
|
|
238
|
-
Entering Angle replaces the axis lock and locking an axis clears Angle.
|
|
239
|
-
Snap/Alt do not override the lock; finishing or canceling a segment clears it.
|
|
240
|
-
Entered coordinates, length and angle, and the final active X/Y lock generate
|
|
241
|
-
explicit constraints in the same source transaction as the new segment. Turning
|
|
242
|
-
the lock off before committing creates no direction constraint; resetting the
|
|
243
|
-
next segment does not remove existing constraints. Ordinary automatic snapping
|
|
244
|
-
does not create constraints. Numeric fields keep native text undo/redo, whose
|
|
245
|
-
grouping belongs to the browser; canvas undo edits source.
|
|
246
|
-
Rectangle uses two opposite corners. Enter Width/Height or let the pointer set
|
|
247
|
-
them; positive dimensions retain their magnitude while the pointer chooses the
|
|
248
|
-
quadrant. It creates ordinary points and lines with horizontal/vertical constraints,
|
|
249
|
-
so later edits preserve right angles. Entered sizes constrain adjacent sides.
|
|
250
|
-
Snapped corners reuse existing point references, including named upstream points.
|
|
251
|
-
The entire rectangle is one source transaction and undo step. Escape cancels its
|
|
252
|
-
draft; a successful rectangle starts a new draft. No rectangle entity is added
|
|
253
|
-
to the author format. Center rectangle chooses a center and corner instead;
|
|
254
|
-
Width/Height are still full side lengths. It retains an ordinary referenceable
|
|
255
|
-
center point, allocated before new corners, and adds one midpoint constraint
|
|
256
|
-
between it and opposite corners. A derived sketch can reference that center
|
|
257
|
-
with `base.point(id)`. Both rectangle modes share inputs, snapping and undo.
|
|
258
|
-
Dragging previews a soft solver target and writes every changed editable point
|
|
259
|
-
in one transaction. Hard constraints remain satisfied. Rules receive the whole
|
|
260
|
-
gesture context, without framework-level point classification or partitioning.
|
|
261
|
-
They recognize centers for preferred local translation, prefer related
|
|
262
|
-
centers or far connected points as soft references, and handle an unconstrained
|
|
263
|
-
sole junction per branch. Radius gestures prefer the curve center.
|
|
264
|
-
Dragging an arc endpoint first prefers keeping its related arc centers in place.
|
|
265
|
-
Dragging a circle or arc center prefers keeping the radii of its curves unchanged
|
|
266
|
-
before following the mouse. A point that is both an arc endpoint and another
|
|
267
|
-
curve's center retains both preferences, with the related arc centers first.
|
|
268
|
-
Within those preferences, the gesture reaches the closest feasible mouse position,
|
|
269
|
-
then prefers local translation and minimizes exterior movement. A constrained
|
|
270
|
-
center or endpoint can therefore stop short of the pointer. Dragging the curve
|
|
271
|
-
itself still adjusts an editable radius. Connected lines do not disable center
|
|
272
|
-
translation: their constraints determine how exterior points follow.
|
|
273
|
-
Finally, a common lowest-priority preference keeps every other point near its
|
|
274
|
-
gesture-start position, resolving only freedom left by those earlier stages.
|
|
275
|
-
It does not pull a translated shape back or turn the other points into fixed
|
|
276
|
-
anchors. Point aliases share one preference, and radius gestures apply this
|
|
277
|
-
final preference to all points without adding new radius constraints.
|
|
278
|
-
Each stage respects all hard constraints; later stages retain earlier achieved
|
|
279
|
-
target parameter values for this frame, not every equivalent optimum. No original
|
|
280
|
-
reference position is made an unconditional anchor, and no stage lock survives
|
|
281
|
-
the frame, adds source constraints or reduces the reported model DOF. An unrestricted center
|
|
282
|
-
rectangle translates when its center moves, without hidden editor metadata.
|
|
283
|
-
Points already on lines, circles or directed arcs at gesture start retain that relation:
|
|
284
|
-
they can slide along the curve, and follow changes to endpoints, centers and radii. The editor
|
|
285
|
-
uses model-space geometric tolerance, not pointer hit areas; lines crossed during
|
|
286
|
-
a gesture do not become sticky. Curves keep their IDs and types, without
|
|
287
|
-
splitting or adding author constraints. Lines and arcs retain their finite bounds;
|
|
288
|
-
CW/CCW arcs never include their missing circular portion. Center moves prefer
|
|
289
|
-
translating their followers, while radius gestures prefer their existing polar
|
|
290
|
-
directions. Read-only upstream curves can guide local
|
|
291
|
-
points. Source replay checks that these gesture-only connections remain satisfied.
|
|
292
|
-
This does not create intersection points or persist curve parameters.
|
|
293
|
-
Movement without authored or inferred equations needs no native kernel;
|
|
294
|
-
point-on-curve dragging uses the Worker solver. During a drag, the editor uses the AST to lock each expression
|
|
295
|
-
coordinate to its evaluated author value: `[width, 0]` locks X but allows Y to move.
|
|
296
|
-
These numeric locks apply to all local points, not just the dragged point, and do
|
|
297
|
-
not become permanent constraints or change normal evaluation. If imposing these
|
|
298
|
-
locks changes the displayed geometry, the solver satisfies them before preparing
|
|
299
|
-
the rule context. Initially unsatisfied author data can therefore adjust on
|
|
300
|
-
the first drag. Editable axes alone are written back; expressions never gain
|
|
301
|
-
offsets. Frames retain a gesture-start reference alongside the preceding solution.
|
|
302
|
-
Previews forward-solve the exact, losslessly serialized data that recompilation uses.
|
|
303
|
-
Deleting a point also deletes connected local lines and affected constraints. Upstream geometry stays
|
|
304
|
-
locked but can supply endpoints for new lines. Coordinates using expressions
|
|
305
|
-
remain editable in code, not by dragging; literal axes on the same point remain
|
|
306
|
-
draggable. The editor preserves existing IDs and
|
|
307
|
-
allocates new IDs from the current local maximum, without `nextId` metadata.
|
|
308
|
-
Deleted IDs may therefore be reused; downstream references are not automatically
|
|
309
|
-
rewritten.
|
|
310
|
-
|
|
311
|
-
### Closed regions and modeling
|
|
312
|
-
|
|
313
|
-
`s.face()` requires exactly one closed region, including its holes. `s.faces()`
|
|
314
|
-
returns all regions as an ordinary readonly array; a sketch without curves returns
|
|
315
|
-
`[]`. Neither query assigns persistent region IDs. Future ID-based selection will
|
|
316
|
-
retain the no-argument meanings; array positions are not stable identifiers.
|
|
317
|
-
|
|
318
|
-
Straight lines, circles and finite CW/CCW arcs form exact B-Rep boundaries.
|
|
319
|
-
Upstream geometry is included. Disconnected contours produce separate faces;
|
|
320
|
-
nested contours alternate material, holes and islands. Standalone points do not
|
|
321
|
-
form boundaries. Open, crossing, touching, overlapping or branched contours report
|
|
322
|
-
an error instead of implicitly trimming, closing, discarding or rewriting entities.
|
|
323
|
-
The editor previews valid regions with a subtle fill and leaves unfinished sketches
|
|
324
|
-
editable; construction diagnostics belong to the `.face()` / `.faces()` call.
|
|
325
|
-
|
|
326
|
-
```ts
|
|
327
|
-
const ring = sketch([
|
|
328
|
-
['point', 1, [0, 0]],
|
|
329
|
-
['circle', 2, [1, 12]],
|
|
330
|
-
['circle', 3, [1, 8]],
|
|
331
|
-
]);
|
|
332
|
-
const sleeve = ring.face().extrude(20);
|
|
333
|
-
const tools = anotherSketch.faces().map(face => face.extrude(10));
|
|
334
|
-
const result = stock.cut(tools); // equivalent to cut(stock, tools)
|
|
335
|
-
```
|
|
336
|
-
|
|
337
|
-
Sketch `[x, y]` maps to model `[x, 0, -y]`, without recentering. Face extrusion
|
|
338
|
-
follows its plane normal (`+Y` before rotation). Distance is signed, finite and
|
|
339
|
-
nonzero; the start cap stays at the original face. `extrude(face, distance)` is
|
|
340
|
-
equivalent to `face.extrude(distance)` and takes one face, never an array. Results
|
|
341
|
-
are normal immutable solid models with caching, rendering, topology and source
|
|
342
|
-
tracing; ordinary `.map()` handles multiple independent outputs.
|
|
343
|
-
|
|
344
|
-
`loft(sections, options)` still takes one face per section. Zero holes and one
|
|
345
|
-
corresponding hole per section work with ordinary or spine-guided lofts. Different
|
|
346
|
-
hole counts and multiple unpaired holes produce explicit errors; holes are never
|
|
347
|
-
silently filled. Arrays in `cut` and `loft` describe one operation's inputs, not
|
|
348
|
-
automatic mapping. General hole correspondence and region ID selectors remain
|
|
349
|
-
future API work.
|
|
350
|
-
|
|
351
|
-
See the [modeling example](../app/examples/sketch-modeling.ts),
|
|
352
|
-
the [sketch example](../app/examples/sketches.ts) and
|
|
353
|
-
[third-party solver sources](THIRD_PARTY.md).
|
|
354
114
|
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
Types used by public signatures, generic constraints, and return values are
|
|
358
|
-
exported alongside the authoring API, including their named type dependencies.
|
|
359
|
-
This includes `ElementKind`, `ModelKind`, `ModelGeometryKind`, `TopologyKind`,
|
|
360
|
-
the named-element and expose result types, and the model capability interfaces.
|
|
361
|
-
|
|
362
|
-
```ts
|
|
363
|
-
import type {
|
|
364
|
-
Anchor,
|
|
365
|
-
ElementKind,
|
|
366
|
-
NamedElements,
|
|
367
|
-
SolidModel,
|
|
368
|
-
} from '@code3d/core';
|
|
369
|
-
|
|
370
|
-
type Mount<Kind extends ElementKind> = Anchor<Kind>;
|
|
371
|
-
type Part<Elements extends NamedElements> = SolidModel<Elements>;
|
|
372
|
-
```
|
|
373
|
-
|
|
374
|
-
Code3d model types come from `@code3d/core`; Replicad builder types such as
|
|
375
|
-
`Shape3D` come from `@code3d/core/replicad`. Type exports do not add runtime
|
|
376
|
-
properties or operations. `Quaternion` belongs to the tooling transform API;
|
|
377
|
-
author rotations use `rotate(x, y, z)` in degrees.
|
|
378
|
-
|
|
379
|
-
## Materials
|
|
380
|
-
|
|
381
|
-
`model.material(value)` returns a new model with a complete replacement material.
|
|
382
|
-
Pass a native [Three.js material](https://threejs.org/docs/pages/Material.html),
|
|
383
|
-
for example `MeshStandardMaterial` or `MeshPhysicalMaterial`, from
|
|
384
|
-
`@code3d/core/three`. This entry directly re-exports the native classes and types
|
|
385
|
-
from Core's Three.js dependency, in both the App and Node. Reusable modeling
|
|
386
|
-
packages use the same entry so their material instances match Core.
|
|
387
|
-
|
|
388
|
-
```ts
|
|
389
|
-
import {box, group} from '@code3d/core';
|
|
390
|
-
import {MeshPhysicalMaterial, MeshStandardMaterial} from '@code3d/core/three';
|
|
391
|
-
|
|
392
|
-
const lacquer = new MeshPhysicalMaterial({
|
|
393
|
-
color: '#eb633e',
|
|
394
|
-
roughness: 0.25,
|
|
395
|
-
clearcoat: 1,
|
|
396
|
-
});
|
|
397
|
-
const part = box(10, 10, 10).material(lacquer);
|
|
398
|
-
const matte = part.material(new MeshStandardMaterial({color: '#8ed5d1'}));
|
|
399
|
-
// matte uses the complete new material; it does not inherit clearcoat.
|
|
400
|
-
const assembly = group([part, matte]).material(lacquer);
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
Assignment captures the material and loaded texture pixels by value. Later
|
|
404
|
-
changes to the Three.js instance do not alter an existing model; call
|
|
405
|
-
`material()` again to capture new values. A group overrides the entire
|
|
406
|
-
material of every descendant, including nested groups. The outermost override
|
|
407
|
-
wins; shared parts retain their materials outside that composition.
|
|
408
|
-
|
|
409
|
-
Named imports and `import * as THREE from "@code3d/core/three"` are both supported.
|
|
410
|
-
A reusable modeling package shares the host project's Core dependency; its own
|
|
411
|
-
independently bundled Three.js copy does not provide the same class identity.
|
|
412
|
-
|
|
413
|
-
The renderer restores and owns Three.js instances from the captured JSON.
|
|
414
|
-
Modeling emphasis uses separate preview copies; Render mode and its PNG export
|
|
415
|
-
use the authored material. Use mesh materials for surfaces/solids,
|
|
416
|
-
`LineBasicMaterial` or `LineDashedMaterial` for curves, and `PointsMaterial` for
|
|
417
|
-
vertices. Choose a corresponding class when overriding a group.
|
|
418
|
-
|
|
419
|
-
Loaded image, canvas, ImageBitmap, data and cube textures are captured with their
|
|
420
|
-
sampling settings. In the modeling worker, use `ImageBitmapLoader` for image
|
|
421
|
-
assets. Assign only after loading completes. Tessellated faces expose their
|
|
422
|
-
native UV coordinates normalized to 0–1 per face; use texture `repeat`, `offset`
|
|
423
|
-
and `rotation` to adjust placement. This is a per-face mapping, not a model-wide
|
|
424
|
-
UV unwrap. See the App's `/examples/materials.ts`.
|
|
425
|
-
|
|
426
|
-
Materials follow Three.js's `toJSON()` / `MaterialLoader` representation.
|
|
427
|
-
Custom material classes, renderer callbacks such as `onBeforeCompile`, live
|
|
428
|
-
video/render-target textures, compressed/layered textures and manual mipmaps
|
|
429
|
-
cannot cross this boundary and are rejected. Material-local clipping, shadow-side and precision overrides are not serialized
|
|
430
|
-
by Three.js and are also rejected. Shader materials must use uniforms
|
|
431
|
-
supported by Three.js's JSON representation.
|
|
432
|
-
|
|
433
|
-
For a simple color, `.material('#f80')` replaces the whole material with the
|
|
434
|
-
default material for that geometry kind. Strings accept CSS names, `#RGB`,
|
|
435
|
-
`#RGBA`, `#RRGGBB`, `#RRGGBBAA`, `rgb(...)` and `rgba(...)`, including percentage
|
|
436
|
-
channels and space-separated values with slash alpha. For example,
|
|
437
|
-
`.material('#f008')` equals `.material('#ff000088')`, and
|
|
438
|
-
`.material('rgb(100% 0% 0% / 50%)')` is half-opaque red. Native Three.js instances
|
|
439
|
-
use their own `opacity` and `transparent` settings.
|
|
440
|
-
|
|
441
|
-
STEP and 3MF preserve the effective base color and opacity; they cannot encode
|
|
442
|
-
Three.js shaders or textures. STL contains geometry only.
|
|
443
|
-
|
|
444
|
-
## Bound relations and rotation
|
|
445
|
-
|
|
446
|
-
`geometry.on(target.up)` translates the source's matching bounding boundary
|
|
447
|
-
onto a directional `Bound`. Targets are `up` (+Y), `down` (−Y), `right` (+X),
|
|
448
|
-
`left` (−X), `front` (+Z), and `back` (−Z), in the target model's local frame.
|
|
449
|
-
Bounds describe the current finite geometry, including solved children of a
|
|
450
|
-
group. They are references owned by the model, not topology surfaces or extra
|
|
451
|
-
box models. Their calculation uses analytic geometry independently of meshing.
|
|
452
|
-
|
|
453
|
-
The source can be a model, vertex, edge, surface, or finite point anchor.
|
|
454
|
-
Only the selected geometry contributes its extent. Its support boundary is
|
|
455
|
-
computed in the target's direction, even when the geometry is tilted. `on`
|
|
456
|
-
never rotates or centers a model. A single contact preserves tangential
|
|
457
|
-
position; multiple contacts solve their translation conditions together and
|
|
458
|
-
report conflicting positions. Mathematical lines and planes without finite
|
|
459
|
-
geometry cannot be sources. Arbitrary models, points, lines, and surfaces
|
|
460
|
-
cannot be targets.
|
|
461
|
-
|
|
462
|
-
```ts
|
|
463
|
-
import {box, group} from '@code3d/core';
|
|
464
|
-
const base = box(10, 10, 10);
|
|
465
|
-
const part = box(20, 20, 20).relate(self => [
|
|
466
|
-
self.on(base.right),
|
|
467
|
-
self.on(base.down),
|
|
468
|
-
]);
|
|
469
|
-
export default group([base, part]); // part at [15, -15, 0]
|
|
115
|
+
export const part = profile.face().extrude(3);
|
|
470
116
|
```
|
|
471
117
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
`relate` always owns the placement. These forms are legal:
|
|
118
|
+
Closed regions bridge sketches to ordinary face and solid modeling. Read the
|
|
119
|
+
[sketch reference](../web/src/content/docs/docs/reference/core.md#editable-sketch-regions)
|
|
120
|
+
and [agent sketch workflow](../../docs/agents/sketches.md) for constraints,
|
|
121
|
+
derived layers, observations, and failure diagnostics. Exact tuple types and
|
|
122
|
+
solver behavior live in [sketch.ts](src/library/sketch.ts) and
|
|
123
|
+
[sketch-solver.ts](src/library/sketch-solver.ts).
|
|
480
124
|
|
|
481
|
-
|
|
482
|
-
part.relate(self => self.on(base.up));
|
|
483
|
-
part.relate(() => part.on(base.up));
|
|
484
|
-
part.relate(self => base.on(self.up)); // moves part below base
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
References to the original receiver are rebound to the new self. Every
|
|
488
|
-
returned relation must involve self or the original receiver. Old model values
|
|
489
|
-
and old references keep their meaning.
|
|
125
|
+
### Relating a sketch to a model plane
|
|
490
126
|
|
|
491
|
-
|
|
127
|
+
`s.relate(self => self.plane.align(target))` returns a new sketch with spatial
|
|
128
|
+
relations, leaving its shared 2D definition and the original sketch unchanged.
|
|
129
|
+
It works before a face exists, including `sketch()` and open contours.
|
|
492
130
|
|
|
493
131
|
```ts
|
|
494
|
-
|
|
495
|
-
self.on(base.up).pivot([50, 0, 0]).rotate(0, 0, 45);
|
|
496
|
-
self.on(base.up).pivotVertex(3).rotate(0, 0, 45);
|
|
497
|
-
self.on(base.up).around(base.axis).rotate(30);
|
|
498
|
-
```
|
|
499
|
-
|
|
500
|
-
`pivot` coordinates, `pivotVertex` IDs, and XYZ axes use relate's **self**,
|
|
501
|
-
regardless of which side of `on` contains self. Direct rotation uses self's
|
|
502
|
-
origin. Angles are degrees, applied X, then Y, then Z. Each pivot or axis
|
|
503
|
-
selection lasts for its next rotation; intermediate chains only complete with
|
|
504
|
-
`rotate`. An axis reference includes position and direction; external axes use
|
|
505
|
-
their resolved composition pose. Rotations compose in call order, following
|
|
506
|
-
that chain's contact placement. Other contacts constrain the final pose.
|
|
507
|
-
Explicit orientations on one self must agree. Remaining translations minimize
|
|
508
|
-
changes at the authored contact stages; duplicate stages do not add bias.
|
|
509
|
-
|
|
510
|
-
Related objects are solved at composition, Boolean, and loft boundaries.
|
|
511
|
-
Standalone views keep the object's own geometry. A group moves its assembled
|
|
512
|
-
children rigidly. `expose()` carries finite references into the group frame.
|
|
513
|
-
Core and App share the same solvers. Pure bound assemblies use exact linear
|
|
514
|
-
translation equations; geometric align relations add joint rigid-pose solving
|
|
515
|
-
without another WASM initialization.
|
|
516
|
-
|
|
517
|
-
In the App, selecting a directional property fills its bound face with the
|
|
518
|
-
same translucent yellow-green as its bounding box, adding corner brackets
|
|
519
|
-
only when that box is absent. The source of `on` shows the complete measured
|
|
520
|
-
bounding box; a topology source limits it to the selected geometry.
|
|
521
|
-
`pivot` has translation handles, `pivotVertex` uses
|
|
522
|
-
self's vertex picker, `around` shows the referenced axis, and `rotate` has
|
|
523
|
-
three angle rings or one axis ring. Source edits retain parameter provenance,
|
|
524
|
-
preview/cancel behavior, and undo. See the
|
|
525
|
-
[bent loft example](../app/examples/bound-rotation.ts).
|
|
526
|
-
|
|
527
|
-
## Geometric alignment
|
|
528
|
-
|
|
529
|
-
`source.align(target)` relates points, curves, and surfaces and can determine
|
|
530
|
-
both position and orientation. Select a solid's `center`, `axis`, `vertex`,
|
|
531
|
-
`edge`, or `surface`; a solid or group itself is not an align reference.
|
|
532
|
-
|
|
533
|
-
| Pair | Meaning |
|
|
534
|
-
| --------------- | ------------------------------------------------------------ |
|
|
535
|
-
| point–point | Coincident points |
|
|
536
|
-
| point–curve | Point lies on the underlying curve |
|
|
537
|
-
| point–surface | Point lies on the underlying surface |
|
|
538
|
-
| curve–curve | Complete underlying curves coincide, with the same direction |
|
|
539
|
-
| curve–surface | The whole underlying curve lies on the surface |
|
|
540
|
-
| surface–surface | Underlying surfaces coincide, with matching normal sense |
|
|
541
|
-
|
|
542
|
-
The first implementation supports points, straight lines, circles, ellipses,
|
|
543
|
-
planes, cylinders, and spheres. Edge trims, arc ranges, face boundaries, and
|
|
544
|
-
holes do not limit the supporting geometry. Equal-radius arcs may coincide
|
|
545
|
-
without matching endpoints; straight lines retain axial sliding and twisting.
|
|
546
|
-
Use a curve's `start`, `midpoint`, `end`, or a selected vertex for more specific
|
|
547
|
-
positioning. Unsupported geometry reports an error. Different radii and other
|
|
548
|
-
proven impossibilities report geometric incompatibility; numerical
|
|
549
|
-
nonconvergence does not prove that no solution exists.
|
|
132
|
+
import {box, sketch} from '@code3d/core';
|
|
550
133
|
|
|
551
|
-
|
|
552
|
-
const
|
|
553
|
-
|
|
554
|
-
|
|
134
|
+
const host = box(40, 20, 30).rotate(0, 0, 25);
|
|
135
|
+
const profile = sketch([
|
|
136
|
+
['point', 1, [0, 0]],
|
|
137
|
+
['circle', 2, [1, 4]],
|
|
555
138
|
]);
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
);
|
|
559
|
-
```
|
|
560
|
-
|
|
561
|
-
`reverse()` changes a line reference's positive direction. `flip()` changes a
|
|
562
|
-
surface's normal sense. Both preserve geometry and reference axes. Point
|
|
563
|
-
membership ignores direction, and curve-to-surface membership adds no arbitrary
|
|
564
|
-
heading within the surface. `around(axis.reverse())` reverses the signed
|
|
565
|
-
rotation direction; curved edges still do not define a single rotation axis.
|
|
566
|
-
|
|
567
|
-
`align(...).offset(x, y, z)` translates **self** in the target reference axes
|
|
568
|
-
after alignment, then applies the authored `rotate`/`pivot`/`around` chain.
|
|
569
|
-
Repeated offsets add; zero adds no positioning condition. Unlike `on.offset`,
|
|
570
|
-
it does not pin trim centers or parameter origins. This holds when self is the
|
|
571
|
-
written target too. Multiple relations are solved jointly. An already satisfied
|
|
572
|
-
relation preserves its pose; remaining freedom is selected deterministically
|
|
573
|
-
by geometric seeds and local numerical solving, without a uniqueness guarantee.
|
|
574
|
-
|
|
575
|
-
In relation context, axes have one positive arrow and edges retain their actual
|
|
576
|
-
curved highlight as the shaft, with only a tangent arrowhead at the directed
|
|
577
|
-
endpoint (a stable seam for a closed edge). Source and target arrowheads share
|
|
578
|
-
a fixed 10-by-6 CSS-pixel size. Passive axes have arrows at both ends. Passive line
|
|
579
|
-
decorations use 1px; interactive topology selection uses 2px. Surface normals
|
|
580
|
-
retain their facing arrows.
|
|
581
|
-
See [the alignment example](../app/examples/geometric-alignment.ts).
|
|
582
|
-
|
|
583
|
-
Source inspection previews each relation call through that stage, before later
|
|
584
|
-
offsets or rotations. The current pair shares one marker color: the inspected
|
|
585
|
-
side keeps its base opacity and the other uses 70% of that opacity. Remaining
|
|
586
|
-
related objects are dim gray. `on`/`align` and subsequent chain calls focus
|
|
587
|
-
self; their target arguments focus the actual target reference, which is self
|
|
588
|
-
in a reverse-written relation. Model opacity uses role-specific caps rather than
|
|
589
|
-
multiplying existing material opacity. See the
|
|
590
|
-
[relation guide](../web/src/content/docs/docs/guides/relations.mdx) and
|
|
591
|
-
[visualization conventions](../../.agents/skills/code3d-visualization/SKILL.md).
|
|
592
|
-
|
|
593
|
-
When several relations include align on one model, use the numeric parameter
|
|
594
|
-
panel or source to edit offsets and rotations. Each edit resolves the coupled
|
|
595
|
-
equations. Spatial drags are available for a single align relation; combined
|
|
596
|
-
geometric relations do not show a misleading rigid-transform preview.
|
|
597
|
-
|
|
598
|
-
## Exposed geometry and topology
|
|
599
|
-
|
|
600
|
-
`expose()` preserves geometry as a reference in the returned model's frame.
|
|
601
|
-
A solid, face, edge, or vertex model becomes a `Solid`, `Surface`, `Edge`, or
|
|
602
|
-
`Vertex` reference. Existing topology references retain their identity; pure
|
|
603
|
-
point, line, plane, and frame anchors retain their reference-geometry meaning.
|
|
604
|
-
Named members remain available, including on an exposed group frame.
|
|
605
|
-
Selected topology contributes its own finite extent to bound positioning; a
|
|
606
|
-
custom model origin does not change that extent.
|
|
607
|
-
|
|
608
|
-
```ts
|
|
609
|
-
const plate = box(32, 4, 24);
|
|
610
|
-
const assembly = group([plate]).expose({body: plate, mount: plate.surface(1)});
|
|
611
|
-
const boundary = assembly.mount.edges();
|
|
612
|
-
const corners = boundary[0].vertices();
|
|
613
|
-
const center = assembly.mount.center;
|
|
614
|
-
```
|
|
615
|
-
|
|
616
|
-
References support geometric queries and `on()`. They do not have model
|
|
617
|
-
operations such as `rotate`, `scaled`, `fillet`, or `relate`. A relation authored
|
|
618
|
-
through `self.mount.center` acts on `self`, including when `self` is an assembly.
|
|
619
|
-
Every chained result carries that assembly context while its geometry and IDs
|
|
620
|
-
continue to refer to the original immutable source. Exposing an upstream value
|
|
621
|
-
captures that source; later modeling operations do not reinterpret its IDs in
|
|
622
|
-
a different geometry. To expose result topology, select it from that result.
|
|
623
|
-
|
|
624
|
-
Subtopology access follows dimension: a surface can query its edges and
|
|
625
|
-
vertices, and an edge its vertices. Singular queries validate membership;
|
|
626
|
-
plural queries retain authored order and allow `[]`. IDs always use the source
|
|
627
|
-
geometry's namespace, so a shared edge has the same ID through either face.
|
|
628
|
-
An edge's vertices are its actual topological vertices; a closed edge can have
|
|
629
|
-
one vertex. A source used in multiple occurrences must be exposed through the
|
|
630
|
-
intended child's reference, such as `left.body`, to select its placement.
|
|
631
|
-
|
|
632
|
-
Every geometric reference has a local bounding-box `center` point, carried
|
|
633
|
-
through rotation and scaling. `Edge.start`, `.midpoint`, and `.end` sample curve
|
|
634
|
-
parameters 0, 0.5, and 1; the midpoint need not be the bounding-box center or the
|
|
635
|
-
half-length point. These calculated points are anchors, not topology vertices.
|
|
636
|
-
`edge.on()` and `surface.on()` use finite geometry extents rather than their
|
|
637
|
-
sampled tangent or normal; `.center.on()` uses only the calculated point.
|
|
638
|
-
|
|
639
|
-
## Origins and rotation
|
|
640
|
-
|
|
641
|
-
All models, including groups, support immutable origin editing and rotation:
|
|
642
|
-
|
|
643
|
-
```ts
|
|
644
|
-
const part = box(24, 6, 14)
|
|
645
|
-
.originVertex(3)
|
|
646
|
-
.originOffset(0, 2, 0)
|
|
647
|
-
.rotate(15, 35, 0);
|
|
648
|
-
```
|
|
649
|
-
|
|
650
|
-
- `originPoint(pointRef)` makes a center, named point, or topology vertex local zero.
|
|
651
|
-
- `originVertex(id)` selects a geometric model’s own input vertex; it is equivalent
|
|
652
|
-
to `model.originPoint(model.vertex(id))`.
|
|
653
|
-
- `originCenter()` makes the model's `center` anchor local zero.
|
|
654
|
-
- `originOffset(dx, dy, dz)` re-expresses every local point as `p - [dx, dy, dz]`.
|
|
655
|
-
- `rotate(x, y, z)` rotates about local zero in degrees, applying fixed local
|
|
656
|
-
X, then Y, then Z rotations. Repeated calls compose in source order.
|
|
657
|
-
|
|
658
|
-
The model origin is always zero in its own coordinates. Origin offsets compose
|
|
659
|
-
and cancel; geometry, centers, named references and topology positions all use
|
|
660
|
-
the resulting coordinates. Directions and topology IDs are preserved. Old model
|
|
661
|
-
values and captured references keep their original meaning. `center` begins at
|
|
662
|
-
the body's local bounding-box center and follows transforms; rotating does not
|
|
663
|
-
recalculate it from the new axis-aligned bounds. `scaled()` scales about current
|
|
664
|
-
local zero. Later origin edits preserve the already-rotated shape.
|
|
665
|
-
|
|
666
|
-
Dimensions use scalar arguments; positions use arrays. `point()` is local zero;
|
|
667
|
-
`point([x, y, z])` equals `point().originOffset(-x, -y, -z)`. `line([x, y, z])`
|
|
668
|
-
starts at zero; `line(start, end)` accepts two position arrays. Their input
|
|
669
|
-
coordinates remain local geometry coordinates. For example, `line([10, 0, 0])`
|
|
670
|
-
has center `[5, 0, 0]`, and `.rotate(0, 90, 0)` takes its end to `[0, 0, -10]`.
|
|
671
|
-
A curve's tangent reference frame does not redefine model XYZ. Directional
|
|
672
|
-
bounds use the model axes, including after geometric rotation.
|
|
673
|
-
|
|
674
|
-
Groups provide `originPoint()`, `originOffset()` and `rotate()`. Their default origin is
|
|
675
|
-
chosen when constructed: solve the direct members' placement, then take the
|
|
676
|
-
axis-aligned bounding-box center of their **origins**, retaining the assembly
|
|
677
|
-
axes. Geometry size does not affect this choice. A nested group contributes
|
|
678
|
-
only its own origin; an empty group defaults to zero. Explicit origin edits
|
|
679
|
-
re-express the assembled result together, preserving internal constraints and
|
|
680
|
-
member spacing. The default is not recalculated on later operations.
|
|
681
|
-
`rotate(x, y, z)` turns the solved assembly together about its current origin,
|
|
682
|
-
including nested instances, without re-solving internal relations. Named
|
|
683
|
-
references and topology follow the members; directional bounds use group axes.
|
|
684
|
-
|
|
685
|
-
```ts
|
|
686
|
-
const base = box(20, 4, 10).originOffset(0, 2, 0);
|
|
687
|
-
const lid = box(20, 2, 10).originOffset(0, -1, 0);
|
|
688
|
-
const assembly = group([base, lid]); // Common origins at their contact plane.
|
|
689
|
-
const mounted = assembly.originPoint(lid.center);
|
|
690
|
-
const tilted = mounted.rotate(0, 0, 30); // Rotate the whole assembly about the lid center.
|
|
139
|
+
const opening = profile.relate(s => s.plane.align(host.surface(4)));
|
|
140
|
+
const result = host.cut([opening.face().extrude(-20)]);
|
|
141
|
+
const draft = sketch().relate(s => s.plane.align(host.surface(2)));
|
|
691
142
|
```
|
|
692
143
|
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
144
|
+
The target may be a named plane or a planar `host.surface(id)`. The sketch plane
|
|
145
|
+
normal is local `+Y`; alignment uses the same directed-plane, target-frame offset
|
|
146
|
+
and rotation semantics as model relations. It does not implicitly center the
|
|
147
|
+
sketch on a trimmed surface. An unbounded sketch plane cannot use `on()` to place
|
|
148
|
+
finite geometry against a bound; use `align()`. Topology-only pivots such as
|
|
149
|
+
`pivotVertex()` require a geometric model, not an empty sketch frame.
|
|
150
|
+
|
|
151
|
+
`derive()`, `face()` / `faces()` and extrusion inherit the relations. Boolean
|
|
152
|
+
operations and loft resolve their inputs in the shared composition context;
|
|
153
|
+
placement is not baked into tuple coordinates. A spatial copy shares point
|
|
154
|
+
identities with its original, so a derived layer can still use `profile.point(id)`.
|
|
155
|
+
References target the actual immutable model value: creating a later rotated or
|
|
156
|
+
repositioned model does not redirect existing sketch relations.
|
|
157
|
+
|
|
158
|
+
In the App, select the related value (`opening`) to edit against read-only model
|
|
159
|
+
outlines projected into the sketch's local plane. Select `profile` for its original
|
|
160
|
+
local view. Both edit the same source array, with ordinary undo; separate placements
|
|
161
|
+
of that geometry are not separate authoring definitions. Context outlines are
|
|
162
|
+
visual references only, not snapping targets or imported geometry constraints.
|
|
163
|
+
The select-surface-and-create UI is tracked separately within
|
|
164
|
+
[#114](https://github.com/vilicvane/code3d/issues/114).
|
|
165
|
+
Try [sketch-on-surface.ts](../app/examples/sketch-on-surface.ts).
|
|
166
|
+
|
|
167
|
+
## Cached computations and custom primitives
|
|
168
|
+
|
|
169
|
+
`cached(fn, options?)` memoizes synchronous, deterministic data computations.
|
|
170
|
+
Pass changing captured state as arguments and treat returned data as immutable.
|
|
171
|
+
Memory hits reuse the retained result; optional `encoder` / `decoder` pairs only
|
|
172
|
+
run when saving to disk or restoring it. The App fingerprints static definitions
|
|
173
|
+
and their dependencies for persistent reuse; dynamic closures and ordinary Node
|
|
174
|
+
calls use function identity for memory reuse. No author cache IDs are needed.
|
|
175
|
+
|
|
176
|
+
`definePrimitive(builder)` from `@code3d/core/replicad` also caches construction,
|
|
177
|
+
normalization and geometry analysis. Each call still creates fresh model metadata
|
|
178
|
+
and independently owned geometry handles. The builder transfers its returned
|
|
179
|
+
solid to Core and owns its intermediate resources. Screws uses this shared cache.
|
|
180
|
+
Read [cached computations](../web/src/content/docs/docs/reference/core.md#cached-computations)
|
|
181
|
+
and [custom primitives](../web/src/content/docs/docs/guides/custom-primitives.mdx)
|
|
182
|
+
for supported data, resource ownership and examples.
|
|
183
|
+
|
|
184
|
+
## Text and fonts
|
|
719
185
|
|
|
720
186
|
```ts
|
|
721
|
-
import {
|
|
187
|
+
import {googleFont, text, extrude, group} from '@code3d/core';
|
|
722
188
|
|
|
723
|
-
|
|
189
|
+
const face = googleFont('Play');
|
|
190
|
+
export default group(extrude(text('Hello', face, 10), 1));
|
|
724
191
|
```
|
|
725
192
|
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
193
|
+
In the App, `googleFont()` uses a static family name and optional weight/italic
|
|
194
|
+
settings; `font()` accepts a static font-file URL or TTF/OTF bytes. The engine
|
|
195
|
+
prepares remote resources before synchronous model execution. Text returns
|
|
196
|
+
ordinary planar faces with a common baseline; `extrude(faces, distance)` preserves
|
|
197
|
+
their order and placement. Node can read local file URLs or use downloaded,
|
|
198
|
+
decoded font bytes. See the [text reference](../web/src/content/docs/docs/reference/core.md#text),
|
|
199
|
+
[runnable example](../app/examples/text.ts) and [font notices](THIRD_PARTY.md).
|
|
200
|
+
|
|
201
|
+
## Materials and entry points
|
|
202
|
+
|
|
203
|
+
`.material()` accepts a color or a native Three.js material. Use
|
|
204
|
+
`@code3d/core/three` when constructing native materials, and
|
|
205
|
+
[@code3d/materials](../materials/README.md) for common presets. A model captures
|
|
206
|
+
its material value; changing the original Three.js object later does not change
|
|
207
|
+
that model. The renderer supplies lighting and environment reflections.
|
|
208
|
+
|
|
209
|
+
| Import | Responsibility |
|
|
210
|
+
| ----------------------- | ------------------------------------------------------------------------ |
|
|
211
|
+
| `@code3d/core` | Public model authoring API; Node entry initializes the kernel |
|
|
212
|
+
| `@code3d/core/three` | Shared Three.js exports for material and geometry integration |
|
|
213
|
+
| `@code3d/core/replicad` | Replicad access for custom primitive builders |
|
|
214
|
+
| `@code3d/core/tooling` | Evaluation, inspection and resource lifetime integration used by the App |
|
|
215
|
+
|
|
216
|
+
Tooling integrations own evaluation lifetimes and disposal. Follow the existing
|
|
217
|
+
[tooling entry](src/tooling/index.ts), [evaluation tests](test/model-test.ts), and
|
|
218
|
+
[App compiler](../app/src/model/compiler.ts) when embedding the runtime. Ordinary
|
|
219
|
+
model files should stay on the authoring API.
|
|
220
|
+
|
|
221
|
+
## Source and development
|
|
222
|
+
|
|
223
|
+
For changes to Core itself, start with the [modeling architecture](../../.agents/docs/architecture/modeling.md)
|
|
224
|
+
and shared [development guide](../../.agents/docs/development.md), then follow
|
|
225
|
+
the implementation and tests below.
|
|
226
|
+
|
|
227
|
+
- [Public exports](src/library/index.ts), [model runtime](src/library/runtime.ts),
|
|
228
|
+
and [public type tests](test/public-types.ts).
|
|
229
|
+
- [Spatial values](src/library/spatial.ts), [relation solving](src/library/relation-solver.ts),
|
|
230
|
+
and [topology](src/library/topology.ts).
|
|
231
|
+
- [Cached computations](src/library/cached.ts), [fonts](src/library/font.ts),
|
|
232
|
+
[text geometry](src/library/text.ts) and their [tests](test/).
|
|
233
|
+
- [Material values](src/library/material.ts), [kernel cache](src/library/kernel-cache.ts),
|
|
234
|
+
and [Node entry](src/node/index.ts).
|
|
235
|
+
- [Executable App examples](../app/examples/) and [runtime tests](test/).
|
|
236
|
+
|
|
237
|
+
Public JavaScript entries are prebundled ESM with shared chunks. Node, browser,
|
|
238
|
+
tooling and interop entries share the same kernel and cache instances. TypeScript
|
|
239
|
+
declarations, declaration maps and their sources remain available for editor
|
|
240
|
+
navigation. The build and npm `prepack` use the same package build script; see the
|
|
241
|
+
[development guide](../../.agents/docs/development.md#公开包产物) for installed
|
|
242
|
+
tarball verification and CI publishing.
|
|
243
|
+
|
|
244
|
+
For a standalone TypeScript project, include `ESNext` and `DOM` in `compilerOptions.lib`.
|
|
245
|
+
Use `module: "ESNext"` and `moduleResolution: "Bundler"` when esbuild or another
|
|
246
|
+
bundler handles execution. Code3D's App uses this resolution mode, supports
|
|
247
|
+
extensionless relative imports and selects browser package exports.
|
|
248
|
+
The public packages are built and verified with `skipLibCheck: false`. NodeNext
|
|
249
|
+
currently needs `skipLibCheck` because the `manifold-3d@3.0.1` declarations omit
|
|
250
|
+
relative `.js` extensions. Core includes the declaration dependencies needed by
|
|
251
|
+
its HarfBuzz and Replicad integrations.
|
|
252
|
+
|
|
253
|
+
From the repository root:
|
|
254
|
+
|
|
255
|
+
```sh
|
|
256
|
+
npm run build:packages
|
|
257
|
+
npm test --workspace @code3d/core
|
|
744
258
|
```
|
|
745
259
|
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
## Custom primitives
|
|
750
|
-
|
|
751
|
-
`definePrimitive` turns a synchronous Replicad builder into a normal code3d
|
|
752
|
-
solid model. Replicad stays behind an explicit author-interoperability entry so
|
|
753
|
-
raw shapes do not become part of the root model API. Import `definePrimitive`
|
|
754
|
-
and `replicad` from `@code3d/core/replicad`.
|
|
755
|
-
|
|
756
|
-
The runnable [custom primitive example](../app/examples/custom-primitives.ts)
|
|
757
|
-
builds a twisted knob with a D-shaped shaft bore, then composes two instances.
|
|
758
|
-
It demonstrates direct parameter annotations, a default argument, Replicad
|
|
759
|
-
extrusion and booleans, and intermediate resource cleanup. The screws package's
|
|
760
|
-
private [thread builder](../screws/src/library/thread.ts) is another consumer.
|
|
761
|
-
Built-in tubes and coils should be imported directly from core, not reimplemented
|
|
762
|
-
in author examples.
|
|
763
|
-
|
|
764
|
-
The builder's argument types, names, and optional parameters are preserved.
|
|
765
|
-
Write validation inside the builder. It executes on every call, including when
|
|
766
|
-
the same arguments are reused, so changes to captured state remain observable.
|
|
767
|
-
Core caches the actual returned B-Rep, so identical output can reuse downstream
|
|
768
|
-
operations and meshes across evaluations without skipping the builder. Each
|
|
769
|
-
model owns its disposable geometry and uses the standard mesh tolerance.
|
|
770
|
-
|
|
771
|
-
Returning a shape transfers its ownership to code3d; do not mutate, delete, or
|
|
772
|
-
return it again. Intermediate resources remain the builder's responsibility,
|
|
773
|
-
following Replicad's ownership rules. A single-solid aggregate produced by
|
|
774
|
-
Replicad booleans is normalized; shells, multiple-solid aggregates, and stray
|
|
775
|
-
lower-dimensional geometry are rejected, and rejected returned shapes are
|
|
776
|
-
released. Kernel installation and replacement remain owned by code3d.
|
|
777
|
-
|
|
778
|
-
Place `@code3d.param` annotations directly on the exported function variable to
|
|
779
|
-
enable its call-site tool panel, including when consumed through emitted
|
|
780
|
-
declarations. No wrapper or definition options are needed. For a standalone
|
|
781
|
-
preview, export an ordinary example invocation; `@code3d.arguments`
|
|
782
|
-
is not expanded to recognize primitive factory definitions.
|
|
783
|
-
|
|
784
|
-
## Tooling evaluation lifetime
|
|
785
|
-
|
|
786
|
-
The App uses the selected runtime's `@code3d/core/tooling` entry, from the project
|
|
787
|
-
when core is declared or from the built-in package otherwise. This internal
|
|
788
|
-
integration surface evolves with the App during prototyping and does not promise
|
|
789
|
-
API stability. It includes topology source identities, assembly transforms, and
|
|
790
|
-
calculated-anchor frames alongside origin, spatial-operation, and sketch layer
|
|
791
|
-
snapshots. It requires installing OpenCascade and the sketch constraint solver
|
|
792
|
-
from that same package dependency graph.
|
|
793
|
-
Call `beginModelEvaluation(): () => void` before each serial source
|
|
794
|
-
evaluation to reset source locations, parameter provenance, and operation
|
|
795
|
-
traces. Call the returned function in `finally`, after creating snapshots.
|
|
796
|
-
Geometry, model identity, and relations remain unchanged; already-created
|
|
797
|
-
snapshots keep their previous evaluation's metadata.
|
|
798
|
-
|
|
799
|
-
The kernel cache retains the complete working set of the latest evaluation,
|
|
800
|
-
including exact transformed-bound queries and render meshes. During evaluation,
|
|
801
|
-
both the previous and current working sets are protected from eviction. Finishing
|
|
802
|
-
keeps the current set and at most 256 unused historical entries, releasing older
|
|
803
|
-
native values. This scales retention with the current model without accumulating
|
|
804
|
-
every edited revision. Calls outside an evaluation use the bounded history.
|
|
805
|
-
|
|
806
|
-
Packages may retain model values privately. The App therefore drops its own
|
|
807
|
-
references after creating snapshots instead of forcibly disposing every model
|
|
808
|
-
it encounters. Unreachable Replicad wrappers release their native resources
|
|
809
|
-
through their finalizers; explicit disposal is appropriate only when the caller
|
|
810
|
-
owns the complete model lifetime. This boundary is tooling-only: ordinary
|
|
811
|
-
model authors do not initialize an evaluation session.
|
|
812
|
-
|
|
813
|
-
Rendering snapshots contain serializable meshes and model metadata, without
|
|
814
|
-
native shapes. File export uses a separate `ModelGeometrySnapshot` retained
|
|
815
|
-
by the compiler Worker. Core clones each distinct source shape once; the
|
|
816
|
-
compiler releases these copies before the next compilation, when replacing
|
|
817
|
-
the runtime, or when it is disposed. The snapshot's shapes are borrowed by
|
|
818
|
-
consumers: each export clones them before transformations or consuming kernel
|
|
819
|
-
operations and releases its temporary geometry on both success and failure.
|
|
820
|
-
Repeated exports therefore preserve the retained geometry and author models.
|
|
821
|
-
|
|
822
|
-
Core owns snapshot creation; the App owns export placement and file generation,
|
|
823
|
-
using Replicad from the same runtime. This division already serves the current
|
|
824
|
-
consumers and changes only when a concrete use case calls for it.
|
|
260
|
+
Use the [agent entry](../../docs/agents.md) to work on a project through the CLI,
|
|
261
|
+
or the [App README](../app/README.md) to develop the editor and visualization.
|