fluidcad 0.0.36 → 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/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 +10 -0
- package/server/dist/fluidcad-server.js +10 -0
- package/server/dist/index.js +4 -2
- 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
|
@@ -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
|
|
@@ -139,6 +139,9 @@ export class ExtrudeToFace extends ExtrudeBase {
|
|
|
139
139
|
if (surfaceType === 'cylinder') {
|
|
140
140
|
splitTargetFace = this.resizeCylindricalFace(targetFace);
|
|
141
141
|
}
|
|
142
|
+
else if (surfaceType === 'cone') {
|
|
143
|
+
splitTargetFace = this.resizeConicalFace(targetFace);
|
|
144
|
+
}
|
|
142
145
|
else {
|
|
143
146
|
splitTargetFace = targetFace;
|
|
144
147
|
}
|
|
@@ -157,6 +160,9 @@ export class ExtrudeToFace extends ExtrudeBase {
|
|
|
157
160
|
resizeCylindricalFace(targetFace) {
|
|
158
161
|
return FaceQuery.makeInfiniteCylindricalFace(targetFace, this.getEndOffset());
|
|
159
162
|
}
|
|
163
|
+
resizeConicalFace(targetFace) {
|
|
164
|
+
return FaceQuery.makeInfiniteConicalFace(targetFace, this.getEndOffset());
|
|
165
|
+
}
|
|
160
166
|
/**
|
|
161
167
|
* Computes the signed distance from the sketch plane to the farthest
|
|
162
168
|
* bounding-box corner of the target face, measured along the sketch
|
|
@@ -8,7 +8,7 @@ export declare class Fillet extends SceneObject {
|
|
|
8
8
|
validate(): void;
|
|
9
9
|
build(context: BuildSceneObjectContext): void;
|
|
10
10
|
doBuild(sceneObjectsMap: Map<SceneObject, Shape[]>, selections: SceneObject[]): {
|
|
11
|
-
addedShapes: Shape<import("
|
|
11
|
+
addedShapes: Shape<import("ocjs-fluidcad").TopoDS_Shape>[];
|
|
12
12
|
removedShapes: {
|
|
13
13
|
shape: Shape;
|
|
14
14
|
owner: SceneObject;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { BuildSceneObjectContext, SceneObject } from "../common/scene-object.js";
|
|
2
|
+
import { AxisObjectBase } from "./axis-renderable-base.js";
|
|
3
|
+
import { IHelix } from "../core/interfaces.js";
|
|
4
|
+
export declare class Helix extends SceneObject implements IHelix {
|
|
5
|
+
source: AxisObjectBase | SceneObject;
|
|
6
|
+
private _pitch?;
|
|
7
|
+
private _turns?;
|
|
8
|
+
private _startOffset;
|
|
9
|
+
private _endOffset;
|
|
10
|
+
private _height?;
|
|
11
|
+
private _radius?;
|
|
12
|
+
private _endRadius?;
|
|
13
|
+
constructor(source: AxisObjectBase | SceneObject);
|
|
14
|
+
pitch(value: number): this;
|
|
15
|
+
turns(value: number): this;
|
|
16
|
+
startOffset(value: number): this;
|
|
17
|
+
endOffset(value: number): this;
|
|
18
|
+
height(value: number): this;
|
|
19
|
+
radius(value: number): this;
|
|
20
|
+
endRadius(value: number): this;
|
|
21
|
+
validate(): void;
|
|
22
|
+
build(_context?: BuildSceneObjectContext): void;
|
|
23
|
+
private deriveTurnsFromHeight;
|
|
24
|
+
private resolveSource;
|
|
25
|
+
private resolveFace;
|
|
26
|
+
private resolveEdge;
|
|
27
|
+
getType(): string;
|
|
28
|
+
getDependencies(): SceneObject[];
|
|
29
|
+
createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
|
|
30
|
+
compareTo(other: SceneObject): boolean;
|
|
31
|
+
serialize(): {
|
|
32
|
+
source: any;
|
|
33
|
+
pitch: number;
|
|
34
|
+
turns: number;
|
|
35
|
+
startOffset: number;
|
|
36
|
+
endOffset: number;
|
|
37
|
+
height: number;
|
|
38
|
+
radius: number;
|
|
39
|
+
endRadius: number;
|
|
40
|
+
};
|
|
41
|
+
}
|