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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Matrix4 } from "../../math/matrix4.js";
|
|
2
2
|
import { Edge, Face } from "../../common/shapes.js";
|
|
3
3
|
import { Solid } from "../../common/solid.js";
|
|
4
|
+
import { ShapeHasher } from "../../oc/shape-hash.js";
|
|
4
5
|
import { FilterBase } from "../filter-base.js";
|
|
5
6
|
import { FilterBuilderBase } from "../filter-builder-base.js";
|
|
6
7
|
declare abstract class BelongsToFaceFilterBase extends FilterBase<Edge> {
|
|
@@ -8,8 +9,9 @@ declare abstract class BelongsToFaceFilterBase extends FilterBase<Edge> {
|
|
|
8
9
|
protected scopeSolids: Solid[];
|
|
9
10
|
protected scopeFaces: Face[];
|
|
10
11
|
protected faceByHash: Map<number, Face[]>;
|
|
12
|
+
protected shapeHasher: ShapeHasher | null;
|
|
11
13
|
constructor(faceFilterBuilders: FilterBuilderBase<Face>[]);
|
|
12
|
-
setScopeIndex(solids: Solid[], extraFaces: Face[], faceByHash: Map<number, Face[]
|
|
14
|
+
setScopeIndex(solids: Solid[], extraFaces: Face[], faceByHash: Map<number, Face[]>, hasher: ShapeHasher): void;
|
|
13
15
|
protected findContainingFaces(edge: Edge): Face[];
|
|
14
16
|
}
|
|
15
17
|
export declare class BelongsToFaceFilter extends BelongsToFaceFilterBase {
|
|
@@ -7,14 +7,16 @@ class BelongsToFaceFilterBase extends FilterBase {
|
|
|
7
7
|
scopeSolids = [];
|
|
8
8
|
scopeFaces = [];
|
|
9
9
|
faceByHash = new Map();
|
|
10
|
+
shapeHasher = null;
|
|
10
11
|
constructor(faceFilterBuilders) {
|
|
11
12
|
super();
|
|
12
13
|
this.faceFilterBuilders = faceFilterBuilders;
|
|
13
14
|
}
|
|
14
|
-
setScopeIndex(solids, extraFaces, faceByHash) {
|
|
15
|
+
setScopeIndex(solids, extraFaces, faceByHash, hasher) {
|
|
15
16
|
this.scopeSolids = solids;
|
|
16
17
|
this.scopeFaces = extraFaces;
|
|
17
18
|
this.faceByHash = faceByHash;
|
|
19
|
+
this.shapeHasher = hasher;
|
|
18
20
|
}
|
|
19
21
|
findContainingFaces(edge) {
|
|
20
22
|
const edgeShape = edge.getShape();
|
|
@@ -24,7 +26,7 @@ class BelongsToFaceFilterBase extends FilterBase {
|
|
|
24
26
|
const index = solid.getEdgeToFacesIndex();
|
|
25
27
|
const rawFaces = TopologyIndex.seekShapes(index, edgeShape);
|
|
26
28
|
for (const raw of rawFaces) {
|
|
27
|
-
const wrapper = resolveFaceWrapper(raw, this.faceByHash);
|
|
29
|
+
const wrapper = resolveFaceWrapper(raw, this.faceByHash, this.shapeHasher);
|
|
28
30
|
if (wrapper && !seen.has(wrapper)) {
|
|
29
31
|
seen.add(wrapper);
|
|
30
32
|
result.push(wrapper);
|
|
@@ -93,9 +95,9 @@ export class NotBelongsToFaceFilter extends BelongsToFaceFilterBase {
|
|
|
93
95
|
return new NotBelongsToFaceFilter(transformed);
|
|
94
96
|
}
|
|
95
97
|
}
|
|
96
|
-
function resolveFaceWrapper(rawFace, faceByHash) {
|
|
97
|
-
const hash =
|
|
98
|
-
const bucket = faceByHash.get(hash);
|
|
98
|
+
function resolveFaceWrapper(rawFace, faceByHash, hasher) {
|
|
99
|
+
const hash = hasher ? hasher.key(rawFace) : null;
|
|
100
|
+
const bucket = hash !== null ? faceByHash.get(hash) : undefined;
|
|
99
101
|
if (bucket) {
|
|
100
102
|
for (const candidate of bucket) {
|
|
101
103
|
if (candidate.getShape().IsSame(rawFace)) {
|
|
@@ -106,11 +108,13 @@ function resolveFaceWrapper(rawFace, faceByHash) {
|
|
|
106
108
|
// Not in scope (e.g. neighbor face from another part / out-of-scope solid).
|
|
107
109
|
// Wrap on the fly so the face filters can still evaluate it.
|
|
108
110
|
const wrapped = Face.fromTopoDSFace(Explorer.toFace(rawFace));
|
|
109
|
-
if (
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
if (hash !== null) {
|
|
112
|
+
if (!bucket) {
|
|
113
|
+
faceByHash.set(hash, [wrapped]);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
bucket.push(wrapped);
|
|
117
|
+
}
|
|
114
118
|
}
|
|
115
119
|
return wrapped;
|
|
116
120
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getOC } from "../oc/init.js";
|
|
2
|
+
import { ShapeHasher } from "../oc/shape-hash.js";
|
|
2
3
|
export class TangentExpander {
|
|
3
4
|
/**
|
|
4
5
|
* Expands a set of seed shapes to include all transitively tangent-connected
|
|
@@ -20,48 +21,64 @@ export class TangentExpander {
|
|
|
20
21
|
* and their tangent vectors at that vertex are parallel.
|
|
21
22
|
*/
|
|
22
23
|
static expandEdges(seeds, pool) {
|
|
23
|
-
//
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
included.
|
|
36
|
-
|
|
24
|
+
// Interns shapes for IsSame-consistent Map keys (replaces TopoDS_Shape.HashCode,
|
|
25
|
+
// removed in OCCT 8.0); scoped to this expansion and freed below.
|
|
26
|
+
const hasher = new ShapeHasher();
|
|
27
|
+
try {
|
|
28
|
+
// Build vertex → edge adjacency map for efficient lookup
|
|
29
|
+
const vertexToEdges = TangentExpander.buildVertexToEdgeMap(pool, hasher);
|
|
30
|
+
const included = new Set(seeds);
|
|
31
|
+
const queue = [...seeds];
|
|
32
|
+
while (queue.length > 0) {
|
|
33
|
+
const current = queue.shift();
|
|
34
|
+
const neighbors = TangentExpander.getAdjacentEdges(current, vertexToEdges, hasher);
|
|
35
|
+
for (const candidate of neighbors) {
|
|
36
|
+
if (included.has(candidate)) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (TangentExpander.areEdgesTangent(current, candidate)) {
|
|
40
|
+
included.add(candidate);
|
|
41
|
+
queue.push(candidate);
|
|
42
|
+
}
|
|
37
43
|
}
|
|
38
44
|
}
|
|
45
|
+
return [...included];
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
hasher.delete();
|
|
39
49
|
}
|
|
40
|
-
return [...included];
|
|
41
50
|
}
|
|
42
51
|
/**
|
|
43
52
|
* BFS expansion for faces. Two faces are tangent if they share an edge
|
|
44
53
|
* and have G1 or higher continuity across that edge.
|
|
45
54
|
*/
|
|
46
55
|
static expandFaces(seeds, pool) {
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
included.
|
|
60
|
-
|
|
56
|
+
// Interns shapes for IsSame-consistent Map keys (replaces TopoDS_Shape.HashCode,
|
|
57
|
+
// removed in OCCT 8.0); scoped to this expansion and freed below.
|
|
58
|
+
const hasher = new ShapeHasher();
|
|
59
|
+
try {
|
|
60
|
+
// Build edge → face adjacency map
|
|
61
|
+
const edgeToFaces = TangentExpander.buildEdgeToFaceMap(pool, hasher);
|
|
62
|
+
const included = new Set(seeds);
|
|
63
|
+
const queue = [...seeds];
|
|
64
|
+
while (queue.length > 0) {
|
|
65
|
+
const current = queue.shift();
|
|
66
|
+
const neighbors = TangentExpander.getAdjacentFaces(current, edgeToFaces, hasher);
|
|
67
|
+
for (const [candidate, sharedEdge] of neighbors) {
|
|
68
|
+
if (included.has(candidate)) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (TangentExpander.areFacesTangent(current, candidate, sharedEdge)) {
|
|
72
|
+
included.add(candidate);
|
|
73
|
+
queue.push(candidate);
|
|
74
|
+
}
|
|
61
75
|
}
|
|
62
76
|
}
|
|
77
|
+
return [...included];
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
hasher.delete();
|
|
63
81
|
}
|
|
64
|
-
return [...included];
|
|
65
82
|
}
|
|
66
83
|
/**
|
|
67
84
|
* Checks if two edges are tangent at a shared vertex by comparing
|
|
@@ -89,10 +106,10 @@ export class TangentExpander {
|
|
|
89
106
|
}
|
|
90
107
|
// Get raw curves and parameters at the shared vertex
|
|
91
108
|
const curve1Handle = oc.BRep_Tool.Curve(e1Raw, 0, 1);
|
|
92
|
-
const curve1 = curve1Handle.
|
|
109
|
+
const curve1 = curve1Handle.returnValue;
|
|
93
110
|
const param1 = oc.BRep_Tool.Parameter(v1, e1Raw);
|
|
94
111
|
const curve2Handle = oc.BRep_Tool.Curve(e2Raw, 0, 1);
|
|
95
|
-
const curve2 = curve2Handle.
|
|
112
|
+
const curve2 = curve2Handle.returnValue;
|
|
96
113
|
const param2 = oc.BRep_Tool.Parameter(v2, e2Raw);
|
|
97
114
|
// Evaluate tangent vectors using D1
|
|
98
115
|
const pnt1 = new oc.gp_Pnt();
|
|
@@ -144,7 +161,7 @@ export class TangentExpander {
|
|
|
144
161
|
/**
|
|
145
162
|
* Builds a map from vertex TShape hash to the list of edges that share that vertex.
|
|
146
163
|
*/
|
|
147
|
-
static buildVertexToEdgeMap(edges) {
|
|
164
|
+
static buildVertexToEdgeMap(edges, hasher) {
|
|
148
165
|
const oc = getOC();
|
|
149
166
|
const map = new Map();
|
|
150
167
|
for (const edge of edges) {
|
|
@@ -152,7 +169,7 @@ export class TangentExpander {
|
|
|
152
169
|
const first = oc.TopExp.FirstVertex(raw, true);
|
|
153
170
|
const last = oc.TopExp.LastVertex(raw, true);
|
|
154
171
|
for (const vertex of [first, last]) {
|
|
155
|
-
const hash =
|
|
172
|
+
const hash = hasher.key(vertex);
|
|
156
173
|
if (!map.has(hash)) {
|
|
157
174
|
map.set(hash, []);
|
|
158
175
|
}
|
|
@@ -164,12 +181,12 @@ export class TangentExpander {
|
|
|
164
181
|
/**
|
|
165
182
|
* Builds a map from edge TShape hash to the list of faces that share that edge.
|
|
166
183
|
*/
|
|
167
|
-
static buildEdgeToFaceMap(faces) {
|
|
184
|
+
static buildEdgeToFaceMap(faces, hasher) {
|
|
168
185
|
const map = new Map();
|
|
169
186
|
for (const face of faces) {
|
|
170
187
|
const faceEdges = face.getEdges();
|
|
171
188
|
for (const edge of faceEdges) {
|
|
172
|
-
const hash = edge.getShape()
|
|
189
|
+
const hash = hasher.key(edge.getShape());
|
|
173
190
|
if (!map.has(hash)) {
|
|
174
191
|
map.set(hash, []);
|
|
175
192
|
}
|
|
@@ -181,14 +198,14 @@ export class TangentExpander {
|
|
|
181
198
|
/**
|
|
182
199
|
* Returns edges from the adjacency map that share a vertex with the given edge.
|
|
183
200
|
*/
|
|
184
|
-
static getAdjacentEdges(edge, vertexToEdges) {
|
|
201
|
+
static getAdjacentEdges(edge, vertexToEdges, hasher) {
|
|
185
202
|
const oc = getOC();
|
|
186
203
|
const raw = edge.getShape();
|
|
187
204
|
const first = oc.TopExp.FirstVertex(raw, true);
|
|
188
205
|
const last = oc.TopExp.LastVertex(raw, true);
|
|
189
206
|
const neighbors = new Set();
|
|
190
207
|
for (const vertex of [first, last]) {
|
|
191
|
-
const hash =
|
|
208
|
+
const hash = hasher.key(vertex);
|
|
192
209
|
const candidates = vertexToEdges.get(hash);
|
|
193
210
|
if (candidates) {
|
|
194
211
|
for (const c of candidates) {
|
|
@@ -204,11 +221,11 @@ export class TangentExpander {
|
|
|
204
221
|
* Returns faces from the adjacency map that share an edge with the given face,
|
|
205
222
|
* along with the shared edge's raw TopoDS_Edge.
|
|
206
223
|
*/
|
|
207
|
-
static getAdjacentFaces(face, edgeToFaces) {
|
|
224
|
+
static getAdjacentFaces(face, edgeToFaces, hasher) {
|
|
208
225
|
const result = [];
|
|
209
226
|
const faceEdges = face.getEdges();
|
|
210
227
|
for (const edge of faceEdges) {
|
|
211
|
-
const hash = edge.getShape()
|
|
228
|
+
const hash = hasher.key(edge.getShape());
|
|
212
229
|
const candidates = edgeToFaces.get(hash);
|
|
213
230
|
if (candidates) {
|
|
214
231
|
for (const c of candidates) {
|
|
@@ -7,6 +7,7 @@ export declare function fuseWithSceneObjects(sceneObjects: SceneObject[], extrus
|
|
|
7
7
|
glue?: 'full' | 'shift';
|
|
8
8
|
recordHistoryFor?: SceneObject;
|
|
9
9
|
profiler?: Profiler;
|
|
10
|
+
skipSimplify?: boolean;
|
|
10
11
|
}): {
|
|
11
12
|
newShapes: Shape<any>[];
|
|
12
13
|
modifiedShapes: any[];
|
|
@@ -21,6 +22,7 @@ export declare function fuseWithSceneObjects(sceneObjects: SceneObject[], extrus
|
|
|
21
22
|
};
|
|
22
23
|
export declare function cutWithSceneObjects(sceneObjects: SceneObject[], toolShapes: Shape[], plane: Plane, distance: number, caller: SceneObject, options?: {
|
|
23
24
|
recordHistoryFor?: SceneObject;
|
|
25
|
+
skipSimplify?: boolean;
|
|
24
26
|
}): {
|
|
25
27
|
cleanedShapes: Shape[];
|
|
26
28
|
stockShapes: Shape[];
|
|
@@ -302,7 +302,7 @@ export function cutWithSceneObjects(sceneObjects, toolShapes, plane, distance, c
|
|
|
302
302
|
const list = cutResult.modified(shape);
|
|
303
303
|
if (list.length) {
|
|
304
304
|
for (const newShape of list) {
|
|
305
|
-
const cleanup = ShapeOps.cleanShapeWithLineage(newShape);
|
|
305
|
+
const cleanup = ShapeOps.cleanShapeWithLineage(newShape, { skipSimplify: options?.skipSimplify });
|
|
306
306
|
caller.addShape(cleanup.shape);
|
|
307
307
|
cleanedShapes.push(cleanup.shape);
|
|
308
308
|
cleanups.push(cleanup);
|
package/lib/dist/index.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export type { ParamDefinition, MultiControlType, SelectOption, ParamVal, ParamSc
|
|
|
22
22
|
export { setAssetProvider } from './io/file-import.js';
|
|
23
23
|
export type { AssetProvider } from './io/file-import.js';
|
|
24
24
|
export { getSceneManager } from './scene-manager.js';
|
|
25
|
+
export { describeOcException } from './oc/errors.js';
|
|
25
26
|
export interface FluidCADOptions {
|
|
26
27
|
mesh?: {
|
|
27
28
|
lineDeflection?: number;
|
|
@@ -42,6 +43,7 @@ export declare function init(options?: FluidCADOptions): Promise<{
|
|
|
42
43
|
getShapeProperties(scene: Scene, shapeId: string): import("./oc/props.js").ShapeProperties | null;
|
|
43
44
|
getFaceProperties(scene: Scene, shapeId: string, faceIndex: number): import("./oc/face-props.js").FaceProperties | null;
|
|
44
45
|
getEdgeProperties(scene: Scene, shapeId: string, edgeIndex: number): import("./oc/edge-props.js").EdgeProperties | null;
|
|
46
|
+
measure(scene: Scene, refs: import("./oc/index.js").MeasureEntityRef[]): import("./oc/index.js").MeasureResult | null;
|
|
45
47
|
exportShapes(scene: Scene, shapeIds: string[], options: import("./io/file-export.js").ExportOptions): {
|
|
46
48
|
data: string | Uint8Array;
|
|
47
49
|
fileName: string;
|
package/lib/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { loadOC } from "./load.js";
|
|
2
|
+
import { FontRegistry } from "./io/font-registry.js";
|
|
2
3
|
import { createManager, getCurrentScene, getSceneManager } from "./scene-manager.js";
|
|
3
4
|
import { parse as parseStackTrace } from "stacktrace-parser";
|
|
4
5
|
export function captureSourceLocation() {
|
|
@@ -91,8 +92,9 @@ export function registerBuilder(builder) {
|
|
|
91
92
|
export { createParamRegistry, getParamRegistry } from './param-registry.js';
|
|
92
93
|
export { setAssetProvider } from './io/file-import.js';
|
|
93
94
|
export { getSceneManager } from './scene-manager.js';
|
|
95
|
+
export { describeOcException } from './oc/errors.js';
|
|
94
96
|
export async function init(options) {
|
|
95
|
-
await loadOC();
|
|
97
|
+
await Promise.all([loadOC(), FontRegistry.init()]);
|
|
96
98
|
const existing = getSceneManager();
|
|
97
99
|
if (existing) {
|
|
98
100
|
return existing;
|
|
@@ -7,6 +7,13 @@ import { Solid } from "../common/solid.js";
|
|
|
7
7
|
*/
|
|
8
8
|
export type AssetProvider = (workspaceRelPath: string) => Uint8Array | null;
|
|
9
9
|
export declare function setAssetProvider(provider: AssetProvider | null): void;
|
|
10
|
+
/**
|
|
11
|
+
* Reads a workspace asset as raw bytes (e.g. a font file). Consults the
|
|
12
|
+
* AssetProvider first (hub mode), then the workspace filesystem. Paths are
|
|
13
|
+
* workspace-relative and confined to the workspace root (no `..` traversal).
|
|
14
|
+
* Returns null when the asset cannot be found.
|
|
15
|
+
*/
|
|
16
|
+
export declare function readWorkspaceAssetBytes(relPath: string): Uint8Array | null;
|
|
10
17
|
export declare class FileImport {
|
|
11
18
|
static deserializeShapes(fileName: string): Solid[];
|
|
12
19
|
static serializeShape(shape: Shape, workspacePath: string, fileName: string): void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
|
-
import { join } from "path";
|
|
2
|
+
import { join, resolve, sep } from "path";
|
|
3
3
|
import { OcIO } from "../oc/io.js";
|
|
4
4
|
import { getSceneManager } from "../scene-manager.js";
|
|
5
5
|
let assetProvider = null;
|
|
@@ -20,6 +20,33 @@ function readWorkspaceAsset(relPath) {
|
|
|
20
20
|
}
|
|
21
21
|
return { text: fs.readFileSync(filePath, 'utf8'), exists: true };
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Reads a workspace asset as raw bytes (e.g. a font file). Consults the
|
|
25
|
+
* AssetProvider first (hub mode), then the workspace filesystem. Paths are
|
|
26
|
+
* workspace-relative and confined to the workspace root (no `..` traversal).
|
|
27
|
+
* Returns null when the asset cannot be found.
|
|
28
|
+
*/
|
|
29
|
+
export function readWorkspaceAssetBytes(relPath) {
|
|
30
|
+
if (assetProvider) {
|
|
31
|
+
const bytes = assetProvider(relPath);
|
|
32
|
+
if (bytes) {
|
|
33
|
+
return bytes;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const sceneManager = getSceneManager();
|
|
37
|
+
if (!sceneManager) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
const root = resolve(sceneManager.rootPath);
|
|
41
|
+
const filePath = resolve(root, relPath);
|
|
42
|
+
if (filePath !== root && !filePath.startsWith(root + sep)) {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
if (!fs.existsSync(filePath)) {
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
return fs.readFileSync(filePath);
|
|
49
|
+
}
|
|
23
50
|
export class FileImport {
|
|
24
51
|
static deserializeShapes(fileName) {
|
|
25
52
|
if (!fileName.endsWith(('.brep'))) {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Font } from "fontkit";
|
|
2
|
+
/**
|
|
3
|
+
* Resolves font names/paths to ready-to-use fontkit `Font` instances.
|
|
4
|
+
*
|
|
5
|
+
* `init()` enumerates system fonts (via `get-system-fonts`) once per process and
|
|
6
|
+
* builds a family -> variants index (via `fontkit`). `resolve()` is synchronous
|
|
7
|
+
* so it can be called from `SceneObject.build()`; it requires `init()` to have
|
|
8
|
+
* completed first, mirroring `getOC()` / `loadOC()`.
|
|
9
|
+
*/
|
|
10
|
+
export declare class FontRegistry {
|
|
11
|
+
private static index;
|
|
12
|
+
private static allFiles;
|
|
13
|
+
private static fontCache;
|
|
14
|
+
static init(): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Resolves a font request into a ready fontkit `Font`. Never returns null:
|
|
17
|
+
* falls back through aliases -> default families -> any available font, and
|
|
18
|
+
* only throws if the machine has no usable fonts at all.
|
|
19
|
+
*/
|
|
20
|
+
static resolve(opts: {
|
|
21
|
+
font?: string;
|
|
22
|
+
weight?: number;
|
|
23
|
+
italic?: boolean;
|
|
24
|
+
}): Font;
|
|
25
|
+
private static ensureInit;
|
|
26
|
+
/** Collects a family's variants plus its alias families' variants, unsorted. */
|
|
27
|
+
private static collectVariants;
|
|
28
|
+
/**
|
|
29
|
+
* Sorts variants by italic match then nearest weight, and opens the first that
|
|
30
|
+
* actually renders (skipping fonts that throw on outline access).
|
|
31
|
+
*/
|
|
32
|
+
private static openFirstRenderable;
|
|
33
|
+
/** Opens and validates a variant; caches the result, including known-bad (null). */
|
|
34
|
+
private static openVariant;
|
|
35
|
+
/** All indexed system font family names (lowercased). Useful for tooling/tests. */
|
|
36
|
+
static availableFamilies(): string[];
|
|
37
|
+
private static tryOpenFile;
|
|
38
|
+
/**
|
|
39
|
+
* A font is usable only if its outlines compute without throwing. Fonts that
|
|
40
|
+
* declare an fvar variation axis but lack the variable outline tables
|
|
41
|
+
* (gvar/glyf or CFF2) throw lazily when glyph paths are accessed.
|
|
42
|
+
*/
|
|
43
|
+
private static canRender;
|
|
44
|
+
private static loadLocalFile;
|
|
45
|
+
}
|