@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
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Positioning with relations
|
|
3
|
+
description: Position geometry with bound contacts, geometric alignment, and explicit rotations.
|
|
4
|
+
sidebar:
|
|
5
|
+
order: 4
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
import ModelExample from '../../web/src/components/ModelExample.astro';
|
|
9
|
+
import SourceCode from '../../web/src/components/SourceCode.astro';
|
|
10
|
+
import ArrowIcon from '../../web/src/components/ArrowIcon.astro';
|
|
11
|
+
import {appUrl, sitePath} from '../../web/src/lib/site';
|
|
12
|
+
import source from '../../app/examples/constraints/combined-constraints.ts?raw';
|
|
13
|
+
import transformations from '../../app/examples/constraints/transformations.ts?raw';
|
|
14
|
+
|
|
15
|
+
A relation describes how one part sits against another. It is attached to a
|
|
16
|
+
model value and resolved when the parts are composed or their relative geometry is queried. The part keeps its own
|
|
17
|
+
[local coordinates](local-coordinates.md): `originOffset()` changes
|
|
18
|
+
those geometry coordinates, while a relation's `offset()` participates in
|
|
19
|
+
placement. Consecutive constraints are solved together; independent transformations
|
|
20
|
+
then move that joint result.
|
|
21
|
+
|
|
22
|
+
<ModelExample id="relate" />
|
|
23
|
+
|
|
24
|
+
## Touch a directional bound
|
|
25
|
+
|
|
26
|
+
`part.on(base.up)` places the part above the base by translating its matching
|
|
27
|
+
bound into contact. The six target directions are `up` (+Y), `down` (−Y),
|
|
28
|
+
`right` (+X), `left` (−X), `front` (+Z), and `back` (−Z), measured in the base's
|
|
29
|
+
local frame. They describe its finite bounding extent, not particular faces.
|
|
30
|
+
|
|
31
|
+
The source can also be a selected vertex, edge, or surface. Only that selected
|
|
32
|
+
geometry contributes its extent. A tilted shape still has a support boundary
|
|
33
|
+
in the target direction; `on` never rotates it. Without an offset, its position
|
|
34
|
+
along the boundary plane stays unchanged.
|
|
35
|
+
|
|
36
|
+
An explicit `offset(x, y, z)` translates self from the original solution in the
|
|
37
|
+
**target reference frame**. Zero leaves the result unchanged; it never adds
|
|
38
|
+
centering constraints. Use explicit point or axis alignment to center parts.
|
|
39
|
+
Consecutive offsets in the same frame add. Offsets and rotations execute in
|
|
40
|
+
call order: a translation before an external-axis rotation moves with that
|
|
41
|
+
rotation; the same translation after it does not.
|
|
42
|
+
`base.up.flip()` reverses the side of contact while keeping that frame and the
|
|
43
|
+
geometry unchanged. Arbitrary models or topology elements are not valid targets.
|
|
44
|
+
|
|
45
|
+
## Combine conditions
|
|
46
|
+
|
|
47
|
+
Return an array from `relate()` to solve several relations together:
|
|
48
|
+
|
|
49
|
+
<SourceCode source={source} file="constraints/combined-constraints.ts" />
|
|
50
|
+
|
|
51
|
+
<p>
|
|
52
|
+
<a
|
|
53
|
+
href={appUrl('constraints/combined-constraints.ts')}
|
|
54
|
+
target="_blank"
|
|
55
|
+
rel="noopener"
|
|
56
|
+
>
|
|
57
|
+
{'Open this example in the App '}
|
|
58
|
+
<ArrowIcon />
|
|
59
|
+
</a>
|
|
60
|
+
</p>
|
|
61
|
+
|
|
62
|
+
The two contacts place the second box at `[15, -15, 0]`. One determines X,
|
|
63
|
+
the other determines Y, and the free Z position stays unchanged. Conflicting
|
|
64
|
+
position conditions report an error. `on` only solves translation; rotations
|
|
65
|
+
are always authored explicitly.
|
|
66
|
+
|
|
67
|
+
## Align underlying geometry
|
|
68
|
+
|
|
69
|
+
Use `align` when the relationship should determine geometry and direction:
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
const post = cylinder(5, 20).relate(self => [
|
|
73
|
+
self.axis.align(base.axis),
|
|
74
|
+
self.on(base.up),
|
|
75
|
+
]);
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Points coincide or lie on a curve or surface. Curves coincide with one another,
|
|
79
|
+
or lie entirely on a surface. Surfaces coincide with matching normal sense.
|
|
80
|
+
Unlike a bound contact, alignment can rotate self. Lines, circles, ellipses,
|
|
81
|
+
planes, cylinders, and spheres are supported; other underlying geometry types
|
|
82
|
+
report unsupported.
|
|
83
|
+
|
|
84
|
+
Edges and faces contribute their complete supporting geometry. A point can lie
|
|
85
|
+
on the extension of a short straight edge; two equal-radius arcs can share a
|
|
86
|
+
circle even when their trimmed ranges differ. Endpoints and parameter origins
|
|
87
|
+
are not paired. Use `start`, `midpoint`, `end`, or a vertex when more specific
|
|
88
|
+
positioning is needed. Multiple solutions can remain.
|
|
89
|
+
|
|
90
|
+
Curve–curve alignment uses the same positive direction. Use `target.reverse()`
|
|
91
|
+
to reverse a line, axis, or edge reference, and `target.flip()` to reverse a
|
|
92
|
+
surface's normal sense. These change direction metadata while preserving the
|
|
93
|
+
reference axes. Point membership ignores direction; a curve lying on a surface
|
|
94
|
+
does not gain an arbitrary heading in that surface.
|
|
95
|
+
|
|
96
|
+
Constraints do not have offset or rotation methods. To adjust their solved pose,
|
|
97
|
+
add an independent `offset(x, y, z)` array entry. Its direction uses the fixed
|
|
98
|
+
composition axes, regardless of which side of `on` or `align` names self.
|
|
99
|
+
Zero leaves the preceding solution unchanged.
|
|
100
|
+
|
|
101
|
+
<ModelExample id="expose" />
|
|
102
|
+
|
|
103
|
+
The pin function exposes its mounting face, tip face and centerline. The cap
|
|
104
|
+
aligns its axis to the pin and touches its tip. These two relations express the
|
|
105
|
+
actual fit; changing the pin's height does not require recomputing the cap position.
|
|
106
|
+
|
|
107
|
+
Relation curves keep their actual shape and serve as the arrow shaft. Only
|
|
108
|
+
the arrowhead is added at the directed endpoint (or seam for a closed curve),
|
|
109
|
+
following its tangent.
|
|
110
|
+
`reverse()` uses the opposite endpoint and tangent. Axes use one positive
|
|
111
|
+
arrow while inspecting a relation; passive axis references have arrows at
|
|
112
|
+
both ends.
|
|
113
|
+
Arrowheads keep the same screen size as you zoom. Unsupported geometry,
|
|
114
|
+
geometric incompatibility, and numerical nonconvergence have separate errors.
|
|
115
|
+
|
|
116
|
+
To adjust a multi-constraint result visually, select self. The App edits or adds
|
|
117
|
+
an independent transformation after the joint constraint segment.
|
|
118
|
+
|
|
119
|
+
## Align coordinate systems
|
|
120
|
+
|
|
121
|
+
All models, including groups, expose `frame` and `origin` references.
|
|
122
|
+
`model.origin` is the same reference as `model.frame.origin`; neither reference
|
|
123
|
+
adds geometry to the result.
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
const positioned = part.relate(self => self.origin.align(base.origin));
|
|
127
|
+
const mounted = part.relate(self => self.frame.align(base.frame));
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Origin alignment leaves orientation free. Frame alignment coincides the origins
|
|
131
|
+
and the corresponding X/Y/Z directions, fixing all six relative degrees of
|
|
132
|
+
freedom. It uses the target's solved placement, including its relations to other
|
|
133
|
+
models. The target can remain a reference dependency without being included in
|
|
134
|
+
the output group. Both constraints participate in the same joint solve as other
|
|
135
|
+
`align` and `on` constraints.
|
|
136
|
+
|
|
137
|
+
Named frames work the same way: `assembly.expose({mount: part.frame})` provides
|
|
138
|
+
`assembly.mount` and `assembly.mount.origin` in the assembly's coordinates.
|
|
139
|
+
|
|
140
|
+
## Choose a rotation pivot or axis
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
import {pivot} from '@code3d/core';
|
|
144
|
+
|
|
145
|
+
const placed = part.relate(self => [
|
|
146
|
+
self.on(base.up),
|
|
147
|
+
pivot([50, 0, 0]).rotate(0, 0, 45),
|
|
148
|
+
]);
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
The pivot is expressed in self's local coordinates. Use `pivotVertex(id)` to
|
|
152
|
+
choose one of self's vertices, or omit the pivot and call `rotate(x, y, z)`
|
|
153
|
+
to rotate around self's origin. Angles are degrees, applied X, then Y, then Z.
|
|
154
|
+
`axisLine(base.axis).rotate(angle)` instead uses a positioned line axis; external
|
|
155
|
+
axes follow their own composition placement. Each selection applies only to
|
|
156
|
+
the next rotation.
|
|
157
|
+
|
|
158
|
+
To move a reference without losing it, use
|
|
159
|
+
`pivotVertex(id).pivotOffset(dx, dy, dz).rotate(x, y, z)` or
|
|
160
|
+
`axisLine(base.axis).axisOffset(dx, dy, dz).rotate(angle)`. `pivot([...])` also
|
|
161
|
+
accepts `pivotOffset`. The point displacement uses self's local axes; the axis
|
|
162
|
+
displacement uses the selected axis frame. Moving along the axis itself has no
|
|
163
|
+
effect on the rotation. These are reference modifiers, followed by one `rotate`;
|
|
164
|
+
completed transformations remain separate array entries.
|
|
165
|
+
|
|
166
|
+
Rotations follow the preceding joint constraint solution. Later transformations
|
|
167
|
+
compose in order; a later constraint starts a new segment from that pose.
|
|
168
|
+
Groups move their assembled children as one rigid part.
|
|
169
|
+
|
|
170
|
+
### Bend a loft with explicit rotations
|
|
171
|
+
|
|
172
|
+
<ModelExample id="loft" />
|
|
173
|
+
|
|
174
|
+
The octagonal and rectangular sections first touch the circle's `up` bound,
|
|
175
|
+
then turn 45° and 90° around a pivot 50 units along self's X axis.
|
|
176
|
+
Inspect `sections` to see the positioned profiles, or `loft` to see the solid
|
|
177
|
+
through them. Editing `pivot` or `rotate` changes the same source used here.
|
|
178
|
+
|
|
179
|
+
## Transform a joint result
|
|
180
|
+
|
|
181
|
+
Import `offset`, `rotate`, `pivot`, `pivotVertex`, `pivotPoint`, `axisEdge`, or `axisLine` from Core to build
|
|
182
|
+
an independent `Transformation` inside `relate`. It acts on the joint solution
|
|
183
|
+
and can move the part away from its contacts:
|
|
184
|
+
|
|
185
|
+
<SourceCode source={transformations} file="constraints/transformations.ts" />
|
|
186
|
+
|
|
187
|
+
<p>
|
|
188
|
+
<a
|
|
189
|
+
href={appUrl('constraints/transformations.ts')}
|
|
190
|
+
target="_blank"
|
|
191
|
+
rel="noopener"
|
|
192
|
+
>
|
|
193
|
+
{'Open the transformation example '}
|
|
194
|
+
<ArrowIcon />
|
|
195
|
+
</a>
|
|
196
|
+
</p>
|
|
197
|
+
|
|
198
|
+
Independent `offset(x, y, z)` uses the composition's fixed axes. Rotating the
|
|
199
|
+
part does not rotate those offset directions. Independent `rotate(x, y, z)`
|
|
200
|
+
uses self's current origin and local axes; `pivot([x, y, z])` changes that center,
|
|
201
|
+
`pivotVertex(id)` chooses a self vertex; `pivotPoint(pointRef)` selects a local or external point while keeping self XYZ axes. `axisEdge(id).rotate(angle)` chooses a straight self edge, and `axisLine(lineRef).rotate(angle)` uses
|
|
202
|
+
the referenced axis in its solved placement. Pivot selections apply to the next
|
|
203
|
+
rotation. Completed transformations cannot be chained: write `[offset(...), rotate(...)]`,
|
|
204
|
+
not `offset(...).rotate(...)`. Only pivot and axis selections expose `rotate` to
|
|
205
|
+
complete that one operation. These constructors describe relative placement;
|
|
206
|
+
they do not add `model.offset()` or change standalone geometry.
|
|
207
|
+
|
|
208
|
+
Transformation array entries execute in order. A later constraint
|
|
209
|
+
starts a new joint segment: `[align, on, offset, rotate]` solves the two constraints
|
|
210
|
+
then transforms the result; `[align, offset, on]` solves align, moves the result,
|
|
211
|
+
then solves on from that pose. The later segment preserves its unconstrained
|
|
212
|
+
position and orientation from its input. Previous segments do not remain hard
|
|
213
|
+
conditions on that later result. Successive `relate` calls continue the same
|
|
214
|
+
sequence; constraints without an intervening transformation remain one segment.
|
|
215
|
+
|
|
216
|
+
The fixed composition frame belongs to this assembly. A nested group's existing
|
|
217
|
+
placement and origin rules carry it into the enclosing group; it is not the
|
|
218
|
+
viewport's world frame. Call order remains meaningful, especially around a fixed
|
|
219
|
+
external axis. A fixed-axis translation and a rotation about the current self
|
|
220
|
+
origin can happen to commute without changing the sequencing rule.
|
|
221
|
+
|
|
222
|
+
## Choose which part moves
|
|
223
|
+
|
|
224
|
+
`relate` returns a new value and passes it to the callback as `self`. Every
|
|
225
|
+
constraint must involve that value, even when written as `base.on(self.up)`.
|
|
226
|
+
The parameter can have any name; it is its value that identifies the new part.
|
|
227
|
+
External variables always refer to their existing model, so a part can be
|
|
228
|
+
placed against the original value from which it was derived:
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
const side = box(2, 250, 250);
|
|
232
|
+
const leftSide = side;
|
|
233
|
+
const rightSide = side.relate(self => [
|
|
234
|
+
self.on(leftSide.right),
|
|
235
|
+
offset(160, 0, 0),
|
|
236
|
+
]);
|
|
237
|
+
const assembly = group([leftSide, rightSide]);
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
The two panel centers are 162 units apart, with a 160-unit gap. `side` and
|
|
241
|
+
`leftSide` remain unchanged; no intermediate copy is needed.
|
|
242
|
+
|
|
243
|
+
This identity rule also applies to selected elements and rotation references:
|
|
244
|
+
`pivotPoint(self.center)` follows the new part's center, while
|
|
245
|
+
`pivotPoint(side.center)` rotates around the original part's center.
|
|
246
|
+
`axisLine(self.axis)` and `axisLine(side.axis)` distinguish the same two owners.
|
|
247
|
+
Use `self.surface(id)`, `self.edge(id)`, or `self.vertex(id)` to constrain an
|
|
248
|
+
element of the new part. A reference selected before the callback stays attached
|
|
249
|
+
to its original model.
|
|
250
|
+
|
|
251
|
+
## Inspect the right scope
|
|
252
|
+
|
|
253
|
+
The related part on its own still displays in its local frame. Select the
|
|
254
|
+
`group` to see the part positioned against the base, or place the cursor in
|
|
255
|
+
the relation to inspect both participants. Related expressions inside the callback keep the actual participants visible.
|
|
256
|
+
`on` and `align` inspectors show the relevant anchors and finite support bounds.
|
|
257
|
+
Unrelated values keep their ordinary preview, and mixed collections preview all
|
|
258
|
+
of their members. An inner call's own inspector or ordinary result takes
|
|
259
|
+
precedence over the enclosing callback.
|
|
260
|
+
|
|
261
|
+
The callback parameter in `relate(part => ...)` is the new related model
|
|
262
|
+
value. Place the cursor on its declaration or a use of `part` inside the
|
|
263
|
+
callback to inspect its completed placement segment. Its tools edit the nearest
|
|
264
|
+
following offset or rotation, with the preview including later operations in that segment.
|
|
265
|
+
Even before you write a consuming
|
|
266
|
+
`group` or `loft`, the relation context shows the participants in their solved
|
|
267
|
+
positions. Selecting the related model's standalone binding shows it in its local
|
|
268
|
+
frame. Operations preserve the observable meaning of existing model values.
|
|
269
|
+
|
|
270
|
+
In a `relate` array, `on` and `align` show the joint solution of their continuous
|
|
271
|
+
constraint segment. Each independent `offset` or `rotate` shows its own result.
|
|
272
|
+
The pivot and axis selectors show the preceding pose with the selected reference.
|
|
273
|
+
Later steps do not move this preview or its handles. Previous segments provide
|
|
274
|
+
the incoming pose; later segments are excluded. An invalid segment reports a
|
|
275
|
+
preview error while keeping the valid final model available.
|
|
276
|
+
|
|
277
|
+
<p>
|
|
278
|
+
<a href={sitePath('examples/relate/')}>
|
|
279
|
+
Step through contact, target, offset, and rotation in the relation preview →
|
|
280
|
+
</a>
|
|
281
|
+
</p>
|
|
282
|
+
|
|
283
|
+
## Read the relation highlights
|
|
284
|
+
|
|
285
|
+
The viewport distinguishes focused targets, other targets, and ambient geometry.
|
|
286
|
+
An inspector declares the complete scene. Targets that are the actual selected
|
|
287
|
+
values receive focus; generated results do not inherit focus from their inputs.
|
|
288
|
+
With focus present, other target markers use 70% of their normal opacity. Without
|
|
289
|
+
focus, all target markers keep their normal opacity. Ambient geometry stays gray.
|
|
290
|
+
|
|
291
|
+
On the `relate` method name, the completed part is the target and this call's
|
|
292
|
+
actual participants are ambient. Unrelated downstream parts are omitted. Inside
|
|
293
|
+
its callback, related values use the same participants and the selected relation
|
|
294
|
+
stage. Unrelated values use ordinary object preview; a mixed collection falls
|
|
295
|
+
through as a whole so no unrelated member disappears.
|
|
296
|
+
|
|
297
|
+
`on` and `align` have their own inspectors for the call, receiver and target.
|
|
298
|
+
Selecting a reference emphasizes that reference. Selecting the method name shows
|
|
299
|
+
the participating references without inventing a focused side. In
|
|
300
|
+
`base.on(self.up)`, selecting `self.up` therefore focuses self's bound. Independent
|
|
301
|
+
`offset`, `pivot`, `pivotVertex`, `pivotPoint`, `axisEdge`, `axisLine` and `rotate`
|
|
302
|
+
expressions use the relate stage; their editing handles remain separate from
|
|
303
|
+
passive inspection. See [source inspection](runtime.md#source-inspection) for
|
|
304
|
+
custom JSDoc inspectors and closure contexts.
|
|
305
|
+
|
|
306
|
+
Model surfaces remain translucent so you can see overlapping references.
|
|
307
|
+
Their opacity is capped for the current role instead of multiplied by the
|
|
308
|
+
material's existing opacity. A model that is already more transparent keeps
|
|
309
|
+
its material; the marker groups still show which side is selected.
|
|
310
|
+
|
|
311
|
+
A bound face adds translucent fill in the same color as its bounding box.
|
|
312
|
+
If that box is already visible, the face does not add another corner outline.
|
|
313
|
+
When no box is visible, it supplies its own corner brackets. The source of
|
|
314
|
+
`on` shows its complete measured bounding box, since contact is calculated
|
|
315
|
+
from that whole extent. For a selected vertex, edge, or surface, this box
|
|
316
|
+
encloses only the selected geometry. Bounds describe finite extents rather
|
|
317
|
+
than selecting a real topology face.
|
|
318
|
+
|
|
319
|
+
Face arrows, axis arrowheads, point markers, and spatial controls keep their
|
|
320
|
+
screen size through zoom and viewport resizing. Axis shafts and curved
|
|
321
|
+
highlights still follow their actual geometry.
|
|
322
|
+
|
|
323
|
+
## Group or fuse
|
|
324
|
+
|
|
325
|
+
Use `group([base, post])` for separate parts. Use `union([base, post])`
|
|
326
|
+
when you want a single fused solid. Boolean operations also resolve operand
|
|
327
|
+
relations before evaluating geometry.
|
|
328
|
+
|
|
329
|
+
## Make visual adjustments
|
|
330
|
+
|
|
331
|
+
Enter an `offset` call in the source to use the position tool. Supported
|
|
332
|
+
parameter changes write back to the defining source values. A unique upstream
|
|
333
|
+
parameter takes priority when the tool can safely preview its uses. If it is
|
|
334
|
+
shared, other affected objects preview the change as well.
|
|
335
|
+
|
|
336
|
+
Without a safe upstream parameter, dragging preserves the offset expression
|
|
337
|
+
and adjusts it by an increment. For example, an X movement of `2` changes
|
|
338
|
+
`offset((i - 2) * 8, 0, 0)` to `offset((i - 2) * 8 + 2, 0, 0)`.
|
|
339
|
+
Another movement of `3` combines that increment into `+ 5`. Returning by `5`
|
|
340
|
+
removes it. The tool does not change the inner `8` or keep nesting offset calls.
|
|
341
|
+
|
|
342
|
+
Selecting self shows the complete placement segment. Choosing a tool keeps a
|
|
343
|
+
matching current call, or checks the immediately following transformation. If
|
|
344
|
+
that transformation matches, it activates the existing call; otherwise it inserts
|
|
345
|
+
before that transformation. It never skips a different transformation to find
|
|
346
|
+
a matching one farther ahead. With no following transformation, it appends. In a multi-constraint array,
|
|
347
|
+
they target independent transformations after the jointly solved constraints.
|
|
348
|
+
The search stops at the next constraint segment. App inserts the corresponding
|
|
349
|
+
Core import when needed. It preserves existing aliases and avoids local name
|
|
350
|
+
collisions.
|
|
351
|
+
|
|
352
|
+
The toolbar starts with no active tool when selecting a model, self, or a blank
|
|
353
|
+
array position. Choose a tool explicitly, or place the caret in an existing
|
|
354
|
+
offset or rotation call to activate its tool. When focus moves into the viewport,
|
|
355
|
+
the editor keeps a static caret and word marker at the current source position.
|
|
356
|
+
The active tool's existing call is underlined; if the tool needs to insert a call,
|
|
357
|
+
the underline appears on that new code after the edit. Marked code scrolls into
|
|
358
|
+
view, including horizontally, without taking focus from the viewport or an input.
|
|
359
|
+
Parameter and topology tools use the same source markers and navigation.
|
|
360
|
+
Clicking a tool with an existing call moves the caret to the complete expression
|
|
361
|
+
end, such as `offset()|` or `axisEdge(1).rotate(25)|`, and shows that step immediately. If a new call is needed, the viewport shows the state just
|
|
362
|
+
before the actual insertion position. The chosen tool stays active, and clicking
|
|
363
|
+
alone does not change the source. New array calls put the caret in the insertion
|
|
364
|
+
gap: before the closing bracket at the end, or before the next item in the middle.
|
|
365
|
+
From an array gap, the same rule checks only the immediately following item;
|
|
366
|
+
a mismatch keeps the insertion position.
|
|
367
|
+
|
|
368
|
+
The start of a self expression, such as `|self.axis.align(...)`, also counts as
|
|
369
|
+
self context. Plain rotate and pivot selectors match point rotation; axis selectors match
|
|
370
|
+
axis rotation. Choosing one does not activate a call of the other type.
|
|
371
|
+
|
|
372
|
+
When an `offset` or `rotate` is selected, the matching tool edits that call.
|
|
373
|
+
Choosing another tool checks the next transformation first. A match activates it;
|
|
374
|
+
a mismatch inserts immediately after the selected call, before later operations. For independent transformations this inserts a new array
|
|
375
|
+
item; a single return value becomes an array. It never chains one completed
|
|
376
|
+
transformation into another. Handles and previews use the frame of that exact
|
|
377
|
+
edit, excluding later operations. A spread argument is replaced
|
|
378
|
+
with the current three values when editing that call.
|
|
379
|
+
|
|
380
|
+
A safe shared parameter can update multiple instances of the same call. If it
|
|
381
|
+
also controls a different operation, dragging adjusts the selected expression
|
|
382
|
+
instead. A shared expression changes all of its runtime occurrences; it is not
|
|
383
|
+
an override for only the clicked part.
|
|
384
|
+
|
|
385
|
+
Release to commit the preview, or press `Esc` while dragging to cancel without
|
|
386
|
+
closing the panel. Use Undo after an edit has been committed. Numeric panel
|
|
387
|
+
input has a different meaning when an expression appears as a placeholder:
|
|
388
|
+
it [replaces the whole argument](../../web/src/content/docs/docs/guides/model-tools.mdx#what-a-panel-can-edit).
|
|
389
|
+
|
|
390
|
+
Use the position toolbar above the panel to choose translation or a rotation
|
|
391
|
+
variant. In either rotation tool, hold Alt to move its reference instead of
|
|
392
|
+
rotating the part. Point or axis candidates appear while the corresponding
|
|
393
|
+
rotation tool is active; click one directly to choose the reference. Point selection
|
|
394
|
+
retains a vertex ID; axis selection uses a straight edge or a named axis of self.
|
|
395
|
+
Replacing a reference within the same rotation type retains its offset and angles;
|
|
396
|
+
choosing a reference for the other rotation type adds a new zero-angle operation.
|
|
397
|
+
|
|
398
|
+
To change the standalone geometry and its origin, see
|
|
399
|
+
[origins and rotation](origins-and-rotation.mdx).
|
|
400
|
+
|
|
401
|
+
See [code and geometry](../../web/src/content/docs/docs/concepts/code-and-geometry.md) for the distinction
|
|
402
|
+
between a model value and its runtime context.
|
|
403
|
+
|
|
404
|
+
## Measure before building a part
|
|
405
|
+
|
|
406
|
+
Use `distance(a, b, axis?)` when another part's dimensions depend on existing
|
|
407
|
+
geometry. The query resolves the inputs' current relations and returns an
|
|
408
|
+
ordinary number; a group is not required before measuring.
|
|
409
|
+
|
|
410
|
+
<ModelExample id="distance" />
|
|
411
|
+
|
|
412
|
+
In this example, change `gap` to resize the opening and its beam. The beam reads
|
|
413
|
+
the X gap between the two facing bounds and the support's Z depth, then builds
|
|
414
|
+
with those dimensions. Its height remains fixed. The Arguments presets show
|
|
415
|
+
two sizes of the same assembly.
|
|
416
|
+
|
|
417
|
+
Omit the axis for the shortest spatial distance, or provide `x`, `y`, `z`, a
|
|
418
|
+
direction vector, or a straight edge/axis reference for the gap between projected
|
|
419
|
+
intervals. Use topology faces when their actual trimmed shape matters; a
|
|
420
|
+
directional bound measures its rectangular extent. See the
|
|
421
|
+
[measurement reference](api.md#measurements) for supported inputs
|
|
422
|
+
and coordinate rules.
|
|
423
|
+
|
|
424
|
+
Measurements follow source order. Adding a later relation does not retroactively
|
|
425
|
+
change a computed length. For a repeated part already in a group, expose the
|
|
426
|
+
intended occurrence and measure that reference.
|
|
427
|
+
|
|
428
|
+
Place the cursor anywhere inside a `distance(...)` call to inspect the measurement
|
|
429
|
+
in the viewport. Both measured objects are emphasized against dimmed related
|
|
430
|
+
models, with a distance line and numeric label. Whole solids and groups retain
|
|
431
|
+
their model appearance instead of receiving a face-selection overlay. The preview uses the solved
|
|
432
|
+
positions at that call, even before a `group` exists. A projected measurement is
|
|
433
|
+
marked with its axis: the line spans the projection intervals, so its endpoints
|
|
434
|
+
need not lie on the selected geometry. The line is placed within the shared
|
|
435
|
+
transverse bounds when possible: for a point inside a face’s projection, it starts
|
|
436
|
+
at the point and reaches the face along the measurement axis. Overlapping
|
|
437
|
+
intervals on the measurement axis show zero.
|
|
438
|
+
|
|
439
|
+
Inside the call, selecting a model variable emphasizes that model and dims the
|
|
440
|
+
other whole-model operand. Selecting an
|
|
441
|
+
element reference emphasizes that element while the other measured element stays
|
|
442
|
+
visible at secondary emphasis. An explicitly selected bound also shows its normal
|
|
443
|
+
direction; other measured bounds keep only their face and corner markers. The
|
|
444
|
+
measurement line stays visible as you move between arguments.
|
|
445
|
+
|
|
446
|
+
Measurements use a gray dashed line with short ticks at both ends and a neutral
|
|
447
|
+
numeric label. The X, Y, or Z letter uses the matching viewport axis color; custom
|
|
448
|
+
directions keep a neutral `axis` label. Dash spacing, endpoint ticks, and text
|
|
449
|
+
keep their screen size as you zoom and are included in annotated image exports. This preview is passive; measurement
|
|
450
|
+
parameter controls and element-picking tools are not yet available.
|