fluidcad 0.0.35 → 0.0.37
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/LICENSE.txt +21 -504
- package/README.md +1 -1
- package/bin/commands/login.js +33 -5
- package/bin/commands/mcp.js +3 -2
- package/bin/commands/publish.js +103 -8
- package/bin/lib/api-client.js +8 -0
- package/bin/lib/model-config.js +27 -4
- package/bin/lib/prompt.js +97 -0
- package/lib/dist/common/edge.d.ts +1 -1
- package/lib/dist/common/face.d.ts +1 -1
- package/lib/dist/common/scene-object.d.ts +6 -0
- package/lib/dist/common/scene-object.js +8 -0
- package/lib/dist/common/shape-factory.d.ts +1 -1
- package/lib/dist/common/shape-history-tracker.d.ts +1 -1
- package/lib/dist/common/shape.d.ts +1 -1
- package/lib/dist/common/solid.d.ts +1 -1
- package/lib/dist/common/transformable-primitive.d.ts +12 -1
- package/lib/dist/common/transformable-primitive.js +27 -0
- package/lib/dist/common/vertex.d.ts +1 -1
- package/lib/dist/common/wire.d.ts +1 -1
- package/lib/dist/core/2d/index.d.ts +1 -0
- package/lib/dist/core/2d/index.js +1 -0
- package/lib/dist/core/2d/text.d.ts +30 -0
- package/lib/dist/core/2d/text.js +37 -0
- package/lib/dist/core/helix.d.ts +20 -0
- package/lib/dist/core/helix.js +36 -0
- package/lib/dist/core/index.d.ts +3 -1
- package/lib/dist/core/index.js +2 -0
- package/lib/dist/core/interfaces.d.ts +180 -0
- package/lib/dist/core/wrap.d.ts +17 -0
- package/lib/dist/core/wrap.js +39 -0
- package/lib/dist/features/2d/text.d.ts +67 -0
- package/lib/dist/features/2d/text.js +320 -0
- package/lib/dist/features/cylinder.d.ts +3 -1
- package/lib/dist/features/cylinder.js +5 -2
- package/lib/dist/features/extrude-base.d.ts +1 -0
- package/lib/dist/features/extrude-to-face.d.ts +1 -0
- package/lib/dist/features/extrude-to-face.js +6 -0
- package/lib/dist/features/fillet.d.ts +1 -1
- package/lib/dist/features/helix.d.ts +41 -0
- package/lib/dist/features/helix.js +337 -0
- package/lib/dist/features/select.js +32 -8
- package/lib/dist/features/simple-extruder.d.ts +1 -1
- package/lib/dist/features/simple-extruder.js +7 -2
- package/lib/dist/features/sphere.d.ts +3 -1
- package/lib/dist/features/sphere.js +5 -2
- package/lib/dist/features/sweep.js +7 -2
- package/lib/dist/features/wrap.d.ts +39 -0
- package/lib/dist/features/wrap.js +116 -0
- package/lib/dist/filters/edge/belongs-to-face.d.ts +3 -1
- package/lib/dist/filters/edge/belongs-to-face.js +14 -10
- package/lib/dist/filters/filter.d.ts +1 -1
- package/lib/dist/filters/from-object.d.ts +1 -1
- package/lib/dist/filters/tangent-expander.d.ts +1 -1
- package/lib/dist/filters/tangent-expander.js +57 -40
- package/lib/dist/helpers/scene-helpers.d.ts +2 -0
- package/lib/dist/helpers/scene-helpers.js +1 -1
- package/lib/dist/index.d.ts +2 -0
- package/lib/dist/index.js +3 -1
- package/lib/dist/io/file-import.d.ts +7 -0
- package/lib/dist/io/file-import.js +28 -1
- package/lib/dist/io/font-registry.d.ts +45 -0
- package/lib/dist/io/font-registry.js +272 -0
- package/lib/dist/math/bspline-interpolation.d.ts +29 -0
- package/lib/dist/math/bspline-interpolation.js +194 -0
- package/lib/dist/oc/boolean-ops.d.ts +3 -1
- package/lib/dist/oc/boolean-ops.js +15 -1
- package/lib/dist/oc/color-transfer.d.ts +1 -1
- package/lib/dist/oc/constraints/constraint-helpers.d.ts +4 -4
- package/lib/dist/oc/constraints/curve/tangent-circle-solver.js +10 -9
- package/lib/dist/oc/constraints/curve/tangent-line-solver.js +5 -6
- package/lib/dist/oc/convert.d.ts +1 -1
- package/lib/dist/oc/draft-ops.d.ts +1 -1
- package/lib/dist/oc/edge-ops.d.ts +2 -2
- package/lib/dist/oc/edge-ops.js +13 -14
- package/lib/dist/oc/edge-props.d.ts +1 -1
- package/lib/dist/oc/edge-query.d.ts +1 -1
- package/lib/dist/oc/edge-query.js +3 -8
- package/lib/dist/oc/errors.d.ts +8 -0
- package/lib/dist/oc/errors.js +27 -0
- package/lib/dist/oc/explorer.d.ts +2 -2
- package/lib/dist/oc/extrude-ops.d.ts +28 -2
- package/lib/dist/oc/extrude-ops.js +56 -7
- package/lib/dist/oc/face-ops.d.ts +2 -1
- package/lib/dist/oc/face-ops.js +11 -0
- package/lib/dist/oc/face-props.d.ts +1 -1
- package/lib/dist/oc/face-query.d.ts +12 -1
- package/lib/dist/oc/face-query.js +39 -0
- package/lib/dist/oc/fillet-ops.d.ts +1 -1
- package/lib/dist/oc/fillet-ops.js +4 -4
- package/lib/dist/oc/geometry.d.ts +1 -1
- package/lib/dist/oc/geometry.js +12 -14
- package/lib/dist/oc/helix-ops.d.ts +37 -0
- package/lib/dist/oc/helix-ops.js +88 -0
- package/lib/dist/oc/hit-test.d.ts +1 -1
- package/lib/dist/oc/index.d.ts +4 -0
- package/lib/dist/oc/index.js +2 -0
- package/lib/dist/oc/init.d.ts +1 -1
- package/lib/dist/oc/init.js +1 -1
- package/lib/dist/oc/intersection.js +1 -1
- package/lib/dist/oc/io.d.ts +6 -6
- package/lib/dist/oc/io.js +31 -24
- package/lib/dist/oc/measure/classify.d.ts +34 -0
- package/lib/dist/oc/measure/classify.js +246 -0
- package/lib/dist/oc/measure/measure-ops.d.ts +9 -0
- package/lib/dist/oc/measure/measure-ops.js +210 -0
- package/lib/dist/oc/measure/measure-types.d.ts +39 -0
- package/lib/dist/oc/measure/measure-types.js +1 -0
- package/lib/dist/oc/measure/sampling.d.ts +9 -0
- package/lib/dist/oc/measure/sampling.js +77 -0
- package/lib/dist/oc/measure/vec.d.ts +13 -0
- package/lib/dist/oc/measure/vec.js +23 -0
- package/lib/dist/oc/mesh.d.ts +1 -1
- package/lib/dist/oc/mesh.js +40 -28
- package/lib/dist/oc/path-sampler.d.ts +29 -0
- package/lib/dist/oc/path-sampler.js +63 -0
- package/lib/dist/oc/props.d.ts +1 -1
- package/lib/dist/oc/props.js +4 -1
- package/lib/dist/oc/shape-hash.d.ts +26 -0
- package/lib/dist/oc/shape-hash.js +32 -0
- package/lib/dist/oc/shape-ops.d.ts +5 -3
- package/lib/dist/oc/shape-ops.js +6 -5
- package/lib/dist/oc/sweep-ops.d.ts +22 -1
- package/lib/dist/oc/sweep-ops.js +206 -18
- package/lib/dist/oc/text-outline.d.ts +62 -0
- package/lib/dist/oc/text-outline.js +212 -0
- package/lib/dist/oc/topology-index.d.ts +1 -1
- package/lib/dist/oc/vertex-ops.d.ts +1 -1
- package/lib/dist/oc/wire-ops.d.ts +1 -1
- package/lib/dist/oc/wire-ops.js +1 -1
- package/lib/dist/oc/wrap-development.d.ts +105 -0
- package/lib/dist/oc/wrap-development.js +179 -0
- package/lib/dist/oc/wrap-ops.d.ts +100 -0
- package/lib/dist/oc/wrap-ops.js +406 -0
- package/lib/dist/rendering/render-solid.js +10 -2
- package/lib/dist/scene-manager.d.ts +2 -0
- package/lib/dist/scene-manager.js +29 -0
- package/lib/dist/tests/features/cylinder-curve-filter.test.js +3 -3
- package/lib/dist/tests/features/extrude-to-face.test.js +38 -1
- package/lib/dist/tests/features/helix.test.d.ts +1 -0
- package/lib/dist/tests/features/helix.test.js +295 -0
- package/lib/dist/tests/features/repeat-primitive.test.d.ts +1 -0
- package/lib/dist/tests/features/repeat-primitive.test.js +60 -0
- package/lib/dist/tests/features/rib.test.js +6 -1
- package/lib/dist/tests/features/sweep.test.js +125 -1
- package/lib/dist/tests/features/text.test.d.ts +1 -0
- package/lib/dist/tests/features/text.test.js +347 -0
- package/lib/dist/tests/features/wrap-development.test.d.ts +1 -0
- package/lib/dist/tests/features/wrap-development.test.js +130 -0
- package/lib/dist/tests/features/wrap-extruded-target.test.d.ts +1 -0
- package/lib/dist/tests/features/wrap-extruded-target.test.js +106 -0
- package/lib/dist/tests/features/wrap-repeat.test.d.ts +1 -0
- package/lib/dist/tests/features/wrap-repeat.test.js +93 -0
- package/lib/dist/tests/features/wrap.test.d.ts +1 -0
- package/lib/dist/tests/features/wrap.test.js +331 -0
- package/lib/dist/tests/math/bspline-interpolation.test.d.ts +1 -0
- package/lib/dist/tests/math/bspline-interpolation.test.js +119 -0
- package/lib/dist/tests/measure.test.d.ts +1 -0
- package/lib/dist/tests/measure.test.js +288 -0
- package/lib/dist/tsconfig.tsbuildinfo +1 -1
- package/llm-docs/api/helix.md +64 -0
- package/llm-docs/api/index.json +11 -2
- package/llm-docs/api/text.md +52 -0
- package/llm-docs/api/types/helix.md +105 -0
- package/llm-docs/api/types/text.md +138 -0
- package/llm-docs/api/types/wrap.md +131 -0
- package/llm-docs/api/wrap.md +62 -0
- package/llm-docs/index.json +121 -1
- package/mcp/dist/server.js +20 -1
- package/mcp/dist/tools/inspection.d.ts +17 -0
- package/mcp/dist/tools/inspection.js +14 -0
- package/package.json +7 -3
- package/server/dist/fluidcad-server.d.ts +29 -0
- package/server/dist/fluidcad-server.js +40 -0
- package/server/dist/index.js +4 -2
- package/server/dist/model-package/pack.js +7 -6
- package/server/dist/model-package/types.d.ts +4 -3
- package/server/dist/preferences.d.ts +4 -0
- package/server/dist/preferences.js +2 -0
- package/server/dist/routes/measure.d.ts +3 -0
- package/server/dist/routes/measure.js +32 -0
- package/server/dist/routes/preferences.js +6 -0
- package/server/dist/routes/sketch-edits.js +2 -1
- package/ui/dist/assets/{index-CDJmUpFI.css → index-dAFdg2Un.css} +1 -1
- package/ui/dist/assets/{index-MRqwG9Vh.js → index-no7mtr5s.js} +149 -102
- package/ui/dist/index.html +2 -2
|
@@ -144,6 +144,82 @@ export interface IGeometry extends ISceneObject {
|
|
|
144
144
|
}
|
|
145
145
|
export interface IExtrudableGeometry extends IGeometry {
|
|
146
146
|
}
|
|
147
|
+
export interface IText extends IExtrudableGeometry {
|
|
148
|
+
/**
|
|
149
|
+
* Sets the text height (em size) in model units. Default 10.
|
|
150
|
+
* @param value - The em size.
|
|
151
|
+
*/
|
|
152
|
+
size(value: number): this;
|
|
153
|
+
/**
|
|
154
|
+
* Sets the font. A name without a font extension (e.g. `"Arial"`) is resolved
|
|
155
|
+
* to a system font; a value ending in `.ttf`/`.otf`/`.ttc`/`.woff` (e.g.
|
|
156
|
+
* `"fonts/Brand.ttf"`) is loaded as a workspace-relative file. When omitted, a
|
|
157
|
+
* default system font is used.
|
|
158
|
+
* @param name - A system family name or a workspace-relative font file path.
|
|
159
|
+
*/
|
|
160
|
+
font(name: string): this;
|
|
161
|
+
/**
|
|
162
|
+
* Sets the font weight: a number (100–900) or a name such as `"regular"`,
|
|
163
|
+
* `"medium"`, or `"bold"`. Resolves to the matching face (or the wght axis of a
|
|
164
|
+
* variable font).
|
|
165
|
+
* @param value - The weight as a number or name.
|
|
166
|
+
*/
|
|
167
|
+
weight(value: number | string): this;
|
|
168
|
+
/**
|
|
169
|
+
* Shortcut for `weight(700)`.
|
|
170
|
+
*/
|
|
171
|
+
bold(): this;
|
|
172
|
+
/**
|
|
173
|
+
* Renders the italic/oblique face of the font.
|
|
174
|
+
* @param value - Whether to use italic (defaults to true).
|
|
175
|
+
*/
|
|
176
|
+
italic(value?: boolean): this;
|
|
177
|
+
/**
|
|
178
|
+
* Horizontal alignment of the text. For straight text it is relative to the
|
|
179
|
+
* origin point; for text along a path it positions the run against the
|
|
180
|
+
* path: `"start"` begins at the path's start, `"center"` centers on the
|
|
181
|
+
* midpoint, `"end"` finishes at the path's end, `"space-between"` justifies
|
|
182
|
+
* the glyphs evenly across the whole path, and `"space-around"` spreads
|
|
183
|
+
* them with half a gap before the first glyph and after the last, like the
|
|
184
|
+
* CSS flexbox value (both path text only). `"left"` and `"right"` are
|
|
185
|
+
* synonyms of `"start"` and `"end"`.
|
|
186
|
+
* @param value - `"left"`/`"start"` (default), `"center"`,
|
|
187
|
+
* `"right"`/`"end"`, `"space-between"`, or `"space-around"`.
|
|
188
|
+
*/
|
|
189
|
+
align(value: "left" | "center" | "right" | "start" | "end" | "space-between" | "space-around"): this;
|
|
190
|
+
/**
|
|
191
|
+
* Line-height multiplier for multi-line text (newlines in the string).
|
|
192
|
+
* @param value - Multiplier on the font's natural line height (default 1).
|
|
193
|
+
*/
|
|
194
|
+
lineSpacing(value: number): this;
|
|
195
|
+
/**
|
|
196
|
+
* Extra spacing added between glyphs, in model units (default 0).
|
|
197
|
+
* @param value - The additional advance per glyph.
|
|
198
|
+
*/
|
|
199
|
+
letterSpacing(value: number): this;
|
|
200
|
+
/**
|
|
201
|
+
* Shifts the baseline perpendicular to the path, in model units: positive
|
|
202
|
+
* values move the text toward its "up" side, negative below the path.
|
|
203
|
+
* Only applies to text following a path (`text(string, path)`).
|
|
204
|
+
* @param value - The perpendicular baseline shift.
|
|
205
|
+
*/
|
|
206
|
+
offset(value: number): this;
|
|
207
|
+
/**
|
|
208
|
+
* Mirrors the text to the other side of the path, reversing the reading
|
|
209
|
+
* direction. On a closed path (circle, loop) text sits on the outside by
|
|
210
|
+
* default — `.flip()` moves it inside. On an open path it mirrors the text
|
|
211
|
+
* below the curve. Only applies to text following a path.
|
|
212
|
+
* @param value - Whether to flip (defaults to true).
|
|
213
|
+
*/
|
|
214
|
+
flip(value?: boolean): this;
|
|
215
|
+
/**
|
|
216
|
+
* Shifts where the text starts along the path, as an arc-length distance
|
|
217
|
+
* from the path's start (combines with `align()`). On a closed path the
|
|
218
|
+
* text wraps around. Only applies to text following a path.
|
|
219
|
+
* @param distance - The arc-length shift in model units.
|
|
220
|
+
*/
|
|
221
|
+
startAt(distance: number): this;
|
|
222
|
+
}
|
|
147
223
|
export interface IOffset extends IExtrudableGeometry {
|
|
148
224
|
/**
|
|
149
225
|
* Closes an open offset by joining it back to the source wire with
|
|
@@ -794,6 +870,59 @@ export interface IRib extends IBooleanOperation {
|
|
|
794
870
|
*/
|
|
795
871
|
extend(): this;
|
|
796
872
|
}
|
|
873
|
+
export interface IWrap extends IBooleanOperation {
|
|
874
|
+
/**
|
|
875
|
+
* Selects the faces lying on the target surface (the base of the wrap).
|
|
876
|
+
* @param args - Numeric indices or {@link FaceFilterBuilder} instances to filter the selection.
|
|
877
|
+
*/
|
|
878
|
+
startFaces(...args: (number | FaceFilterBuilder)[]): ISceneObject;
|
|
879
|
+
/**
|
|
880
|
+
* Selects the raised (or recessed) faces offset from the target surface by the wrap thickness.
|
|
881
|
+
* @param args - Numeric indices or {@link FaceFilterBuilder} instances to filter the selection.
|
|
882
|
+
*/
|
|
883
|
+
endFaces(...args: (number | FaceFilterBuilder)[]): ISceneObject;
|
|
884
|
+
/**
|
|
885
|
+
* Selects edges on the base faces of the wrap.
|
|
886
|
+
* @param args - Numeric indices or {@link EdgeFilterBuilder} instances to filter the selection.
|
|
887
|
+
*/
|
|
888
|
+
startEdges(...args: (number | EdgeFilterBuilder)[]): ISceneObject;
|
|
889
|
+
/**
|
|
890
|
+
* Selects edges on the offset faces of the wrap.
|
|
891
|
+
* @param args - Numeric indices or {@link EdgeFilterBuilder} instances to filter the selection.
|
|
892
|
+
*/
|
|
893
|
+
endEdges(...args: (number | EdgeFilterBuilder)[]): ISceneObject;
|
|
894
|
+
/**
|
|
895
|
+
* Selects the wall faces created from the outer boundary of each wrapped region.
|
|
896
|
+
* @param args - Numeric indices or {@link FaceFilterBuilder} instances to filter the selection.
|
|
897
|
+
*/
|
|
898
|
+
sideFaces(...args: (number | FaceFilterBuilder)[]): ISceneObject;
|
|
899
|
+
/**
|
|
900
|
+
* Selects edges on the wall faces, excluding edges shared with base/offset faces.
|
|
901
|
+
* @param args - Numeric indices or {@link EdgeFilterBuilder} instances to filter the selection.
|
|
902
|
+
*/
|
|
903
|
+
sideEdges(...args: (number | EdgeFilterBuilder)[]): ISceneObject;
|
|
904
|
+
/**
|
|
905
|
+
* Selects the wall faces created from holes inside a wrapped region.
|
|
906
|
+
* @param args - Numeric indices or {@link FaceFilterBuilder} instances to filter the selection.
|
|
907
|
+
*/
|
|
908
|
+
internalFaces(...args: (number | FaceFilterBuilder)[]): ISceneObject;
|
|
909
|
+
/**
|
|
910
|
+
* Selects edges bounding the hole walls of the wrap.
|
|
911
|
+
* @param args - Numeric indices or {@link EdgeFilterBuilder} instances to filter the selection.
|
|
912
|
+
*/
|
|
913
|
+
internalEdges(...args: (number | EdgeFilterBuilder)[]): ISceneObject;
|
|
914
|
+
/**
|
|
915
|
+
* Enables or disables drill mode, which partitions the sketch into face regions
|
|
916
|
+
* before wrapping.
|
|
917
|
+
* @param value - `true` to enable (default), `false` to disable.
|
|
918
|
+
*/
|
|
919
|
+
drill(value?: boolean): this;
|
|
920
|
+
/**
|
|
921
|
+
* Restricts wrapping to only the sketch regions containing the given points.
|
|
922
|
+
* @param points - 2D points in the sketch plane identifying regions to wrap.
|
|
923
|
+
*/
|
|
924
|
+
pick(...points: Point2DLike[]): this;
|
|
925
|
+
}
|
|
797
926
|
export type ShellJoinType = 'arc' | 'intersection' | 'tangent';
|
|
798
927
|
export interface IShell extends ISceneObject {
|
|
799
928
|
/**
|
|
@@ -814,3 +943,54 @@ export interface IShell extends ISceneObject {
|
|
|
814
943
|
*/
|
|
815
944
|
join(type: ShellJoinType): this;
|
|
816
945
|
}
|
|
946
|
+
/**
|
|
947
|
+
* A 3D helix wire — a single edge that traces a helix curve on a cylindrical or
|
|
948
|
+
* conical surface. Used as a path for `sweep()` to produce springs, threads, and
|
|
949
|
+
* coils.
|
|
950
|
+
*
|
|
951
|
+
* Created from one of:
|
|
952
|
+
* - An axis (`AxisLike`): user supplies geometry via chained config.
|
|
953
|
+
* - A cylindrical or conical face: axis + radii + height derived from the face.
|
|
954
|
+
* - A line edge: axis = the line, height = line length.
|
|
955
|
+
* - A circular edge: axis = circle normal, radius = circle radius.
|
|
956
|
+
*/
|
|
957
|
+
export interface IHelix extends ISceneObject {
|
|
958
|
+
/**
|
|
959
|
+
* Axial rise per turn (distance along the helix axis covered per full revolution).
|
|
960
|
+
* If unset, derived from `height / turns`.
|
|
961
|
+
*/
|
|
962
|
+
pitch(pitch: number): this;
|
|
963
|
+
/**
|
|
964
|
+
* Number of full turns. Fractional values are allowed. Default 1.
|
|
965
|
+
*/
|
|
966
|
+
turns(turns: number): this;
|
|
967
|
+
/**
|
|
968
|
+
* Shifts the start of the helix along its axis, in axial mm. Positive values
|
|
969
|
+
* trim the start (move it toward the end); negative values extend it. Default 0.
|
|
970
|
+
*/
|
|
971
|
+
startOffset(offset: number): this;
|
|
972
|
+
/**
|
|
973
|
+
* Extends (positive) or trims (negative) the helix at its end, in axial mm.
|
|
974
|
+
* Default 0.
|
|
975
|
+
*/
|
|
976
|
+
endOffset(offset: number): this;
|
|
977
|
+
/**
|
|
978
|
+
* Total axial height. Overrides face/edge-derived height when set. For line-edge
|
|
979
|
+
* input, defaults to the line length. For circular-edge / pure-axis input,
|
|
980
|
+
* defaults to 50 if neither this nor `pitch * turns` determine it.
|
|
981
|
+
*/
|
|
982
|
+
height(height: number): this;
|
|
983
|
+
/**
|
|
984
|
+
* Start radius. Defaults to 20 for axis/line-edge input. For a cylindrical
|
|
985
|
+
* face input, defaults to the face's radius and may be overridden (useful for
|
|
986
|
+
* sweep/fuse workflows where the helix tube must overlap the cylinder
|
|
987
|
+
* volumetrically — offset by ~1mm to avoid pure tangency). Ignored on
|
|
988
|
+
* conical face input (radius is derived from face geometry).
|
|
989
|
+
*/
|
|
990
|
+
radius(radius: number): this;
|
|
991
|
+
/**
|
|
992
|
+
* End radius — when different from `radius()`, produces a conical helix.
|
|
993
|
+
* Defaults to `radius()`. Ignored on face/circle inputs.
|
|
994
|
+
*/
|
|
995
|
+
endRadius(radius: number): this;
|
|
996
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { IWrap, ISceneObject } from "./interfaces.js";
|
|
2
|
+
import { type NumberParam } from "./param.js";
|
|
3
|
+
interface WrapFunction {
|
|
4
|
+
/**
|
|
5
|
+
* Wraps the given sketch onto a curved face, raising it from the surface by
|
|
6
|
+
* the given thickness (emboss). Chain `.remove()` to sink it into the
|
|
7
|
+
* surface instead (deboss), or `.new()` to keep the wrapped pad standalone.
|
|
8
|
+
* The sketch is developed onto the surface with its lengths preserved — a
|
|
9
|
+
* true wrap, not a projection. Cylindrical and conical faces are supported.
|
|
10
|
+
* @param thickness - Pad thickness measured along the surface normal (must be positive)
|
|
11
|
+
* @param sketch - The sketch to wrap onto the face
|
|
12
|
+
* @param face - The target face to wrap onto
|
|
13
|
+
*/
|
|
14
|
+
(thickness: NumberParam, sketch: ISceneObject, face: ISceneObject): IWrap;
|
|
15
|
+
}
|
|
16
|
+
declare const _default: WrapFunction;
|
|
17
|
+
export default _default;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { SceneObject } from "../common/scene-object.js";
|
|
2
|
+
import { registerBuilder } from "../index.js";
|
|
3
|
+
import { Wrap } from "../features/wrap.js";
|
|
4
|
+
import { isNumberParam, resolveParam } from "./param.js";
|
|
5
|
+
function isExtrudable(obj) {
|
|
6
|
+
return obj instanceof SceneObject && obj.isExtrudable();
|
|
7
|
+
}
|
|
8
|
+
function build(context) {
|
|
9
|
+
//@ts-ignore
|
|
10
|
+
return function wrap() {
|
|
11
|
+
const args = [...arguments];
|
|
12
|
+
if (args.length !== 3) {
|
|
13
|
+
throw new Error("wrap() expects (thickness, sketch, face).");
|
|
14
|
+
}
|
|
15
|
+
if (!isNumberParam(args[0])) {
|
|
16
|
+
throw new Error("wrap() thickness must be a positive number.");
|
|
17
|
+
}
|
|
18
|
+
const thickness = resolveParam(args[0]);
|
|
19
|
+
if (!(thickness > 0)) {
|
|
20
|
+
throw new Error("wrap() thickness must be a positive number.");
|
|
21
|
+
}
|
|
22
|
+
const source = args[1];
|
|
23
|
+
if (!(source instanceof SceneObject)) {
|
|
24
|
+
throw new Error("wrap() sketch must be a sketch or face-bearing scene object.");
|
|
25
|
+
}
|
|
26
|
+
const face = args[2];
|
|
27
|
+
if (!(face instanceof SceneObject) || isExtrudable(face)) {
|
|
28
|
+
throw new Error("wrap() requires a target face selection as its last argument.");
|
|
29
|
+
}
|
|
30
|
+
if (!isExtrudable(source)) {
|
|
31
|
+
context.addSceneObject(source);
|
|
32
|
+
}
|
|
33
|
+
context.addSceneObject(face);
|
|
34
|
+
const result = new Wrap(thickness, face, source);
|
|
35
|
+
context.addSceneObject(result);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export default registerBuilder(build);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { SceneObject } from "../../common/scene-object.js";
|
|
2
|
+
import { PlaneObjectBase } from "../plane-renderable-base.js";
|
|
3
|
+
import { ExtrudableGeometryBase } from "./extrudable-base.js";
|
|
4
|
+
import { IText } from "../../core/interfaces.js";
|
|
5
|
+
import { type TextAlign } from "../../oc/text-outline.js";
|
|
6
|
+
import { Plane } from "../../math/plane.js";
|
|
7
|
+
/**
|
|
8
|
+
* 3D text as an extrudable outline profile. Glyph outlines are produced via
|
|
9
|
+
* fontkit and converted to sketch edges; extruding the result gives raised or
|
|
10
|
+
* cut lettering. Works standalone on a plane (`text("xy", "Hi")`), inside a
|
|
11
|
+
* `sketch()` (`text("Hi")`), or following a planar curve
|
|
12
|
+
* (`text("Hi", path)`).
|
|
13
|
+
*/
|
|
14
|
+
export declare class Text extends ExtrudableGeometryBase implements IText {
|
|
15
|
+
text: string;
|
|
16
|
+
private path;
|
|
17
|
+
private _size;
|
|
18
|
+
private _font?;
|
|
19
|
+
private _weight;
|
|
20
|
+
private _italic;
|
|
21
|
+
private _align;
|
|
22
|
+
private _lineSpacing;
|
|
23
|
+
private _letterSpacing;
|
|
24
|
+
private _pathOffset;
|
|
25
|
+
private _flip;
|
|
26
|
+
private _startAt;
|
|
27
|
+
private _pathPlane;
|
|
28
|
+
constructor(text: string, targetPlane?: PlaneObjectBase, path?: SceneObject);
|
|
29
|
+
build(): void;
|
|
30
|
+
private buildAlongPath;
|
|
31
|
+
/**
|
|
32
|
+
* The plane the text lies in: the path object's own plane when it has one
|
|
33
|
+
* (sketch, planar primitive), otherwise a plane fitted through the path.
|
|
34
|
+
* Also verifies the path actually is planar.
|
|
35
|
+
*/
|
|
36
|
+
private resolvePathPlane;
|
|
37
|
+
private pathOwnPlane;
|
|
38
|
+
getPlane(): Plane;
|
|
39
|
+
size(value: number): this;
|
|
40
|
+
font(name: string): this;
|
|
41
|
+
weight(value: number | string): this;
|
|
42
|
+
bold(): this;
|
|
43
|
+
italic(value?: boolean): this;
|
|
44
|
+
align(value: TextAlign): this;
|
|
45
|
+
lineSpacing(value: number): this;
|
|
46
|
+
letterSpacing(value: number): this;
|
|
47
|
+
offset(value: number): this;
|
|
48
|
+
flip(value?: boolean): this;
|
|
49
|
+
startAt(distance: number): this;
|
|
50
|
+
getType(): string;
|
|
51
|
+
getDependencies(): SceneObject[];
|
|
52
|
+
createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
|
|
53
|
+
compareTo(other: Text): boolean;
|
|
54
|
+
serialize(): {
|
|
55
|
+
text: string;
|
|
56
|
+
size: number;
|
|
57
|
+
font: string;
|
|
58
|
+
weight: number;
|
|
59
|
+
italic: boolean;
|
|
60
|
+
align: TextAlign;
|
|
61
|
+
lineSpacing: number;
|
|
62
|
+
letterSpacing: number;
|
|
63
|
+
offset: number;
|
|
64
|
+
flip: boolean;
|
|
65
|
+
startAt: number;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import { Sketch } from "./sketch.js";
|
|
2
|
+
import { ExtrudableGeometryBase } from "./extrudable-base.js";
|
|
3
|
+
import { FontRegistry } from "../../io/font-registry.js";
|
|
4
|
+
import { TextOutline } from "../../oc/text-outline.js";
|
|
5
|
+
import { PathSampler } from "../../oc/path-sampler.js";
|
|
6
|
+
import { WireOps } from "../../oc/wire-ops.js";
|
|
7
|
+
import { BuildError } from "../../common/build-error.js";
|
|
8
|
+
import { GeometrySceneObject } from "./geometry.js";
|
|
9
|
+
import { Plane } from "../../math/plane.js";
|
|
10
|
+
import { Point } from "../../math/point.js";
|
|
11
|
+
import { Vector3d } from "../../math/vector3d.js";
|
|
12
|
+
const WEIGHT_NAMES = {
|
|
13
|
+
thin: 100, extralight: 200, ultralight: 200, light: 300, regular: 400,
|
|
14
|
+
normal: 400, medium: 500, semibold: 600, demibold: 600, bold: 700,
|
|
15
|
+
extrabold: 800, ultrabold: 800, black: 900, heavy: 900,
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Fits a plane through sampled path points (Newell-style accumulation of
|
|
19
|
+
* cross products around the centroid). Returns null when the points are
|
|
20
|
+
* colinear — a straight path carries no orientation of its own.
|
|
21
|
+
*/
|
|
22
|
+
function fitPathPlane(samples, startTangent, pathLength) {
|
|
23
|
+
const n = samples.length;
|
|
24
|
+
let cx = 0, cy = 0, cz = 0;
|
|
25
|
+
for (const p of samples) {
|
|
26
|
+
cx += p.x;
|
|
27
|
+
cy += p.y;
|
|
28
|
+
cz += p.z;
|
|
29
|
+
}
|
|
30
|
+
const centroid = new Point(cx / n, cy / n, cz / n);
|
|
31
|
+
let nx = 0, ny = 0, nz = 0;
|
|
32
|
+
for (let i = 0; i + 1 < n; i++) {
|
|
33
|
+
const a = centroid.vectorTo(samples[i]);
|
|
34
|
+
const b = centroid.vectorTo(samples[i + 1]);
|
|
35
|
+
const cross = a.cross(b);
|
|
36
|
+
nx += cross.x;
|
|
37
|
+
ny += cross.y;
|
|
38
|
+
nz += cross.z;
|
|
39
|
+
}
|
|
40
|
+
const mag = Math.hypot(nx, ny, nz);
|
|
41
|
+
if (mag < 1e-9 * pathLength * pathLength) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
const normal = new Vector3d(nx / mag, ny / mag, nz / mag);
|
|
45
|
+
const xDirection = startTangent
|
|
46
|
+
.subtract(normal.multiply(startTangent.dot(normal)))
|
|
47
|
+
.normalize();
|
|
48
|
+
return new Plane(samples[0], xDirection, normal);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* 3D text as an extrudable outline profile. Glyph outlines are produced via
|
|
52
|
+
* fontkit and converted to sketch edges; extruding the result gives raised or
|
|
53
|
+
* cut lettering. Works standalone on a plane (`text("xy", "Hi")`), inside a
|
|
54
|
+
* `sketch()` (`text("Hi")`), or following a planar curve
|
|
55
|
+
* (`text("Hi", path)`).
|
|
56
|
+
*/
|
|
57
|
+
export class Text extends ExtrudableGeometryBase {
|
|
58
|
+
text;
|
|
59
|
+
path;
|
|
60
|
+
_size = 10;
|
|
61
|
+
_font;
|
|
62
|
+
_weight = 400;
|
|
63
|
+
_italic = false;
|
|
64
|
+
_align = "left";
|
|
65
|
+
_lineSpacing = 1;
|
|
66
|
+
_letterSpacing = 0;
|
|
67
|
+
_pathOffset = 0;
|
|
68
|
+
_flip = false;
|
|
69
|
+
_startAt = 0;
|
|
70
|
+
_pathPlane = null;
|
|
71
|
+
constructor(text, targetPlane = null, path = null) {
|
|
72
|
+
super(targetPlane);
|
|
73
|
+
this.text = text;
|
|
74
|
+
this.path = path;
|
|
75
|
+
}
|
|
76
|
+
build() {
|
|
77
|
+
if (this.path) {
|
|
78
|
+
this.buildAlongPath();
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (this._pathOffset !== 0 || this._flip || this._startAt !== 0) {
|
|
82
|
+
throw new BuildError("text: .offset(), .flip() and .startAt() only apply to text following a path.", "Use the text(string, path) form, or remove these modifiers.");
|
|
83
|
+
}
|
|
84
|
+
if (this._align === "space-between" || this._align === "space-around") {
|
|
85
|
+
throw new BuildError(`text: align('${this._align}') only applies to text following a path.`, "Use the text(string, path) form, or pick left/center/right.");
|
|
86
|
+
}
|
|
87
|
+
const plane = this.targetPlane
|
|
88
|
+
? this.targetPlane.getPlane()
|
|
89
|
+
: this.getParent().getPlane();
|
|
90
|
+
const origin = this.targetPlane
|
|
91
|
+
? plane.worldToLocal(this.targetPlane.getPlaneCenter())
|
|
92
|
+
: this.getCurrentPosition();
|
|
93
|
+
const font = FontRegistry.resolve({ font: this._font, weight: this._weight, italic: this._italic });
|
|
94
|
+
const edges = TextOutline.buildEdges(font, this.text, {
|
|
95
|
+
size: this._size,
|
|
96
|
+
align: this._align,
|
|
97
|
+
lineSpacing: this._lineSpacing,
|
|
98
|
+
letterSpacing: this._letterSpacing,
|
|
99
|
+
}, plane, origin);
|
|
100
|
+
this.addShapes(edges);
|
|
101
|
+
if (this.targetPlane) {
|
|
102
|
+
this.targetPlane.removeShapes(this);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
buildAlongPath() {
|
|
106
|
+
// Guide curves are included: marking the path `.guide()` is the natural
|
|
107
|
+
// way to keep it out of the sketch profile while text follows it.
|
|
108
|
+
const shapes = this.path.getShapes({ excludeMeta: false, excludeGuide: false });
|
|
109
|
+
const pathEdges = shapes.flatMap(s => s.getSubShapes('edge'));
|
|
110
|
+
if (pathEdges.length === 0) {
|
|
111
|
+
throw new BuildError("text: path contains no edges.");
|
|
112
|
+
}
|
|
113
|
+
const wire = WireOps.makeWireFromEdges(pathEdges);
|
|
114
|
+
const sampler = new PathSampler(wire);
|
|
115
|
+
try {
|
|
116
|
+
const plane = this.resolvePathPlane(sampler);
|
|
117
|
+
this._pathPlane = plane;
|
|
118
|
+
// On a closed loop, normalize the (arbitrary) wire winding so text
|
|
119
|
+
// sits on the OUTSIDE by default; `.flip()` then moves it inside.
|
|
120
|
+
// A clockwise loop (w.r.t. the plane normal) already has its glyph
|
|
121
|
+
// "up" (normal × tangent) pointing outward.
|
|
122
|
+
let flip = this._flip;
|
|
123
|
+
if (sampler.closed && !WireOps.isCW(wire, plane.normal)) {
|
|
124
|
+
flip = !flip;
|
|
125
|
+
}
|
|
126
|
+
const font = FontRegistry.resolve({ font: this._font, weight: this._weight, italic: this._italic });
|
|
127
|
+
const edges = TextOutline.buildEdgesAlongPath(font, this.text, {
|
|
128
|
+
size: this._size,
|
|
129
|
+
align: this._align,
|
|
130
|
+
lineSpacing: this._lineSpacing,
|
|
131
|
+
letterSpacing: this._letterSpacing,
|
|
132
|
+
}, {
|
|
133
|
+
evalAt: (s) => sampler.evalAt(s),
|
|
134
|
+
length: sampler.length,
|
|
135
|
+
normal: plane.normal,
|
|
136
|
+
offset: this._pathOffset,
|
|
137
|
+
startAt: this._startAt,
|
|
138
|
+
flip,
|
|
139
|
+
closed: sampler.closed,
|
|
140
|
+
});
|
|
141
|
+
this.addShapes(edges);
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
sampler.dispose();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* The plane the text lies in: the path object's own plane when it has one
|
|
149
|
+
* (sketch, planar primitive), otherwise a plane fitted through the path.
|
|
150
|
+
* Also verifies the path actually is planar.
|
|
151
|
+
*/
|
|
152
|
+
resolvePathPlane(sampler) {
|
|
153
|
+
const samples = sampler.sample(64);
|
|
154
|
+
let plane = this.pathOwnPlane();
|
|
155
|
+
if (!plane) {
|
|
156
|
+
plane = fitPathPlane(samples, sampler.evalAt(0).tangent, sampler.length);
|
|
157
|
+
}
|
|
158
|
+
if (!plane) {
|
|
159
|
+
throw new BuildError("text: cannot derive the path's orientation — a straight-line path carries no plane of its own.", "Draw the path in a sketch (or use a planar primitive) so the text knows which way is up.");
|
|
160
|
+
}
|
|
161
|
+
const tol = Math.max(1e-5, sampler.length * 1e-6);
|
|
162
|
+
for (const p of samples) {
|
|
163
|
+
if (plane.distanceToPoint(p) > tol) {
|
|
164
|
+
throw new BuildError("text: path must be planar.", "Text can only follow a curve lying in a single plane (e.g. a sketch curve or a planar edge loop).");
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return plane;
|
|
168
|
+
}
|
|
169
|
+
pathOwnPlane() {
|
|
170
|
+
if (this.path instanceof Sketch) {
|
|
171
|
+
return this.path.getPlane();
|
|
172
|
+
}
|
|
173
|
+
if (this.path instanceof ExtrudableGeometryBase) {
|
|
174
|
+
try {
|
|
175
|
+
return this.path.getPlane();
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Plain sketch geometry (arc, line, …) lies in its sketch's plane.
|
|
182
|
+
if (this.path instanceof GeometrySceneObject) {
|
|
183
|
+
const sketch = this.path.sketch;
|
|
184
|
+
return sketch ? sketch.getPlane() : null;
|
|
185
|
+
}
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
getPlane() {
|
|
189
|
+
if (this.path) {
|
|
190
|
+
if (!this._pathPlane) {
|
|
191
|
+
throw new Error("text: the path plane is resolved during build; render the scene first.");
|
|
192
|
+
}
|
|
193
|
+
return this._pathPlane;
|
|
194
|
+
}
|
|
195
|
+
return super.getPlane();
|
|
196
|
+
}
|
|
197
|
+
size(value) {
|
|
198
|
+
this._size = value;
|
|
199
|
+
return this;
|
|
200
|
+
}
|
|
201
|
+
font(name) {
|
|
202
|
+
this._font = name;
|
|
203
|
+
return this;
|
|
204
|
+
}
|
|
205
|
+
weight(value) {
|
|
206
|
+
this._weight = typeof value === "number" ? value : (WEIGHT_NAMES[value.toLowerCase()] ?? 400);
|
|
207
|
+
return this;
|
|
208
|
+
}
|
|
209
|
+
bold() {
|
|
210
|
+
this._weight = 700;
|
|
211
|
+
return this;
|
|
212
|
+
}
|
|
213
|
+
italic(value = true) {
|
|
214
|
+
this._italic = value;
|
|
215
|
+
return this;
|
|
216
|
+
}
|
|
217
|
+
align(value) {
|
|
218
|
+
this._align = value;
|
|
219
|
+
return this;
|
|
220
|
+
}
|
|
221
|
+
lineSpacing(value) {
|
|
222
|
+
this._lineSpacing = value;
|
|
223
|
+
return this;
|
|
224
|
+
}
|
|
225
|
+
letterSpacing(value) {
|
|
226
|
+
this._letterSpacing = value;
|
|
227
|
+
return this;
|
|
228
|
+
}
|
|
229
|
+
offset(value) {
|
|
230
|
+
this._pathOffset = value;
|
|
231
|
+
return this;
|
|
232
|
+
}
|
|
233
|
+
flip(value = true) {
|
|
234
|
+
this._flip = value;
|
|
235
|
+
return this;
|
|
236
|
+
}
|
|
237
|
+
startAt(distance) {
|
|
238
|
+
this._startAt = distance;
|
|
239
|
+
return this;
|
|
240
|
+
}
|
|
241
|
+
getType() {
|
|
242
|
+
return "text";
|
|
243
|
+
}
|
|
244
|
+
getDependencies() {
|
|
245
|
+
const deps = [];
|
|
246
|
+
if (this.targetPlane) {
|
|
247
|
+
deps.push(this.targetPlane);
|
|
248
|
+
}
|
|
249
|
+
if (this.path) {
|
|
250
|
+
deps.push(this.path);
|
|
251
|
+
}
|
|
252
|
+
return deps;
|
|
253
|
+
}
|
|
254
|
+
createCopy(remap) {
|
|
255
|
+
const targetPlane = this.targetPlane
|
|
256
|
+
? (remap.get(this.targetPlane) || this.targetPlane)
|
|
257
|
+
: null;
|
|
258
|
+
const path = this.path
|
|
259
|
+
? (remap.get(this.path) || this.path)
|
|
260
|
+
: null;
|
|
261
|
+
const copy = new Text(this.text, targetPlane, path);
|
|
262
|
+
copy._size = this._size;
|
|
263
|
+
copy._font = this._font;
|
|
264
|
+
copy._weight = this._weight;
|
|
265
|
+
copy._italic = this._italic;
|
|
266
|
+
copy._align = this._align;
|
|
267
|
+
copy._lineSpacing = this._lineSpacing;
|
|
268
|
+
copy._letterSpacing = this._letterSpacing;
|
|
269
|
+
copy._pathOffset = this._pathOffset;
|
|
270
|
+
copy._flip = this._flip;
|
|
271
|
+
copy._startAt = this._startAt;
|
|
272
|
+
return copy;
|
|
273
|
+
}
|
|
274
|
+
compareTo(other) {
|
|
275
|
+
if (!(other instanceof Text)) {
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
if (!super.compareTo(other)) {
|
|
279
|
+
return false;
|
|
280
|
+
}
|
|
281
|
+
if (this.targetPlane?.constructor !== other.targetPlane?.constructor) {
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
if (this.targetPlane && other.targetPlane && !this.targetPlane.compareTo(other.targetPlane)) {
|
|
285
|
+
return false;
|
|
286
|
+
}
|
|
287
|
+
if (this.path?.constructor !== other.path?.constructor) {
|
|
288
|
+
return false;
|
|
289
|
+
}
|
|
290
|
+
if (this.path && other.path && !this.path.compareTo(other.path)) {
|
|
291
|
+
return false;
|
|
292
|
+
}
|
|
293
|
+
return this.text === other.text
|
|
294
|
+
&& this._size === other._size
|
|
295
|
+
&& this._font === other._font
|
|
296
|
+
&& this._weight === other._weight
|
|
297
|
+
&& this._italic === other._italic
|
|
298
|
+
&& this._align === other._align
|
|
299
|
+
&& this._lineSpacing === other._lineSpacing
|
|
300
|
+
&& this._letterSpacing === other._letterSpacing
|
|
301
|
+
&& this._pathOffset === other._pathOffset
|
|
302
|
+
&& this._flip === other._flip
|
|
303
|
+
&& this._startAt === other._startAt;
|
|
304
|
+
}
|
|
305
|
+
serialize() {
|
|
306
|
+
return {
|
|
307
|
+
text: this.text,
|
|
308
|
+
size: this._size,
|
|
309
|
+
font: this._font,
|
|
310
|
+
weight: this._weight,
|
|
311
|
+
italic: this._italic,
|
|
312
|
+
align: this._align,
|
|
313
|
+
lineSpacing: this._lineSpacing,
|
|
314
|
+
letterSpacing: this._letterSpacing,
|
|
315
|
+
offset: this._pathOffset,
|
|
316
|
+
flip: this._flip,
|
|
317
|
+
startAt: this._startAt,
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { TransformablePrimitive } from "../common/transformable-primitive.js";
|
|
2
|
+
import { BuildSceneObjectContext, SceneObject } from "../common/scene-object.js";
|
|
2
3
|
export declare class Cylinder extends TransformablePrimitive {
|
|
3
4
|
radius: number;
|
|
4
5
|
height: number;
|
|
5
6
|
constructor(radius: number, height: number);
|
|
6
|
-
build(): void;
|
|
7
|
+
build(context?: BuildSceneObjectContext): void;
|
|
8
|
+
createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
|
|
7
9
|
compareTo(other: Cylinder): boolean;
|
|
8
10
|
getType(): string;
|
|
9
11
|
serialize(): {
|
|
@@ -8,9 +8,12 @@ export class Cylinder extends TransformablePrimitive {
|
|
|
8
8
|
this.radius = radius;
|
|
9
9
|
this.height = height;
|
|
10
10
|
}
|
|
11
|
-
build() {
|
|
11
|
+
build(context) {
|
|
12
12
|
const cyl = Primitives.makeCylinder(this.radius, this.height);
|
|
13
|
-
this.
|
|
13
|
+
this.addPrimitiveShape(cyl, context);
|
|
14
|
+
}
|
|
15
|
+
createCopy(remap) {
|
|
16
|
+
return new Cylinder(this.radius, this.height).syncPrimitiveWith(this);
|
|
14
17
|
}
|
|
15
18
|
compareTo(other) {
|
|
16
19
|
if (!(other instanceof Cylinder)) {
|
|
@@ -87,6 +87,7 @@ export declare abstract class ExtrudeBase extends SceneObject implements IExtrud
|
|
|
87
87
|
*/
|
|
88
88
|
protected finalizeAndFuse(shapes: Shape[], classified: ClassifiedFaces, context: BuildSceneObjectContext, fuseOpts?: {
|
|
89
89
|
glue?: 'full' | 'shift';
|
|
90
|
+
skipSimplify?: boolean;
|
|
90
91
|
}): void;
|
|
91
92
|
/**
|
|
92
93
|
* One-shot edge classification: derive start/end/side/internal/cap edges
|
|
@@ -11,6 +11,7 @@ export declare class ExtrudeToFace extends ExtrudeBase {
|
|
|
11
11
|
private createAdvancedExtrude;
|
|
12
12
|
private resizePlanarFace;
|
|
13
13
|
private resizeCylindricalFace;
|
|
14
|
+
private resizeConicalFace;
|
|
14
15
|
/**
|
|
15
16
|
* Computes the signed distance from the sketch plane to the farthest
|
|
16
17
|
* bounding-box corner of the target face, measured along the sketch
|