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
package/lib/dist/oc/edge-ops.js
CHANGED
|
@@ -96,9 +96,8 @@ export class EdgeOps {
|
|
|
96
96
|
static edgeMiddlePoint(edge) {
|
|
97
97
|
const oc = getOC();
|
|
98
98
|
const curveAdaptor = new oc.BRepAdaptor_Curve(oc.TopoDS.Edge(edge));
|
|
99
|
-
const
|
|
100
|
-
const
|
|
101
|
-
const midPoint = curve.Value(midParam);
|
|
99
|
+
const midParam = (curveAdaptor.FirstParameter() + curveAdaptor.LastParameter()) / 2.0;
|
|
100
|
+
const midPoint = curveAdaptor.Value(midParam);
|
|
102
101
|
const result = new oc.gp_Pnt(midPoint.X(), midPoint.Y(), midPoint.Z());
|
|
103
102
|
curveAdaptor.delete();
|
|
104
103
|
return result;
|
|
@@ -131,7 +130,7 @@ export class EdgeOps {
|
|
|
131
130
|
const oc = getOC();
|
|
132
131
|
const isReversed = edge.Orientation() === oc.TopAbs_Orientation.TopAbs_REVERSED;
|
|
133
132
|
const curveHandle = oc.BRep_Tool.Curve(edge, 0, 1);
|
|
134
|
-
const curve = curveHandle.
|
|
133
|
+
const curve = curveHandle.returnValue;
|
|
135
134
|
const param = isReversed ? curve.FirstParameter() : curve.LastParameter();
|
|
136
135
|
const edgeSign = isReversed ? -1 : 1;
|
|
137
136
|
const tangentVec = new oc.gp_Vec();
|
|
@@ -143,11 +142,11 @@ export class EdgeOps {
|
|
|
143
142
|
}
|
|
144
143
|
static makeEdgeFromCurveAndVerticesRaw(curve, v1, v2) {
|
|
145
144
|
const oc = getOC();
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
// Handles are unwrapped in V8: pass the Geom_Curve straight to MakeEdge
|
|
146
|
+
// (constructing the abstract oc.Geom_Curve base throws at runtime).
|
|
147
|
+
const edgeMaker = new oc.BRepBuilderAPI_MakeEdge(curve, v1, v2);
|
|
148
148
|
const edge = edgeMaker.Edge();
|
|
149
149
|
edgeMaker.delete();
|
|
150
|
-
handle.delete();
|
|
151
150
|
return edge;
|
|
152
151
|
}
|
|
153
152
|
static splitEdges(edges) {
|
|
@@ -233,17 +232,17 @@ export class EdgeOps {
|
|
|
233
232
|
sourceIndex.push(srcIdx);
|
|
234
233
|
continue;
|
|
235
234
|
}
|
|
236
|
-
// Get the underlying curve for creating sub-edges
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
const
|
|
235
|
+
// Get the underlying curve for creating sub-edges. Handles are unwrapped in
|
|
236
|
+
// V8 — use the returned Geom_Curve directly (the abstract oc.Geom_Curve base
|
|
237
|
+
// has no constructor).
|
|
238
|
+
const geomCurve = oc.BRep_Tool.Curve(edge, 0, 1).returnValue;
|
|
240
239
|
if (isClosed && interior.length >= 2) {
|
|
241
240
|
// Closed curve: N split points → N arcs (no seam split)
|
|
242
241
|
const period = last - first;
|
|
243
242
|
for (let k = 0; k < interior.length; k++) {
|
|
244
243
|
const u1 = interior[k];
|
|
245
244
|
const u2 = k < interior.length - 1 ? interior[k + 1] : interior[0] + period;
|
|
246
|
-
const maker = new oc.BRepBuilderAPI_MakeEdge(
|
|
245
|
+
const maker = new oc.BRepBuilderAPI_MakeEdge(geomCurve, u1, u2);
|
|
247
246
|
if (maker.IsDone()) {
|
|
248
247
|
result.push(Edge.fromTopoDSEdge(maker.Edge()));
|
|
249
248
|
sourceIndex.push(srcIdx);
|
|
@@ -255,7 +254,7 @@ export class EdgeOps {
|
|
|
255
254
|
// Open curve: include edge endpoints as boundaries
|
|
256
255
|
const allParams = [first, ...interior, last];
|
|
257
256
|
for (let k = 0; k < allParams.length - 1; k++) {
|
|
258
|
-
const maker = new oc.BRepBuilderAPI_MakeEdge(
|
|
257
|
+
const maker = new oc.BRepBuilderAPI_MakeEdge(geomCurve, allParams[k], allParams[k + 1]);
|
|
259
258
|
if (maker.IsDone()) {
|
|
260
259
|
result.push(Edge.fromTopoDSEdge(maker.Edge()));
|
|
261
260
|
sourceIndex.push(srcIdx);
|
|
@@ -268,7 +267,7 @@ export class EdgeOps {
|
|
|
268
267
|
result.push(Edge.fromTopoDSEdge(edge));
|
|
269
268
|
sourceIndex.push(srcIdx);
|
|
270
269
|
}
|
|
271
|
-
|
|
270
|
+
geomCurve.delete();
|
|
272
271
|
}
|
|
273
272
|
return { edges: result, sourceIndex };
|
|
274
273
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { gp_Pln, gp_Vec, TopoDS_Edge, TopoDS_Face, TopoDS_Shape } from "
|
|
1
|
+
import type { gp_Pln, gp_Vec, TopoDS_Edge, TopoDS_Face, TopoDS_Shape } from "ocjs-fluidcad";
|
|
2
2
|
import { Point } from "../math/point.js";
|
|
3
3
|
import { Vector3d } from "../math/vector3d.js";
|
|
4
4
|
import { Plane } from "../math/plane.js";
|
|
@@ -148,17 +148,12 @@ export class EdgeQuery {
|
|
|
148
148
|
const oc = getOC();
|
|
149
149
|
const ocEdge = oc.TopoDS.Edge(edge);
|
|
150
150
|
const adaptor = new oc.BRepAdaptor_Curve(ocEdge);
|
|
151
|
-
const
|
|
152
|
-
|
|
153
|
-
adaptor.delete();
|
|
154
|
-
return false;
|
|
155
|
-
}
|
|
156
|
-
const firstParam = curve.FirstParameter();
|
|
157
|
-
const lastParam = curve.LastParameter();
|
|
151
|
+
const firstParam = adaptor.FirstParameter();
|
|
152
|
+
const lastParam = adaptor.LastParameter();
|
|
158
153
|
const midParam = (firstParam + lastParam) / 2;
|
|
159
154
|
const tangent = new oc.gp_Vec();
|
|
160
155
|
const tempPnt = new oc.gp_Pnt();
|
|
161
|
-
|
|
156
|
+
adaptor.D1(midParam, tempPnt, tangent);
|
|
162
157
|
const dotProduct = Math.abs(tangent.Dot(planeNormal));
|
|
163
158
|
const tolerance = 1e-6;
|
|
164
159
|
const result = dotProduct < tolerance;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ocjs v3 / OCCT V8 raises C++ failures as native `WebAssembly.Exception`
|
|
3
|
+
* objects. Their default stringification is the opaque
|
|
4
|
+
* `[object WebAssembly.Exception]`, so decode the OCCT failure type + message
|
|
5
|
+
* via the module's `getExceptionMessage`. Ordinary JS errors pass through with
|
|
6
|
+
* their stack/message.
|
|
7
|
+
*/
|
|
8
|
+
export declare function describeOcException(e: unknown): string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getOC } from "./init.js";
|
|
2
|
+
/**
|
|
3
|
+
* ocjs v3 / OCCT V8 raises C++ failures as native `WebAssembly.Exception`
|
|
4
|
+
* objects. Their default stringification is the opaque
|
|
5
|
+
* `[object WebAssembly.Exception]`, so decode the OCCT failure type + message
|
|
6
|
+
* via the module's `getExceptionMessage`. Ordinary JS errors pass through with
|
|
7
|
+
* their stack/message.
|
|
8
|
+
*/
|
|
9
|
+
export function describeOcException(e) {
|
|
10
|
+
if (isWasmException(e)) {
|
|
11
|
+
try {
|
|
12
|
+
const [type, message] = getOC().getExceptionMessage(e);
|
|
13
|
+
return `${type}: ${message}`;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return "WebAssembly.Exception (failed to decode OCCT message)";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
if (e instanceof Error) {
|
|
20
|
+
return e.stack ?? e.message;
|
|
21
|
+
}
|
|
22
|
+
return String(e);
|
|
23
|
+
}
|
|
24
|
+
function isWasmException(e) {
|
|
25
|
+
const ctor = globalThis.WebAssembly?.Exception;
|
|
26
|
+
return typeof ctor === "function" && e instanceof ctor;
|
|
27
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TopAbs_ShapeEnum, TopoDS_Compound, TopoDS_Edge, TopoDS_Face, TopoDS_Shape, TopoDS_Solid, TopoDS_Wire, TopoDS_Vertex } from "
|
|
1
|
+
import type { TopAbs_ShapeEnum, TopoDS_Compound, TopoDS_Edge, TopoDS_Face, TopoDS_Shape, TopoDS_Solid, TopoDS_Wire, TopoDS_Vertex } from "ocjs-fluidcad";
|
|
2
2
|
import { Shape } from "../common/shape.js";
|
|
3
3
|
import { Face } from "../common/face.js";
|
|
4
4
|
import { Edge } from "../common/edge.js";
|
|
@@ -18,7 +18,7 @@ export declare class Explorer {
|
|
|
18
18
|
static findShapes<T = TopoDS_Shape>(shape: TopoDS_Shape, lookFor: TopAbs_ShapeEnum): T[];
|
|
19
19
|
static findFirstShapeOfType<T = TopoDS_Shape>(shape: TopoDS_Shape, lookFor: TopAbs_ShapeEnum): T | null;
|
|
20
20
|
static findAllShapes(shape: TopoDS_Compound): any[];
|
|
21
|
-
static getOcShapeType(type: string):
|
|
21
|
+
static getOcShapeType(type: string): "TopAbs_SOLID" | "TopAbs_FACE" | "TopAbs_WIRE" | "TopAbs_EDGE" | "TopAbs_VERTEX";
|
|
22
22
|
static toSolid(shape: TopoDS_Shape): TopoDS_Solid;
|
|
23
23
|
static toFace(shape: TopoDS_Shape): TopoDS_Face;
|
|
24
24
|
static toWire(shape: TopoDS_Shape): TopoDS_Wire;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { TopoDS_Shape } from "
|
|
1
|
+
import type { TopoDS_Shape } from "ocjs-fluidcad";
|
|
2
2
|
import { Vector3d } from "../math/vector3d.js";
|
|
3
3
|
import { Plane } from "../math/plane.js";
|
|
4
4
|
import { Axis } from "../math/axis.js";
|
|
@@ -22,11 +22,37 @@ export interface MakeRevolResult {
|
|
|
22
22
|
}
|
|
23
23
|
export declare class ExtrudeOps {
|
|
24
24
|
static makePrism(shape: Shape, direction: Vector3d, distance: number): Shape;
|
|
25
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Build a prism by sweeping `shape` along `vec`. `firstFace` is the cap at the
|
|
27
|
+
* profile location, `lastFace` the cap at `profile + vec`.
|
|
28
|
+
*
|
|
29
|
+
* When `canonicalizeSweep` is set, the sweep is reoriented to a canonical
|
|
30
|
+
* direction (see below). The swept lateral surfaces (cylinders, cones from a
|
|
31
|
+
* non-drafted profile) take their axis/parametrization from the sweep
|
|
32
|
+
* direction, and OCCT 8's `ShapeUpgrade_UnifySameDomain` refuses to merge two
|
|
33
|
+
* such faces swept in opposite directions. So a symmetric extrude (one half
|
|
34
|
+
* up, one half down) otherwise fuses into a solid whose lateral surface stays
|
|
35
|
+
* split at the mid-plane. Canonicalizing makes anti-parallel extrudes share
|
|
36
|
+
* parametrization so the fused result merges cleanly.
|
|
37
|
+
*
|
|
38
|
+
* This must stay OFF for drafted extrudes: `BRepOffsetAPI_DraftAngle` tilts
|
|
39
|
+
* each side face relative to its own parametrization, so flipping the sweep
|
|
40
|
+
* would invert the draft. Drafted halves are cones of differing half-angle
|
|
41
|
+
* anyway and are not expected to merge across the mid-plane.
|
|
42
|
+
*/
|
|
43
|
+
static makePrismFromVec(shape: Shape, vec: Vector3d, canonicalizeSweep?: boolean): {
|
|
26
44
|
solid: Shape;
|
|
27
45
|
firstFace: Shape;
|
|
28
46
|
lastFace: Shape;
|
|
29
47
|
};
|
|
48
|
+
/**
|
|
49
|
+
* Whether a sweep vector points into the canonical hemisphere (dominant
|
|
50
|
+
* component positive). Anti-parallel vectors map to opposite results, so a
|
|
51
|
+
* `v` / `-v` pair always agree on a single canonical sweep direction — which
|
|
52
|
+
* is what keeps their swept surfaces mergeable. `>=` ties pick the same axis
|
|
53
|
+
* for `v` and `-v`.
|
|
54
|
+
*/
|
|
55
|
+
private static isCanonicalSweep;
|
|
30
56
|
static makePrismInfinite(shape: Shape, direction: Vector3d): Shape;
|
|
31
57
|
static makePrismSymmetric(shape: Shape, direction: Vector3d): Shape;
|
|
32
58
|
static makeRevol(shape: Shape, axis: Axis, angle: number): MakeRevolResult;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getOC } from "./init.js";
|
|
2
2
|
import { Convert } from "./convert.js";
|
|
3
|
+
import { Matrix4 } from "../math/matrix4.js";
|
|
3
4
|
import { Explorer } from "./explorer.js";
|
|
4
5
|
import { Face } from "../common/face.js";
|
|
5
6
|
import { ShapeFactory } from "../common/shape-factory.js";
|
|
@@ -14,26 +15,74 @@ export class ExtrudeOps {
|
|
|
14
15
|
disposeVec();
|
|
15
16
|
return ShapeFactory.fromShape(result);
|
|
16
17
|
}
|
|
17
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Build a prism by sweeping `shape` along `vec`. `firstFace` is the cap at the
|
|
20
|
+
* profile location, `lastFace` the cap at `profile + vec`.
|
|
21
|
+
*
|
|
22
|
+
* When `canonicalizeSweep` is set, the sweep is reoriented to a canonical
|
|
23
|
+
* direction (see below). The swept lateral surfaces (cylinders, cones from a
|
|
24
|
+
* non-drafted profile) take their axis/parametrization from the sweep
|
|
25
|
+
* direction, and OCCT 8's `ShapeUpgrade_UnifySameDomain` refuses to merge two
|
|
26
|
+
* such faces swept in opposite directions. So a symmetric extrude (one half
|
|
27
|
+
* up, one half down) otherwise fuses into a solid whose lateral surface stays
|
|
28
|
+
* split at the mid-plane. Canonicalizing makes anti-parallel extrudes share
|
|
29
|
+
* parametrization so the fused result merges cleanly.
|
|
30
|
+
*
|
|
31
|
+
* This must stay OFF for drafted extrudes: `BRepOffsetAPI_DraftAngle` tilts
|
|
32
|
+
* each side face relative to its own parametrization, so flipping the sweep
|
|
33
|
+
* would invert the draft. Drafted halves are cones of differing half-angle
|
|
34
|
+
* anyway and are not expected to merge across the mid-plane.
|
|
35
|
+
*/
|
|
36
|
+
static makePrismFromVec(shape, vec, canonicalizeSweep = false) {
|
|
18
37
|
const oc = getOC();
|
|
19
|
-
|
|
20
|
-
|
|
38
|
+
// Sweep toward the hemisphere whose dominant component is positive; for a
|
|
39
|
+
// `v` / `-v` pair this resolves to the same direction. When we flip, sweep
|
|
40
|
+
// a copy of the profile translated to the far end, then swap the caps back.
|
|
41
|
+
const flip = canonicalizeSweep && !ExtrudeOps.isCanonicalSweep(vec);
|
|
42
|
+
const sweep = flip ? vec.multiply(-1) : vec;
|
|
43
|
+
const profile = flip
|
|
44
|
+
? ShapeOps.transform(shape, Matrix4.fromTranslationVector(vec))
|
|
45
|
+
: shape;
|
|
46
|
+
const [gpVec, disposeVec] = Convert.toGpVec(sweep);
|
|
47
|
+
const prism = new oc.BRepPrimAPI_MakePrism(profile.getShape(), gpVec, true, true);
|
|
21
48
|
if (!prism.IsDone()) {
|
|
22
49
|
prism.delete();
|
|
23
50
|
disposeVec();
|
|
24
51
|
throw new Error("Extrusion failed");
|
|
25
52
|
}
|
|
26
53
|
const solid = prism.Shape();
|
|
27
|
-
|
|
28
|
-
|
|
54
|
+
// When flipped, the swept profile is the far cap: FirstShape is the far end
|
|
55
|
+
// and LastShape sits at the original profile location — swap them back to
|
|
56
|
+
// preserve the (firstFace = profile, lastFace = far end) contract.
|
|
57
|
+
const first = prism.FirstShape();
|
|
58
|
+
const last = prism.LastShape();
|
|
29
59
|
prism.delete();
|
|
30
60
|
disposeVec();
|
|
31
61
|
return {
|
|
32
62
|
solid: ShapeFactory.fromShape(solid),
|
|
33
|
-
firstFace: ShapeFactory.fromShape(
|
|
34
|
-
lastFace: ShapeFactory.fromShape(
|
|
63
|
+
firstFace: ShapeFactory.fromShape(flip ? last : first),
|
|
64
|
+
lastFace: ShapeFactory.fromShape(flip ? first : last),
|
|
35
65
|
};
|
|
36
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Whether a sweep vector points into the canonical hemisphere (dominant
|
|
69
|
+
* component positive). Anti-parallel vectors map to opposite results, so a
|
|
70
|
+
* `v` / `-v` pair always agree on a single canonical sweep direction — which
|
|
71
|
+
* is what keeps their swept surfaces mergeable. `>=` ties pick the same axis
|
|
72
|
+
* for `v` and `-v`.
|
|
73
|
+
*/
|
|
74
|
+
static isCanonicalSweep(vec) {
|
|
75
|
+
const ax = Math.abs(vec.x);
|
|
76
|
+
const ay = Math.abs(vec.y);
|
|
77
|
+
const az = Math.abs(vec.z);
|
|
78
|
+
if (az >= ax && az >= ay) {
|
|
79
|
+
return vec.z > 0;
|
|
80
|
+
}
|
|
81
|
+
if (ay >= ax) {
|
|
82
|
+
return vec.y > 0;
|
|
83
|
+
}
|
|
84
|
+
return vec.x > 0;
|
|
85
|
+
}
|
|
37
86
|
static makePrismInfinite(shape, direction) {
|
|
38
87
|
const oc = getOC();
|
|
39
88
|
const [vec, disposeVec] = Convert.toGpVec(direction);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { gp_Cylinder, gp_Pln, TopoDS_Face, TopoDS_Wire } from "
|
|
1
|
+
import type { gp_Cone, gp_Cylinder, gp_Pln, TopoDS_Face, TopoDS_Wire } from "ocjs-fluidcad";
|
|
2
2
|
import { Plane } from "../math/plane.js";
|
|
3
3
|
import { Point } from "../math/point.js";
|
|
4
4
|
import { Vector3d } from "../math/vector3d.js";
|
|
@@ -28,5 +28,6 @@ export declare class FaceOps {
|
|
|
28
28
|
}): TopoDS_Face;
|
|
29
29
|
static makeFaceFromPlane(plane: gp_Pln): TopoDS_Face;
|
|
30
30
|
static makeFaceFromCylinder(cylinder: gp_Cylinder): TopoDS_Face;
|
|
31
|
+
static makeFaceFromCone(cone: gp_Cone): TopoDS_Face;
|
|
31
32
|
static planeToFace(plane: Plane, center?: Point): Face;
|
|
32
33
|
}
|
package/lib/dist/oc/face-ops.js
CHANGED
|
@@ -223,6 +223,17 @@ export class FaceOps {
|
|
|
223
223
|
faceMaker.delete();
|
|
224
224
|
return face;
|
|
225
225
|
}
|
|
226
|
+
static makeFaceFromCone(cone) {
|
|
227
|
+
const oc = getOC();
|
|
228
|
+
const faceMaker = new oc.BRepBuilderAPI_MakeFace(cone);
|
|
229
|
+
if (!faceMaker.IsDone()) {
|
|
230
|
+
faceMaker.delete();
|
|
231
|
+
throw new Error("Failed to create face from cone");
|
|
232
|
+
}
|
|
233
|
+
const face = faceMaker.Face();
|
|
234
|
+
faceMaker.delete();
|
|
235
|
+
return face;
|
|
236
|
+
}
|
|
226
237
|
static planeToFace(plane, center) {
|
|
227
238
|
const oc = getOC();
|
|
228
239
|
const size = 100;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { gp_Pln, gp_Cylinder, TopoDS_Shape } from "
|
|
1
|
+
import type { gp_Pln, gp_Cylinder, gp_Cone, TopoDS_Shape } from "ocjs-fluidcad";
|
|
2
2
|
import { Vector3d } from "../math/vector3d.js";
|
|
3
3
|
import { Plane } from "../math/plane.js";
|
|
4
4
|
import { Shape } from "../common/shape.js";
|
|
@@ -20,6 +20,7 @@ export declare class FaceQuery {
|
|
|
20
20
|
static findFarthestCornerDistanceFromFace(targetFace: Shape, sourceFace: Shape): number;
|
|
21
21
|
static makeInfinitePlanarFace(face: Shape, offset?: number, offsetDirection?: Vector3d): Face;
|
|
22
22
|
static makeInfiniteCylindricalFace(face: Shape, offset?: number): Face;
|
|
23
|
+
static makeInfiniteConicalFace(face: Shape, offset?: number): Face;
|
|
23
24
|
static isCircleFaceRaw(face: TopoDS_Shape, diameter?: number): boolean;
|
|
24
25
|
static isConeFaceRaw(face: TopoDS_Shape): boolean;
|
|
25
26
|
static isCylinderFaceRaw(face: TopoDS_Shape, diameter?: number): boolean;
|
|
@@ -31,6 +32,16 @@ export declare class FaceQuery {
|
|
|
31
32
|
static getSurfaceTypeRaw(face: TopoDS_Shape): string;
|
|
32
33
|
static getSurfaceAdaptorPlaneRaw(face: TopoDS_Shape): gp_Pln;
|
|
33
34
|
static getSurfaceAdaptorCylinderRaw(face: TopoDS_Shape): gp_Cylinder;
|
|
35
|
+
static getSurfaceAdaptorConeRaw(face: TopoDS_Shape): gp_Cone;
|
|
36
|
+
/**
|
|
37
|
+
* Returns the parametric V-bounds of `face`'s underlying surface. For a
|
|
38
|
+
* cylindrical surface V is the axial coordinate; for a conical surface V is
|
|
39
|
+
* along the slant (caller multiplies by `cos(semiAngle)` to get axial Z).
|
|
40
|
+
*/
|
|
41
|
+
static getSurfaceVBoundsRaw(face: TopoDS_Shape): {
|
|
42
|
+
vMin: number;
|
|
43
|
+
vMax: number;
|
|
44
|
+
};
|
|
34
45
|
static findFarthestCornerDistanceRaw(face: TopoDS_Shape, plane: gp_Pln): number;
|
|
35
46
|
static arePlanesParallelRaw(plane1: gp_Pln, plane2: gp_Pln): boolean;
|
|
36
47
|
static findFaceByDistance(faces: Face[], plane: Plane, mode: 'first' | 'last'): Face | null;
|
|
@@ -102,6 +102,23 @@ export class FaceQuery {
|
|
|
102
102
|
cylMaker.delete();
|
|
103
103
|
return Face.fromTopoDSFace(rawFace);
|
|
104
104
|
}
|
|
105
|
+
static makeInfiniteConicalFace(face, offset) {
|
|
106
|
+
const cone = FaceQuery.getSurfaceAdaptorConeRaw(face.getShape());
|
|
107
|
+
if (offset) {
|
|
108
|
+
// The parallel surface at normal distance `offset` is the coaxial cone
|
|
109
|
+
// with the same semi-angle and a reference radius enlarged by
|
|
110
|
+
// offset / cos(semiAngle).
|
|
111
|
+
const radius = cone.RefRadius() + offset / Math.cos(cone.SemiAngle());
|
|
112
|
+
if (radius < 0) {
|
|
113
|
+
cone.delete();
|
|
114
|
+
throw new Error("endOffset is too large for the conical target face");
|
|
115
|
+
}
|
|
116
|
+
cone.SetRadius(radius);
|
|
117
|
+
}
|
|
118
|
+
const rawFace = FaceOps.makeFaceFromCone(cone);
|
|
119
|
+
cone.delete();
|
|
120
|
+
return Face.fromTopoDSFace(rawFace);
|
|
121
|
+
}
|
|
105
122
|
// Raw methods (for oc-internal and common/ use)
|
|
106
123
|
static isCircleFaceRaw(face, diameter) {
|
|
107
124
|
const oc = getOC();
|
|
@@ -296,6 +313,28 @@ export class FaceQuery {
|
|
|
296
313
|
adaptor.delete();
|
|
297
314
|
return cylinder;
|
|
298
315
|
}
|
|
316
|
+
static getSurfaceAdaptorConeRaw(face) {
|
|
317
|
+
const oc = getOC();
|
|
318
|
+
const ocFace = oc.TopoDS.Face(face);
|
|
319
|
+
const adaptor = new oc.BRepAdaptor_Surface(ocFace, true);
|
|
320
|
+
const cone = adaptor.Cone();
|
|
321
|
+
adaptor.delete();
|
|
322
|
+
return cone;
|
|
323
|
+
}
|
|
324
|
+
/**
|
|
325
|
+
* Returns the parametric V-bounds of `face`'s underlying surface. For a
|
|
326
|
+
* cylindrical surface V is the axial coordinate; for a conical surface V is
|
|
327
|
+
* along the slant (caller multiplies by `cos(semiAngle)` to get axial Z).
|
|
328
|
+
*/
|
|
329
|
+
static getSurfaceVBoundsRaw(face) {
|
|
330
|
+
const oc = getOC();
|
|
331
|
+
const ocFace = oc.TopoDS.Face(face);
|
|
332
|
+
const adaptor = new oc.BRepAdaptor_Surface(ocFace, true);
|
|
333
|
+
const vMin = adaptor.FirstVParameter();
|
|
334
|
+
const vMax = adaptor.LastVParameter();
|
|
335
|
+
adaptor.delete();
|
|
336
|
+
return { vMin, vMax };
|
|
337
|
+
}
|
|
299
338
|
static findFarthestCornerDistanceRaw(face, plane) {
|
|
300
339
|
const oc = getOC();
|
|
301
340
|
const bbox = new oc.Bnd_Box();
|
|
@@ -105,7 +105,7 @@ export class FilletOps {
|
|
|
105
105
|
const explorer = new oc.BRepTools_WireExplorer(wire);
|
|
106
106
|
while (explorer.More()) {
|
|
107
107
|
const raw = oc.TopoDS.Edge(explorer.Current());
|
|
108
|
-
const isReversed = raw.Orientation()
|
|
108
|
+
const isReversed = raw.Orientation() === oc.TopAbs_Orientation.TopAbs_REVERSED;
|
|
109
109
|
if (!isReversed) {
|
|
110
110
|
wireEdges.push(raw);
|
|
111
111
|
ownedEdges.push(raw);
|
|
@@ -116,13 +116,13 @@ export class FilletOps {
|
|
|
116
116
|
const edgeLast = adaptor.LastParameter();
|
|
117
117
|
adaptor.delete();
|
|
118
118
|
const curveHandle = oc.BRep_Tool.Curve(raw, 0, 1);
|
|
119
|
-
if (!curveHandle
|
|
119
|
+
if (!curveHandle) {
|
|
120
120
|
raw.delete();
|
|
121
121
|
explorer.delete();
|
|
122
122
|
ownedEdges.forEach(e => e.delete());
|
|
123
123
|
throw new Error("fillet2d: edge has no 3D curve");
|
|
124
124
|
}
|
|
125
|
-
const curve = curveHandle.
|
|
125
|
+
const curve = curveHandle.returnValue;
|
|
126
126
|
const reversedHandle = curve.Reversed();
|
|
127
127
|
const newFirst = curve.ReversedParameter(edgeLast);
|
|
128
128
|
const newLast = curve.ReversedParameter(edgeFirst);
|
|
@@ -130,7 +130,7 @@ export class FilletOps {
|
|
|
130
130
|
const newEdge = oc.TopoDS.Edge(maker.Edge());
|
|
131
131
|
maker.delete();
|
|
132
132
|
reversedHandle.delete();
|
|
133
|
-
|
|
133
|
+
curve.delete();
|
|
134
134
|
raw.delete();
|
|
135
135
|
wireEdges.push(newEdge);
|
|
136
136
|
ownedEdges.push(newEdge);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Geom_BezierCurve, Geom_Circle, Geom_TrimmedCurve, TopoDS_Edge } from "
|
|
1
|
+
import type { Geom_BezierCurve, Geom_Circle, Geom_TrimmedCurve, TopoDS_Edge } from "ocjs-fluidcad";
|
|
2
2
|
import { Point, Point2D } from "../math/point.js";
|
|
3
3
|
import { Vector3d } from "../math/vector3d.js";
|
|
4
4
|
import { Edge } from "../common/edge.js";
|
package/lib/dist/oc/geometry.js
CHANGED
|
@@ -16,7 +16,7 @@ export class Geometry {
|
|
|
16
16
|
disposeP2();
|
|
17
17
|
throw new Error("Failed to create segment: " + status);
|
|
18
18
|
}
|
|
19
|
-
const geometry = segmentMaker.Value()
|
|
19
|
+
const geometry = segmentMaker.Value();
|
|
20
20
|
segmentMaker.delete();
|
|
21
21
|
disposeP1();
|
|
22
22
|
disposeP2();
|
|
@@ -29,7 +29,7 @@ export class Geometry {
|
|
|
29
29
|
const [gpP3, disposeP3] = Convert.toGpPnt(p3);
|
|
30
30
|
const arcMaker = new oc.GC_MakeArcOfCircle(gpStart, gpEnd, gpP3);
|
|
31
31
|
if (arcMaker.IsDone()) {
|
|
32
|
-
const curve = arcMaker.Value()
|
|
32
|
+
const curve = arcMaker.Value();
|
|
33
33
|
arcMaker.delete();
|
|
34
34
|
disposeStart();
|
|
35
35
|
disposeEnd();
|
|
@@ -54,7 +54,7 @@ export class Geometry {
|
|
|
54
54
|
const arcMaker = new oc.GC_MakeArcOfCircle(circle, s, e, true);
|
|
55
55
|
let curve = null;
|
|
56
56
|
if (arcMaker.IsDone()) {
|
|
57
|
-
curve = arcMaker.Value()
|
|
57
|
+
curve = arcMaker.Value();
|
|
58
58
|
}
|
|
59
59
|
disposeC();
|
|
60
60
|
disposeS();
|
|
@@ -77,7 +77,7 @@ export class Geometry {
|
|
|
77
77
|
const circle = new oc.gp_Circ(ax2, radius);
|
|
78
78
|
const arcMaker = new oc.GC_MakeArcOfCircle(circle, gpStart, angle, true);
|
|
79
79
|
if (arcMaker.IsDone()) {
|
|
80
|
-
const curve = arcMaker.Value()
|
|
80
|
+
const curve = arcMaker.Value();
|
|
81
81
|
arcMaker.delete();
|
|
82
82
|
ax2.delete();
|
|
83
83
|
circle.delete();
|
|
@@ -102,7 +102,7 @@ export class Geometry {
|
|
|
102
102
|
const [gpEnd, disposeEnd] = Convert.toGpPnt(end);
|
|
103
103
|
const arcMaker = new oc.GC_MakeArcOfCircle(gpStart, gpTangent, gpEnd);
|
|
104
104
|
if (arcMaker.IsDone()) {
|
|
105
|
-
const curve = arcMaker.Value()
|
|
105
|
+
const curve = arcMaker.Value();
|
|
106
106
|
arcMaker.delete();
|
|
107
107
|
disposeStart();
|
|
108
108
|
disposeTangent();
|
|
@@ -124,7 +124,7 @@ export class Geometry {
|
|
|
124
124
|
const gpCircle = new oc.gp_Circ(ax2, radius);
|
|
125
125
|
const circleMaker = new oc.GC_MakeCircle(gpCircle);
|
|
126
126
|
if (circleMaker.IsDone()) {
|
|
127
|
-
const circle = circleMaker.Value()
|
|
127
|
+
const circle = circleMaker.Value();
|
|
128
128
|
circleMaker.delete();
|
|
129
129
|
ax2.delete();
|
|
130
130
|
gpCircle.delete();
|
|
@@ -185,17 +185,16 @@ export class Geometry {
|
|
|
185
185
|
}
|
|
186
186
|
static makeEdgeFromBezier(curve) {
|
|
187
187
|
const oc = getOC();
|
|
188
|
-
|
|
189
|
-
|
|
188
|
+
// Handles are unwrapped in V8: pass the Geom_Curve straight to MakeEdge
|
|
189
|
+
// (constructing the abstract oc.Geom_Curve base throws at runtime).
|
|
190
|
+
const edgeMaker = new oc.BRepBuilderAPI_MakeEdge(curve, curve.StartPoint(), curve.EndPoint());
|
|
190
191
|
if (edgeMaker.IsDone()) {
|
|
191
192
|
const edge = edgeMaker.Edge();
|
|
192
193
|
edgeMaker.delete();
|
|
193
|
-
handle.delete();
|
|
194
194
|
return Edge.fromTopoDSEdge(edge);
|
|
195
195
|
}
|
|
196
196
|
const status = edgeMaker.Error();
|
|
197
197
|
edgeMaker.delete();
|
|
198
|
-
handle.delete();
|
|
199
198
|
throw new Error('Failed to create edge from bezier curve: ' + status);
|
|
200
199
|
}
|
|
201
200
|
// ── Edge factories ─────────────────────────────────────────────────────────
|
|
@@ -223,17 +222,16 @@ export class Geometry {
|
|
|
223
222
|
}
|
|
224
223
|
static makeEdgeFromCurveRaw(curve) {
|
|
225
224
|
const oc = getOC();
|
|
226
|
-
|
|
227
|
-
|
|
225
|
+
// Handles are unwrapped in V8: pass the Geom_Curve straight to MakeEdge
|
|
226
|
+
// (constructing the abstract oc.Geom_Curve base throws at runtime).
|
|
227
|
+
const edgeMaker = new oc.BRepBuilderAPI_MakeEdge(curve, curve.StartPoint(), curve.EndPoint());
|
|
228
228
|
if (edgeMaker.IsDone()) {
|
|
229
229
|
const edge = edgeMaker.Edge();
|
|
230
230
|
edgeMaker.delete();
|
|
231
|
-
handle.delete();
|
|
232
231
|
return edge;
|
|
233
232
|
}
|
|
234
233
|
const status = edgeMaker.Error();
|
|
235
234
|
edgeMaker.delete();
|
|
236
|
-
handle.delete();
|
|
237
235
|
throw new Error('Failed to create edge from arc: ' + status);
|
|
238
236
|
}
|
|
239
237
|
static makeEdgeFromCircleRaw(circle) {
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Edge } from "../common/edge.js";
|
|
2
|
+
import { CoordinateSystem } from "../math/coordinate-system.js";
|
|
3
|
+
/**
|
|
4
|
+
* Builds 3D helix edges with OCCT's TKHelix package. The analytic helix
|
|
5
|
+
* (`HelixGeom_HelixCurve`) is approximated as a single B-spline via
|
|
6
|
+
* `HelixGeom_Tools.ApprCurve3D`. Cylindrical and tapered (conical) helixes come
|
|
7
|
+
* from one uniform call — the taper is driven purely by the difference between
|
|
8
|
+
* the start and end radii over the axial range.
|
|
9
|
+
*
|
|
10
|
+
* NB: we deliberately do NOT use `HelixGeom_Tools.ApprHelix`, which hardcodes a
|
|
11
|
+
* 150-segment approximation budget. That is plenty for a cylinder (~3 segments
|
|
12
|
+
* per turn) but far too few for a many-turn tapered helix (~25+ per turn): the
|
|
13
|
+
* single-B-spline fit silently saturates the budget and oscillates wildly over
|
|
14
|
+
* the final turns while still reporting success (returnValue 0, theMaxError in
|
|
15
|
+
* the tens of mm). ApprCurve3D lets us scale the segment budget with the turn
|
|
16
|
+
* count so the adaptive fit can actually reach tolerance.
|
|
17
|
+
*/
|
|
18
|
+
export declare class HelixOps {
|
|
19
|
+
private static readonly APPROX_TOLERANCE;
|
|
20
|
+
private static readonly MAX_DEGREE;
|
|
21
|
+
private static readonly SEGMENTS_PER_TURN;
|
|
22
|
+
private static readonly MIN_SEGMENTS;
|
|
23
|
+
private static readonly MAX_SEGMENTS;
|
|
24
|
+
/**
|
|
25
|
+
* Build a helix edge running `turns` full revolutions, climbing along
|
|
26
|
+
* `cs.mainDirection` from axial coordinate `zStart` to `zEnd` and starting at
|
|
27
|
+
* angle 0 (the `cs.xDirection` ray). `startRadius` is the radius at `zStart`;
|
|
28
|
+
* when `endRadius` differs the radius tapers linearly to it at `zEnd`, yielding
|
|
29
|
+
* a conical helix (`endRadius === startRadius` gives a constant-radius cylinder).
|
|
30
|
+
*/
|
|
31
|
+
static makeHelix(cs: CoordinateSystem, startRadius: number, endRadius: number, zStart: number, zEnd: number, turns: number): Edge;
|
|
32
|
+
/**
|
|
33
|
+
* Rigidly move an edge built in the canonical frame (axis +Z through the
|
|
34
|
+
* origin) so it sits in `cs`, lifted along `cs.mainDirection` by `zStart`.
|
|
35
|
+
*/
|
|
36
|
+
private static placeInFrame;
|
|
37
|
+
}
|