@code3d/core 0.0.1-alpha.0 → 0.0.1-alpha.11
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 +43 -807
- package/THIRD_PARTY.md +40 -0
- package/bld/THIRD_PARTY_NOTICES.txt +182 -0
- package/bld/chunks/chunk-7FIFPADJ.js +1 -0
- package/bld/chunks/chunk-7FIFPADJ.js.map +7 -0
- package/bld/chunks/chunk-CL3E2DE4.js +19 -0
- package/bld/chunks/chunk-CL3E2DE4.js.map +7 -0
- package/bld/chunks/chunk-HZRQUHM2.js +30 -0
- package/bld/chunks/chunk-HZRQUHM2.js.map +7 -0
- package/bld/chunks/chunk-JBVIAMJ6.js +26474 -0
- package/bld/chunks/chunk-JBVIAMJ6.js.map +7 -0
- package/bld/chunks/chunk-QK6ZET47.js +31 -0
- package/bld/chunks/chunk-QK6ZET47.js.map +7 -0
- package/bld/library/bound-solver.d.ts +29 -5
- package/bld/library/bound-solver.d.ts.map +1 -1
- package/bld/library/cached.d.ts +35 -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 +10 -2
- package/bld/library/index.d.ts.map +1 -1
- package/bld/library/index.js +94 -3
- package/bld/library/index.js.map +7 -1
- package/bld/library/inspect.d.ts +100 -0
- package/bld/library/inspect.d.ts.map +1 -0
- package/bld/library/kernel-artifact-codec.d.ts.map +1 -1
- package/bld/library/kernel-cache.d.ts +28 -7
- package/bld/library/kernel-cache.d.ts.map +1 -1
- package/bld/library/loft.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/relation-solver.d.ts +19 -8
- package/bld/library/relation-solver.d.ts.map +1 -1
- 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 +518 -155
- 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 +21 -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/library/topology.d.ts +6 -2
- package/bld/library/topology.d.ts.map +1 -1
- package/bld/node/index.d.ts.map +1 -1
- package/bld/node/index.js +96 -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 +18 -15
- package/bld/tooling/index.d.ts.map +1 -1
- package/bld/tooling/index.js +165 -19
- package/bld/tooling/index.js.map +7 -1
- package/docs/api.md +764 -0
- package/docs/custom-primitives.mdx +58 -0
- package/docs/local-coordinates.md +187 -0
- package/docs/origins-and-rotation.mdx +105 -0
- package/docs/relations.mdx +450 -0
- package/docs/runtime.md +297 -0
- package/docs/shells.mdx +70 -0
- package/docs/sketches.md +83 -0
- package/docs/text.md +23 -0
- package/docs/topology.md +152 -0
- package/docs/values.md +119 -0
- package/package.json +20 -7
- package/src/library/bound-solver.ts +103 -73
- package/src/library/cached.ts +153 -0
- package/src/library/font.ts +186 -0
- package/src/library/google-font.ts +97 -0
- package/src/library/index.ts +53 -5
- package/src/library/inspect.ts +178 -0
- package/src/library/kernel-artifact-codec.ts +129 -20
- package/src/library/kernel-cache.ts +175 -39
- package/src/library/loft.ts +9 -1
- package/src/library/material.ts +3 -4
- package/src/library/open-cascade.ts +13 -0
- package/src/library/relation-solver.ts +230 -113
- package/src/library/replicad.ts +5 -5
- package/src/library/retained-memory.ts +6 -1
- package/src/library/runtime.ts +3769 -1178
- package/src/library/shell.ts +3 -3
- package/src/library/sketch-solver.ts +3 -1
- package/src/library/sketch.ts +112 -13
- package/src/library/text.ts +477 -0
- package/src/library/topology.ts +61 -17
- 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 +64 -51
- 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/docs/runtime.md
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Runtime and integration
|
|
3
|
+
description: Cache computations, integrate native materials and embed the modeling runtime.
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 11
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Cached computations and custom primitives
|
|
9
|
+
|
|
10
|
+
`cache(fn)` memoizes synchronous, deterministic data computations;
|
|
11
|
+
`cache(fn, args)` immediately returns the cached result for an argument tuple.
|
|
12
|
+
Both forms share the same function identity and argument keys. Supply custom
|
|
13
|
+
codecs in the third argument: `cache(fn, undefined, options)` for a function or
|
|
14
|
+
`cache(fn, args, options)` for a value.
|
|
15
|
+
Pass changing captured state as arguments and treat returned data as immutable.
|
|
16
|
+
Memory hits reuse the retained result; optional `encoder` / `decoder` pairs only
|
|
17
|
+
run when saving to disk or restoring it. Newly computed entries are eligible
|
|
18
|
+
for disk storage when computation reaches the configured threshold (1 ms by
|
|
19
|
+
default). Faster results remain in memory and are not encoded or written on later
|
|
20
|
+
memory hits. Change the threshold in **Settings → Cache** in the App; it applies
|
|
21
|
+
to new computations and preserves existing cache entries. Existing
|
|
22
|
+
disk records can still be restored. The App fingerprints static definitions
|
|
23
|
+
and their dependencies for persistent reuse; dynamic closures and ordinary Node
|
|
24
|
+
calls use function identity for memory reuse. No author cache IDs are needed.
|
|
25
|
+
|
|
26
|
+
`definePrimitive(builder)` from `@code3d/core/replicad` also caches construction,
|
|
27
|
+
normalization and geometry analysis. Each call still creates fresh model metadata
|
|
28
|
+
and independently owned geometry handles. The builder transfers its returned
|
|
29
|
+
solid to Core and owns its intermediate resources. Screws uses this shared cache.
|
|
30
|
+
Read [cached computations](api.md#cached-computations)
|
|
31
|
+
and [custom primitives](custom-primitives.mdx)
|
|
32
|
+
for supported data, resource ownership and examples.
|
|
33
|
+
|
|
34
|
+
## Materials and entry points
|
|
35
|
+
|
|
36
|
+
`.material()` accepts a color or a native Three.js material. Use
|
|
37
|
+
`@code3d/core/three` when constructing native materials, and
|
|
38
|
+
[@code3d/materials](../../materials/README.md) for common presets. A model captures
|
|
39
|
+
its material value; changing the original Three.js object later does not change
|
|
40
|
+
that model. The renderer supplies lighting and environment reflections.
|
|
41
|
+
|
|
42
|
+
| Import | Responsibility |
|
|
43
|
+
| ----------------------- | ------------------------------------------------------------------------ |
|
|
44
|
+
| `@code3d/core` | Public model authoring API; Node entry initializes the kernel |
|
|
45
|
+
| `@code3d/core/three` | Shared Three.js exports for material and geometry integration |
|
|
46
|
+
| `@code3d/core/replicad` | Replicad access for custom primitive builders |
|
|
47
|
+
| `@code3d/core/tooling` | Evaluation, inspection and resource lifetime integration used by the App |
|
|
48
|
+
|
|
49
|
+
Tooling integrations own evaluation lifetimes and disposal. Follow the existing
|
|
50
|
+
[tooling entry](../src/tooling/index.ts), [evaluation tests](../test/model-test.ts), and
|
|
51
|
+
[App compiler](../../app/src/model/compiler.ts) when embedding the runtime. Ordinary
|
|
52
|
+
model files should stay on the authoring API.
|
|
53
|
+
|
|
54
|
+
## Source inspection
|
|
55
|
+
|
|
56
|
+
Ordinary expression values preview directly, including models, anchors and collections.
|
|
57
|
+
Model values retain their authored material opacity: an opaque color stays opaque,
|
|
58
|
+
explicit alpha stays unchanged, and unstyled surfaces keep the default translucency.
|
|
59
|
+
This also applies to ordinary call results and parameter fallbacks. Inspection
|
|
60
|
+
scenes apply the target/focused/ambient opacity limits; an anchor's owner remains
|
|
61
|
+
context behind the reference in both kinds of preview.
|
|
62
|
+
Use `@code3d.inspect parameter callback` when a parameter needs additional context;
|
|
63
|
+
use `@code3d.inspect callback` for an exceptional call-result view. A parameter
|
|
64
|
+
first tries its parameter inspector, then the call inspector, then the ordinary
|
|
65
|
+
call result. A declared closure body has its own scope: declining it continues
|
|
66
|
+
outward without re-entering that same call's parameter or call inspector. The callback
|
|
67
|
+
receives the original argument tuple and `InspectContext`; method receivers are
|
|
68
|
+
in `context.receiver`. Its `target` and `ambient` arrays own the complete scene.
|
|
69
|
+
Returning `undefined` declines the scope; returning `{}` intentionally displays
|
|
70
|
+
an empty scene. Target values matching `context.focused.values` receive focus;
|
|
71
|
+
generated geometry does not inherit focus from its inputs.
|
|
72
|
+
|
|
73
|
+
Selecting an array member focuses that value while keeping the other inspection
|
|
74
|
+
targets visible at a weaker level; selecting the whole array focuses its members.
|
|
75
|
+
For cut tools and intersect operands, selected inputs are targets and other inputs
|
|
76
|
+
are ambient. The generated cut volume (orange) or intersection (cyan) is a separate
|
|
77
|
+
target, including when inspecting a single input. A failed intersection still
|
|
78
|
+
shows the selected inputs and ambient operands without inventing a result.
|
|
79
|
+
These region inspectors use ordinary unlit materials with depth testing disabled,
|
|
80
|
+
so their colors remain visible through the translucent inputs.
|
|
81
|
+
|
|
82
|
+
Core uses this mechanism for distance measurements, relate calls and their
|
|
83
|
+
closures, on/align references, relative transformation stages, group children,
|
|
84
|
+
expose sources, Boolean operands and loft sections/spines, plus box and extrusion
|
|
85
|
+
dimensions. Selecting a normal constructor or Boolean function name
|
|
86
|
+
still previews its return value. Inspectors retain the original operation frame,
|
|
87
|
+
so a later relation or a different consumer cannot move its inspection.
|
|
88
|
+
|
|
89
|
+
A closure can independently declare a context factory with
|
|
90
|
+
`@code3d.inspect.context parameter callback` and a renderer with
|
|
91
|
+
`@code3d.inspect.closure parameter callback`. Context factories run lazily once
|
|
92
|
+
per actual execution. Inner inspectors can read `context.closure.data` and its
|
|
93
|
+
parent contexts regardless of which renderer is selected. The first non-undefined
|
|
94
|
+
inspector wins, searching from the selected expression outward.
|
|
95
|
+
|
|
96
|
+
For relate, context includes only actual consumed relation participants. Unrelated
|
|
97
|
+
values use ordinary preview. A collection is handled only when every member is
|
|
98
|
+
related; mixed collections fall through as a whole, preserving every previewable
|
|
99
|
+
member. Selecting an individual member tests that member independently.
|
|
100
|
+
Relative transformation functions and pivot/axis chains share a call inspector:
|
|
101
|
+
numeric and reference arguments inspect the consumed relation stage. Unconsumed
|
|
102
|
+
chains do not invent a stage. The tool can edit an ambient participant without
|
|
103
|
+
promoting its display tier.
|
|
104
|
+
|
|
105
|
+
Topology accessors (`vertex`, `edge`, `surface` and their plural forms) keep
|
|
106
|
+
ordinary anchor preview when they return references. Their inspector returns
|
|
107
|
+
the owner as `ambient` when the call fails or the reference collection is empty.
|
|
108
|
+
The owner therefore has the same background appearance before and after a
|
|
109
|
+
selection; missing or invalid IDs still produce their normal modeling errors.
|
|
110
|
+
|
|
111
|
+
### Call data
|
|
112
|
+
|
|
113
|
+
The App runs JSDoc inspection callbacks when the corresponding source is selected.
|
|
114
|
+
Callbacks return `target` and `ambient` preview values. The viewport retains its
|
|
115
|
+
previous scene until the new inspection is ready; an inspection error preserves
|
|
116
|
+
that scene and is reported separately from model evaluation errors.
|
|
117
|
+
|
|
118
|
+
Models, anchors, sketches, sketch points and passive annotations share this scene.
|
|
119
|
+
Sketches show their points and curves at their actual 3D placement, including open
|
|
120
|
+
curves, inherited layers and multiple noncoplanar sketches. They do not need to
|
|
121
|
+
form a face. The App's **Edit sketch** tool opens the selected authored sketch in
|
|
122
|
+
its 2D plane; **Finish sketch** returns to the 3D preview. Inspection callbacks
|
|
123
|
+
control passive appearance; editing and selection remain tool responsibilities.
|
|
124
|
+
|
|
125
|
+
Use `captureInspectData(data)` inside a modeling function to retain facts from
|
|
126
|
+
that invocation for its inspector. The function keeps its ordinary return type.
|
|
127
|
+
`InspectContext<Return, Receiver, Data>` describes the callback's return value,
|
|
128
|
+
receiver and recorded data. For example, a scalar query can retain its bounds:
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
import {
|
|
132
|
+
captureInspectData,
|
|
133
|
+
dimension,
|
|
134
|
+
type InspectContext,
|
|
135
|
+
type InspectResult,
|
|
136
|
+
type Model,
|
|
137
|
+
type Vec3,
|
|
138
|
+
} from '@code3d/core';
|
|
139
|
+
|
|
140
|
+
type SpanData = {owner: Model; minimum: Vec3; maximum: Vec3};
|
|
141
|
+
|
|
142
|
+
/** @code3d.inspect spanX.inspect */
|
|
143
|
+
export function spanX(owner: Model): number {
|
|
144
|
+
const {minimum, maximum} = owner.bounds();
|
|
145
|
+
captureInspectData({owner, minimum, maximum} satisfies SpanData);
|
|
146
|
+
return maximum[0] - minimum[0];
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/** @internal */
|
|
150
|
+
export namespace spanX {
|
|
151
|
+
export function inspect(
|
|
152
|
+
_args: [Model],
|
|
153
|
+
context: InspectContext<number, unknown, SpanData | undefined>,
|
|
154
|
+
): InspectResult | undefined {
|
|
155
|
+
const data = context.data;
|
|
156
|
+
if (!data || context.return === undefined) return undefined;
|
|
157
|
+
return {
|
|
158
|
+
target: [
|
|
159
|
+
data.owner,
|
|
160
|
+
dimension({
|
|
161
|
+
owner: data.owner,
|
|
162
|
+
start: data.minimum,
|
|
163
|
+
end: [data.maximum[0], data.minimum[1], data.minimum[2]],
|
|
164
|
+
value: context.return,
|
|
165
|
+
}),
|
|
166
|
+
],
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Data belongs to the actual call, including nested calls with equal return values.
|
|
173
|
+
Without a record, `context.data` is `undefined`; multiple records in one call use
|
|
174
|
+
the last value. Closure context factories can read their owning call's data from
|
|
175
|
+
`execution.call.data`. The executor retains references without cloning them, so
|
|
176
|
+
capture immutable facts when later changes must not alter the inspection.
|
|
177
|
+
Inspectors do not run the modeling function again.
|
|
178
|
+
|
|
179
|
+
A modeling function that throws can still be inspected if it was actually invoked.
|
|
180
|
+
Its original evaluated arguments and last captured data remain available, with
|
|
181
|
+
`context.return === undefined`. Argument evaluation failures and optional-chain
|
|
182
|
+
short circuits do not create an invocation of the outer function. Entered closure
|
|
183
|
+
callbacks follow the same rule. The original modeling diagnostic remains separate
|
|
184
|
+
from any inspection error; inspectors decide what to render when no result exists.
|
|
185
|
+
|
|
186
|
+
Without an inspection recording session, `captureInspectData` does nothing.
|
|
187
|
+
Calls from an inspector also do not overwrite modeling records. Published
|
|
188
|
+
callbacks use normal runtime exports; `@internal` with TypeScript's
|
|
189
|
+
`stripInternal` can hide their declarations while keeping those exports.
|
|
190
|
+
|
|
191
|
+
A dimension can provide fixed `start`/`end` points or a nonempty `candidates` list.
|
|
192
|
+
All points use the owner's local frame. For candidates, the renderer picks the
|
|
193
|
+
nearest segment when inspection begins, then retains it while orbiting or
|
|
194
|
+
rechecking the same parameter. Leaving that inspection resets the choice.
|
|
195
|
+
Both forms show a number, endpoint ticks and a screen-sized dashed line.
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
import {dimension, type Model} from '@code3d/core';
|
|
199
|
+
|
|
200
|
+
function showLength(owner: Model) {
|
|
201
|
+
return {
|
|
202
|
+
target: [
|
|
203
|
+
owner,
|
|
204
|
+
dimension({
|
|
205
|
+
owner,
|
|
206
|
+
value: 10,
|
|
207
|
+
candidates: [
|
|
208
|
+
{start: [-5, -2, -3], end: [5, -2, -3]},
|
|
209
|
+
{start: [-5, 2, 3], end: [5, 2, 3]},
|
|
210
|
+
],
|
|
211
|
+
}),
|
|
212
|
+
],
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
`boundsAnnotation` represents a finite range without adding CAD geometry. Its
|
|
218
|
+
`frame` is relative to `owner`, centered on the box; `size` measures its three
|
|
219
|
+
local axes. The App draws the existing bounds corners at a fixed screen width.
|
|
220
|
+
It can represent the exact support range of an `on` relation, including flat or
|
|
221
|
+
linear ranges, instead of substituting the whole owner's bounding box.
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
import {boundsAnnotation, type Model} from '@code3d/core';
|
|
225
|
+
|
|
226
|
+
function showRange(owner: Model) {
|
|
227
|
+
return {
|
|
228
|
+
target: [
|
|
229
|
+
owner,
|
|
230
|
+
boundsAnnotation({
|
|
231
|
+
owner,
|
|
232
|
+
size: [20, 10, 5],
|
|
233
|
+
frame: {position: [0, 0, 0], quaternion: [0, 0, 0, 1]},
|
|
234
|
+
}),
|
|
235
|
+
],
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Use `anchorAnnotation(reference, {direction})` to choose `'none'`, `'forward'`
|
|
241
|
+
or `'both'` for direction arrows while keeping the reference's geometry and
|
|
242
|
+
placement. For curves, arrows follow the real endpoint tangents; reversing the
|
|
243
|
+
reference reverses its authored direction. The annotation retains the reference's
|
|
244
|
+
focus identity. Returning an ordinary Anchor keeps its default object preview.
|
|
245
|
+
|
|
246
|
+
```ts
|
|
247
|
+
import {anchorAnnotation, type SolidModel} from '@code3d/core';
|
|
248
|
+
|
|
249
|
+
function showAxis(owner: SolidModel) {
|
|
250
|
+
return {
|
|
251
|
+
ambient: [owner],
|
|
252
|
+
target: [anchorAnnotation(owner.axis, {direction: 'forward'})],
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## Source and development
|
|
258
|
+
|
|
259
|
+
For changes to Core itself, start with the [modeling architecture](../../../.agents/docs/architecture/modeling.md)
|
|
260
|
+
and shared [development guide](../../../.agents/docs/development.md), then follow
|
|
261
|
+
the implementation and tests below.
|
|
262
|
+
|
|
263
|
+
- [Public exports](../src/library/index.ts), [model runtime](../src/library/runtime.ts),
|
|
264
|
+
and [public type tests](../test/public-types.ts).
|
|
265
|
+
- [Spatial values](../src/library/spatial.ts), [relation solving](../src/library/relation-solver.ts),
|
|
266
|
+
and [topology](../src/library/topology.ts).
|
|
267
|
+
- [Cached computations](../src/library/cached.ts), [fonts](../src/library/font.ts),
|
|
268
|
+
[text geometry](../src/library/text.ts) and their [tests](../test).
|
|
269
|
+
- [Material values](../src/library/material.ts), [kernel cache](../src/library/kernel-cache.ts),
|
|
270
|
+
and [Node entry](../src/node/index.ts).
|
|
271
|
+
- [Executable App examples](../../app/examples) and [runtime tests](../test).
|
|
272
|
+
|
|
273
|
+
Public JavaScript entries are prebundled ESM with shared chunks. Node, browser,
|
|
274
|
+
tooling and interop entries share the same kernel and cache instances. TypeScript
|
|
275
|
+
declarations, declaration maps and their sources remain available for editor
|
|
276
|
+
navigation. The build and npm `prepack` use the same package build script; see the
|
|
277
|
+
[development guide](../../../.agents/docs/development.md#公开包产物) for installed
|
|
278
|
+
tarball verification and CI publishing.
|
|
279
|
+
|
|
280
|
+
For a standalone TypeScript project, include `ESNext` and `DOM` in `compilerOptions.lib`.
|
|
281
|
+
Use `module: "ESNext"` and `moduleResolution: "Bundler"` when esbuild or another
|
|
282
|
+
bundler handles execution. Code3D's App uses this resolution mode, supports
|
|
283
|
+
extensionless relative imports and selects browser package exports.
|
|
284
|
+
The public packages are built and verified with `skipLibCheck: false`. NodeNext
|
|
285
|
+
currently needs `skipLibCheck` because the `manifold-3d@3.0.1` declarations omit
|
|
286
|
+
relative `.js` extensions. Core includes the declaration dependencies needed by
|
|
287
|
+
its HarfBuzz and Replicad integrations.
|
|
288
|
+
|
|
289
|
+
From the repository root:
|
|
290
|
+
|
|
291
|
+
```sh
|
|
292
|
+
npm run build:packages
|
|
293
|
+
npm test --workspace @code3d/core
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Use the [agent entry](../../../docs/agents.md) to work on a project through the CLI,
|
|
297
|
+
or the [App README](../../app/README.md) to develop the editor and visualization.
|
package/docs/shells.mdx
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Making hollow parts
|
|
3
|
+
description: Create uniform walls and choose openings directly on a solid.
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 8
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
import ModelExample from '../../web/src/components/ModelExample.astro';
|
|
9
|
+
|
|
10
|
+
Start with a solid that describes the outside of your part. Use
|
|
11
|
+
`shell(thickness, removedSurfaceIds?)` to hollow it and choose which faces
|
|
12
|
+
become openings.
|
|
13
|
+
|
|
14
|
+
<ModelExample id="shell" />
|
|
15
|
+
|
|
16
|
+
## Set the wall thickness
|
|
17
|
+
|
|
18
|
+
Positive thickness offsets inward, preserving the outside dimensions.
|
|
19
|
+
The example keeps its 40 × 24 × 30 outside size with walls 1.5 units thick.
|
|
20
|
+
Negative thickness offsets outward, keeping the original boundary on the
|
|
21
|
+
inside; neighboring offset faces use rounded joins where they separate.
|
|
22
|
+
|
|
23
|
+
Place the cursor inside `shell(1.5, [4])` to edit **Wall thickness** in the
|
|
24
|
+
panel. Thickness must be finite and nonzero.
|
|
25
|
+
|
|
26
|
+
## Pick the openings
|
|
27
|
+
|
|
28
|
+
S4 is the input box's +Y face. In the **Openings** tool, click another face to
|
|
29
|
+
open it, or click a selected face again to restore the wall. The viewport
|
|
30
|
+
keeps the input faces available while showing the hollow result, so a removed
|
|
31
|
+
face can still be selected.
|
|
32
|
+
|
|
33
|
+
Selections write back immediately. **Close all openings** removes the surface
|
|
34
|
+
array. Omitting it, or passing `[]`, creates a sealed cavity:
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
const sealed = box(40, 24, 30).shell(1.5);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
At least one face must remain as a wall. Use Undo to revert a committed
|
|
41
|
+
selection; moving the source cursor out of the call leaves the tool.
|
|
42
|
+
|
|
43
|
+
## Select faces from the input
|
|
44
|
+
|
|
45
|
+
An opening ID belongs to the solid before `shell`. For a two-section loft,
|
|
46
|
+
the cap IDs carry their source-section paths:
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
const openEnds = body.shell(1, [
|
|
50
|
+
[1, 1],
|
|
51
|
+
[2, 1],
|
|
52
|
+
]);
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The outer array lists two openings; each inner array is one surface ID.
|
|
56
|
+
After shelling, one-to-one inherited topology keeps its complete ID.
|
|
57
|
+
Offset walls receive fresh numeric IDs without reusing retired ones. Pick later fillet or chamfer edges
|
|
58
|
+
from the shell result. See [topology paths](topology.md#ids-belong-to-a-model)
|
|
59
|
+
and the [loft cap example](/examples/topology-paths/).
|
|
60
|
+
|
|
61
|
+
## Correct a failed shell
|
|
62
|
+
|
|
63
|
+
Shelling requires one connected solid. Tight curves, narrow features, and
|
|
64
|
+
complex intersections can prevent a valid offset or opening. The tool keeps
|
|
65
|
+
the input available so you can change the thickness or selected faces.
|
|
66
|
+
|
|
67
|
+
On some lofts between different profile shapes, a sealed cavity succeeds
|
|
68
|
+
while opening an end fails, even at smaller thicknesses. The
|
|
69
|
+
[bent loft example](/examples/loft/) has this known
|
|
70
|
+
limitation. See [geometric operation limits](../../web/src/content/docs/docs/getting-started/limitations.md#what-to-account-for).
|
package/docs/sketches.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Editable sketches
|
|
3
|
+
description: Create constrained sketches and relate their planes to model geometry.
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 7
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Editable sketches
|
|
9
|
+
|
|
10
|
+
Sketches are immutable 2D definitions, separate from B-Rep model values. Entries
|
|
11
|
+
carry positive IDs within a layer; constraints express what should stay true.
|
|
12
|
+
A derived layer can reference its upstream geometry.
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
import {sketch} from '@code3d/core';
|
|
16
|
+
|
|
17
|
+
const profile = sketch(
|
|
18
|
+
[
|
|
19
|
+
['point', 1, [0, 0]],
|
|
20
|
+
['circle', 2, [1, 8]],
|
|
21
|
+
],
|
|
22
|
+
{
|
|
23
|
+
constraints: [
|
|
24
|
+
['fixed', 1],
|
|
25
|
+
['radius', 2, 8],
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
export const part = profile.face().extrude(3);
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Closed regions bridge sketches to ordinary face and solid modeling. Read the
|
|
34
|
+
[sketch reference](api.md#editable-sketch-regions)
|
|
35
|
+
and [agent sketch workflow](../../../docs/agents/sketches.md) for constraints,
|
|
36
|
+
derived layers, observations, and failure diagnostics. Exact tuple types and
|
|
37
|
+
solver behavior live in [sketch.ts](../src/library/sketch.ts) and
|
|
38
|
+
[sketch-solver.ts](../src/library/sketch-solver.ts).
|
|
39
|
+
|
|
40
|
+
### Relating a sketch to a model plane
|
|
41
|
+
|
|
42
|
+
`s.relate(self => self.plane.align(target))` returns a new sketch with spatial
|
|
43
|
+
relations, leaving its shared 2D definition and the original sketch unchanged.
|
|
44
|
+
It works before a face exists, including `sketch()` and open contours.
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
import {box, sketch} from '@code3d/core';
|
|
48
|
+
|
|
49
|
+
const host = box(40, 20, 30).rotate(0, 0, 25);
|
|
50
|
+
const profile = sketch([
|
|
51
|
+
['point', 1, [0, 0]],
|
|
52
|
+
['circle', 2, [1, 4]],
|
|
53
|
+
]);
|
|
54
|
+
const opening = profile.relate(s => s.plane.align(host.surface(4)));
|
|
55
|
+
const result = host.cut([opening.face().extrude(-20)]);
|
|
56
|
+
const draft = sketch().relate(s => s.plane.align(host.surface(2)));
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The target may be a named plane or a planar `host.surface(id)`. The sketch plane
|
|
60
|
+
normal is local `+Y`; alignment uses the same directed-plane alignment, composition-axis offset
|
|
61
|
+
and rotation semantics as model relations. It does not implicitly center the
|
|
62
|
+
sketch on a trimmed surface. An unbounded sketch plane cannot use `on()` to place
|
|
63
|
+
finite geometry against a bound; use `align()`. Topology-only pivots such as
|
|
64
|
+
`pivotVertex()` require a geometric model, not an empty sketch frame.
|
|
65
|
+
|
|
66
|
+
`derive()`, `face()` / `faces()` and extrusion inherit the relations. Boolean
|
|
67
|
+
operations and loft resolve their inputs in the shared composition context;
|
|
68
|
+
placement is not baked into tuple coordinates. A spatial copy shares point
|
|
69
|
+
identities with its original, so a derived layer can still use `profile.point(id)`.
|
|
70
|
+
References target the actual immutable model value: creating a later rotated or
|
|
71
|
+
repositioned model does not redirect existing sketch relations.
|
|
72
|
+
The `relate` callback parameter represents the new sketch frame; every returned
|
|
73
|
+
constraint must involve it. References to the original sketch's plane stay on
|
|
74
|
+
the original frame.
|
|
75
|
+
|
|
76
|
+
In the App, select the related value (`opening`) and choose **Edit sketch** to edit against read-only model
|
|
77
|
+
outlines projected into the sketch's local plane. Select `profile` and choose **Edit sketch** for its original
|
|
78
|
+
local view. Both edit the same source array, with ordinary undo; separate placements
|
|
79
|
+
of that geometry are not separate authoring definitions. Context outlines are
|
|
80
|
+
visual references only, not snapping targets or imported geometry constraints.
|
|
81
|
+
The select-surface-and-create UI is tracked separately within
|
|
82
|
+
[#114](https://github.com/vilicvane/code3d/issues/114).
|
|
83
|
+
Try [mounting-plate.ts](../../app/examples/sketches/mounting-plate.ts).
|
package/docs/text.md
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Text and fonts
|
|
3
|
+
description: Build solid text with Google Fonts or local font files.
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 9
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Text and fonts
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import {googleFont, text, extrude, group} from '@code3d/core';
|
|
12
|
+
|
|
13
|
+
const face = googleFont('Play');
|
|
14
|
+
export default group(extrude(text('Hello', face, 10), 1));
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
In the App, `googleFont()` uses a static family name and optional weight/italic
|
|
18
|
+
settings; `font()` accepts a static font-file URL or TTF/OTF bytes. The engine
|
|
19
|
+
prepares remote resources before synchronous model execution. Text returns
|
|
20
|
+
ordinary planar faces with a common baseline; `extrude(faces, distance)` preserves
|
|
21
|
+
their order and placement. Node can read local file URLs or use downloaded,
|
|
22
|
+
decoded font bytes. See the [text reference](api.md#text),
|
|
23
|
+
[runnable example](../../app/examples/text.ts) and [font notices](../THIRD_PARTY.md).
|
package/docs/topology.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Selecting vertices, edges, and faces
|
|
3
|
+
description: Pick topology for fillets, chamfers, shells, origins, and relation anchors.
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 6
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Start with a box:
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import {box} from '@code3d/core';
|
|
12
|
+
|
|
13
|
+
const base = box(36, 4, 24).fillet(1);
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Round all edges
|
|
17
|
+
|
|
18
|
+
`fillet(radius)` rounds every edge. `chamfer(distance)` bevels every edge.
|
|
19
|
+
The number must fit the geometry: an operation can fail when its size consumes
|
|
20
|
+
a small face or creates an invalid intersection.
|
|
21
|
+
|
|
22
|
+
## Choose edges visually
|
|
23
|
+
|
|
24
|
+
Place the cursor inside the `fillet` argument area. The edge tool lets you
|
|
25
|
+
select the edges to round. Selecting specific edges adds their IDs as the
|
|
26
|
+
second argument, for example `fillet(1, [2, 4])`.
|
|
27
|
+
|
|
28
|
+
The tool keeps the operation's input edges available for selection while
|
|
29
|
+
showing its result. Use the panel to adjust the radius or distance; those
|
|
30
|
+
edits return to the source as you type.
|
|
31
|
+
|
|
32
|
+
**Use all edges** removes the second argument. Deselecting every explicit edge
|
|
33
|
+
also returns to all-edge mode; an empty array is not an explicit no-op.
|
|
34
|
+
|
|
35
|
+
Selections write back immediately. Pressing `Esc` does not discard them or
|
|
36
|
+
close the tool; move the editor cursor away from the call to leave it, and
|
|
37
|
+
use Undo to revert an edit.
|
|
38
|
+
|
|
39
|
+
## Hollow a solid
|
|
40
|
+
|
|
41
|
+
`shell(thickness, removedSurfaceIds?)` creates uniform walls in a connected solid.
|
|
42
|
+
Positive thickness offsets inward and preserves its outside boundary; negative
|
|
43
|
+
thickness offsets outward and preserves the original boundary on the inside.
|
|
44
|
+
Outward offsets use rounded joins where neighboring offset faces separate.
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
const enclosure = box(40, 24, 30).shell(1.5, [4]);
|
|
48
|
+
const sealed = box(40, 24, 30).shell(1.5);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
For this box, S4 is its +Y face. Removing it makes an open enclosure. Follow the
|
|
52
|
+
[hollow-part guide](shells.mdx) for the runnable example. Place the
|
|
53
|
+
cursor inside `shell(...)` to adjust **Wall thickness** and toggle **Openings**
|
|
54
|
+
on the input model while viewing the result. IDs belong to that input model.
|
|
55
|
+
The picker retains removed faces so you can close an opening again.
|
|
56
|
+
|
|
57
|
+
Omitting the surface array, or passing `[]`, creates an enclosed cavity.
|
|
58
|
+
**Close all openings** removes the array. Selecting every face is an error:
|
|
59
|
+
at least one surface must remain as a wall. Thickness must be finite and nonzero.
|
|
60
|
+
Offsets can fail around narrow features and complex curves; the input remains
|
|
61
|
+
available to correct the thickness or openings.
|
|
62
|
+
|
|
63
|
+
## IDs belong to a model
|
|
64
|
+
|
|
65
|
+
Edge, face, and vertex IDs have separate namespaces within each model. An ID
|
|
66
|
+
is not a position in a JavaScript array or a globally unique identifier.
|
|
67
|
+
|
|
68
|
+
Primitives use numbers starting at `1`. Constructors such as loft, extrusion and
|
|
69
|
+
Boolean operations create a new namespace. Inherited elements receive paths
|
|
70
|
+
`[inputIndex, ...previousId]`, with input indices starting at `1`; new elements
|
|
71
|
+
receive numeric IDs starting at `1` in that result.
|
|
72
|
+
|
|
73
|
+
For `loft([start, end])`, the two cap faces are `surface([1, 1])` and
|
|
74
|
+
`surface([2, 1])`; side faces are `surface(1)`, `surface(2)`, and so on. Changing
|
|
75
|
+
the number of side faces does not move the cap IDs. Boolean operations use the
|
|
76
|
+
same rule for every input, including cutting tools. Edges and vertices follow
|
|
77
|
+
the same rules in their own namespaces.
|
|
78
|
+
|
|
79
|
+
Local edits (`fillet`, `chamfer`, and `shell`) keep the input namespace. A
|
|
80
|
+
one-to-one original `E10` remains `E10`, so a later chamfer can select it with
|
|
81
|
+
`rounded.chamfer(0.5, [10])`. Existing paths also remain unchanged: a loft cap
|
|
82
|
+
`S[2,1]` keeps that ID after a fillet. New elements use fresh numeric IDs above
|
|
83
|
+
all numbers previously allocated in this namespace, including retired IDs.
|
|
84
|
+
|
|
85
|
+
For example, `box(50, 3000, 100).fillet(5, [2, 4, 6, 8])` retains faces
|
|
86
|
+
`S1`–`S6` and adds four rounded faces `S7`–`S10`. The two end faces are still
|
|
87
|
+
`S3` and `S4`; rounding their corners does not break their one-to-one identity.
|
|
88
|
+
|
|
89
|
+
In the [topology paths example](/examples/topology-paths/), inspect
|
|
90
|
+
`inlet`, `outlet`, and `side` to compare inherited cap IDs with a new side
|
|
91
|
+
face. The viewport labels paths as S[1,1] or E[1,10]; selections write the
|
|
92
|
+
corresponding arrays into source.
|
|
93
|
+
|
|
94
|
+
Only one-to-one descendants inherit an ID. Deleted elements have no descendant;
|
|
95
|
+
ambiguous splits and merges receive new numeric IDs. A middle loft section is
|
|
96
|
+
not a cap, and a section edge split by loft compatibility does not retain a
|
|
97
|
+
single edge identity. New-element numbering follows deterministic construction
|
|
98
|
+
and can change when that construction changes.
|
|
99
|
+
|
|
100
|
+
Rotation, scaling, placement, and exposed references keep complete IDs. Always
|
|
101
|
+
select IDs from the model passed into the operation being edited; IDs are not
|
|
102
|
+
interchangeable between a source and its result.
|
|
103
|
+
|
|
104
|
+
Shelling follows the same history rules: an unchanged boundary retains its ID,
|
|
105
|
+
and offset walls get new numeric IDs. An opening rim can
|
|
106
|
+
inherit its former cap's surface ID when the kernel records a one-to-one
|
|
107
|
+
modification. To open both ends of a two-section loft, use
|
|
108
|
+
`body.shell(1, [[1, 1], [2, 1]])`.
|
|
109
|
+
|
|
110
|
+
## Use topology as a relation anchor
|
|
111
|
+
|
|
112
|
+
`model.surface(id)`, `model.edge(id)`, and `model.vertex(id)` return
|
|
113
|
+
face, line, and point anchors. Use their plural forms to obtain a collection;
|
|
114
|
+
omitting the ID array returns all elements of that kind.
|
|
115
|
+
|
|
116
|
+
Place the cursor in one of these calls to pick its topology in the viewport.
|
|
117
|
+
Singular forms select one ID; plural forms let you toggle multiple IDs and
|
|
118
|
+
can explicitly use `[]` for no elements. That is different from fillet and
|
|
119
|
+
chamfer's all-edge behavior.
|
|
120
|
+
|
|
121
|
+
Continue querying a selected face or edge:
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
const face = base.surface(1);
|
|
125
|
+
const boundary = face.edges();
|
|
126
|
+
const corners = boundary[0].vertices();
|
|
127
|
+
const center = face.center;
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Queries use the original model's IDs and stay within the selected element.
|
|
131
|
+
`face.edge(id)` reports an error if that edge is outside the face. The viewport
|
|
132
|
+
picker offers only the eligible edges or vertices, including when the geometry
|
|
133
|
+
is exposed from an assembly.
|
|
134
|
+
|
|
135
|
+
`center` is the selected geometry's local bounding-box center, carried through
|
|
136
|
+
transforms. Edges also provide `start`, `midpoint`, and `end` point anchors at
|
|
137
|
+
curve parameters 0, 0.5, and 1. A curve midpoint can differ from its center or
|
|
138
|
+
half-length point. Calculated points do not acquire vertex IDs; `.vertices()`
|
|
139
|
+
returns the actual topology, including a single vertex on a closed edge.
|
|
140
|
+
|
|
141
|
+
To choose a vertex as a rotation pivot, use `.originVertex(id)`. See
|
|
142
|
+
[origins and rotation](origins-and-rotation.mdx).
|
|
143
|
+
|
|
144
|
+
A named element exposed by a reusable part usually communicates intent better
|
|
145
|
+
than a caller maintaining its internal topology IDs. See
|
|
146
|
+
[reusable models](../../web/src/content/docs/docs/guides/reusable-models.mdx).
|
|
147
|
+
|
|
148
|
+
## Recover from an operation failure
|
|
149
|
+
|
|
150
|
+
Check the input edges first, then reduce the radius or distance. A failed
|
|
151
|
+
fillet or chamfer can still expose its input model to the contextual tool,
|
|
152
|
+
so you can correct the operation without deleting it.
|