@constructorfleet/sketchforge-engine 1.26.0 → 1.27.0
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/dist/cadAnalysis.d.ts +94 -0
- package/dist/cadAnalysis.d.ts.map +1 -0
- package/dist/cadAnalysis.js +143 -0
- package/dist/cadAnalysis.js.map +1 -0
- package/dist/cadShell.d.ts +143 -0
- package/dist/cadShell.d.ts.map +1 -0
- package/dist/cadShell.js +306 -0
- package/dist/cadShell.js.map +1 -0
- package/dist/domain/sketchforge.d.ts +1 -1
- package/dist/domain/sketchforge.d.ts.map +1 -1
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +57 -15
- package/dist/engine.js.map +1 -1
- package/dist/parametricRecompute.d.ts.map +1 -1
- package/dist/parametricRecompute.js +7 -4
- package/dist/parametricRecompute.js.map +1 -1
- package/dist/revolveRequests.d.ts.map +1 -1
- package/dist/serverCadInterference.d.ts +8 -45
- package/dist/serverCadInterference.d.ts.map +1 -1
- package/dist/serverCadInterference.js +13 -42
- package/dist/serverCadInterference.js.map +1 -1
- package/dist/serverCadOperations.d.ts.map +1 -1
- package/dist/serverCadOperations.js +76 -25
- package/dist/serverCadOperations.js.map +1 -1
- package/dist/serverCadShell.d.ts +7 -94
- package/dist/serverCadShell.d.ts.map +1 -1
- package/dist/serverCadShell.js +25 -269
- package/dist/serverCadShell.js.map +1 -1
- package/dist/serverCadThickness.d.ts +8 -8
- package/dist/serverCadThickness.d.ts.map +1 -1
- package/dist/serverCadThickness.js +15 -42
- package/dist/serverCadThickness.js.map +1 -1
- package/dist/serverStepExplode.d.ts +1 -2
- package/dist/serverStepExplode.d.ts.map +1 -1
- package/dist/serverStepExplode.js +15 -148
- package/dist/serverStepExplode.js.map +1 -1
- package/dist/sketchFaceDraftKernel.d.ts +5 -5
- package/dist/sketchFaceDraftKernel.d.ts.map +1 -1
- package/dist/sketchFaceDraftKernel.js +11 -9
- package/dist/sketchFaceDraftKernel.js.map +1 -1
- package/dist/stepAssemblyExplode.d.ts +45 -0
- package/dist/stepAssemblyExplode.d.ts.map +1 -0
- package/dist/stepAssemblyExplode.js +195 -0
- package/dist/stepAssemblyExplode.js.map +1 -0
- package/dist/support/cadModifierTypes.d.ts +59 -0
- package/dist/support/cadModifierTypes.d.ts.map +1 -1
- package/dist/support/i18n/locales/en/messages.json +13 -1
- package/package.json +1 -1
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interference and wall-thickness analysis over kernel solids (#380).
|
|
3
|
+
*
|
|
4
|
+
* Kernel-agnostic on purpose, like `exactBooleanSolids`: the REST API runs it
|
|
5
|
+
* under Node on solids placed from the stored project, and the editor's CAD
|
|
6
|
+
* worker runs it in the browser on solids rebuilt from the parts it sends. Both
|
|
7
|
+
* then give the same answer, refuse the same oversized requests, and disclose
|
|
8
|
+
* the same method, because there is only one implementation of each.
|
|
9
|
+
*
|
|
10
|
+
* Neither function changes anything: they read solids and return numbers.
|
|
11
|
+
*/
|
|
12
|
+
import type { OcctKernel, ShapeHandle } from "occt-wasm";
|
|
13
|
+
export declare const MAX_INTERFERENCE_SHAPES = 128;
|
|
14
|
+
export declare const MAX_INTERFERENCE_CANDIDATES = 512;
|
|
15
|
+
export declare const INTERFERENCE_METHOD: "OCCT exact distance and common volume; AABB candidate prefilter";
|
|
16
|
+
export type InterferencePair = {
|
|
17
|
+
a: {
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
};
|
|
21
|
+
b: {
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
};
|
|
25
|
+
/** Exact OCCT minimum surface distance in mm. */
|
|
26
|
+
gap: number;
|
|
27
|
+
/** Exact common volume in mm^3; zero when separated or touching. */
|
|
28
|
+
overlapVolume: number;
|
|
29
|
+
/** Imported triangle meshes remain tessellated inputs to the exact kernel solver. */
|
|
30
|
+
precision: "exact" | "tessellated";
|
|
31
|
+
};
|
|
32
|
+
export type InterferenceReport = {
|
|
33
|
+
shapesChecked: number;
|
|
34
|
+
candidatePairsChecked: number;
|
|
35
|
+
clearance: number;
|
|
36
|
+
method: typeof INTERFERENCE_METHOD;
|
|
37
|
+
pairs: InterferencePair[];
|
|
38
|
+
};
|
|
39
|
+
export type InterferenceRefusal = {
|
|
40
|
+
reason: "invalid_clearance";
|
|
41
|
+
} | {
|
|
42
|
+
reason: "too_many_shapes";
|
|
43
|
+
limit: number;
|
|
44
|
+
given: number;
|
|
45
|
+
} | {
|
|
46
|
+
reason: "too_many_candidates";
|
|
47
|
+
limit: number;
|
|
48
|
+
given: number;
|
|
49
|
+
};
|
|
50
|
+
export type InterferenceResult = {
|
|
51
|
+
ok: true;
|
|
52
|
+
value: InterferenceReport;
|
|
53
|
+
} | {
|
|
54
|
+
ok: false;
|
|
55
|
+
refusal: InterferenceRefusal;
|
|
56
|
+
};
|
|
57
|
+
/** One shape to check: who it is, and whether its solid was sewn from triangles. */
|
|
58
|
+
export type InterferenceOperand = {
|
|
59
|
+
id: string;
|
|
60
|
+
name: string;
|
|
61
|
+
tessellated: boolean;
|
|
62
|
+
};
|
|
63
|
+
/** Why a request is refused before any solid is built, or null when it may run. */
|
|
64
|
+
export declare function interferenceRequestRefusal(count: number, clearance: number): InterferenceRefusal | null;
|
|
65
|
+
/**
|
|
66
|
+
* Exact gaps and overlap volumes between every pair of operands within
|
|
67
|
+
* `clearance`. Axis-aligned bounds only discard pairs that cannot be that
|
|
68
|
+
* close; every pair left is measured by OCCT. Exceeding either limit refuses
|
|
69
|
+
* the request whole -- half a report would read as "nothing else collides".
|
|
70
|
+
*
|
|
71
|
+
* `solidFor` builds an operand's solid where it stands in the project.
|
|
72
|
+
*/
|
|
73
|
+
export declare function interferenceBetweenSolids<T extends InterferenceOperand>(cad: OcctKernel, operands: readonly T[], solidFor: (operand: T) => ShapeHandle, clearance?: number): InterferenceResult;
|
|
74
|
+
export declare const WALL_THICKNESS_MAX_FACES = 256;
|
|
75
|
+
export type WallThicknessResult = {
|
|
76
|
+
minimum: number | null;
|
|
77
|
+
unit: "mm";
|
|
78
|
+
method: "sampled-opposing-surface-distance";
|
|
79
|
+
samplesPerFace: number;
|
|
80
|
+
facesChecked: number;
|
|
81
|
+
};
|
|
82
|
+
/** Why a solid cannot be sampled at all. */
|
|
83
|
+
export declare class WallThicknessRefusal extends Error {
|
|
84
|
+
readonly reason: "no_faces" | "too_many_faces";
|
|
85
|
+
readonly limit?: number | undefined;
|
|
86
|
+
constructor(reason: "no_faces" | "too_many_faces", limit?: number | undefined);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* The smallest sampled distance between opposing faces of `solid`. This is a
|
|
90
|
+
* screening estimate, not a medial-axis or certified minimum-thickness result:
|
|
91
|
+
* a wall thinner between two sample points than at any of them is missed.
|
|
92
|
+
*/
|
|
93
|
+
export declare function sampledWallThickness(cad: OcctKernel, solid: ShapeHandle): WallThicknessResult;
|
|
94
|
+
//# sourceMappingURL=cadAnalysis.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cadAnalysis.d.ts","sourceRoot":"","sources":["../src/cadAnalysis.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAQ,MAAM,WAAW,CAAC;AAE/D,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,2BAA2B,MAAM,CAAC;AAC/C,eAAO,MAAM,mBAAmB,EAAG,iEAA0E,CAAC;AAG9G,MAAM,MAAM,gBAAgB,GAAG;IAC7B,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAChC,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAChC,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,oEAAoE;IACpE,aAAa,EAAE,MAAM,CAAC;IACtB,qFAAqF;IACrF,SAAS,EAAE,OAAO,GAAG,aAAa,CAAC;CACpC,CAAC;AACF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,aAAa,EAAE,MAAM,CAAC;IACtB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,OAAO,mBAAmB,CAAC;IACnC,KAAK,EAAE,gBAAgB,EAAE,CAAC;CAC3B,CAAC;AACF,MAAM,MAAM,mBAAmB,GAC3B;IAAE,MAAM,EAAE,mBAAmB,CAAA;CAAE,GAC/B;IAAE,MAAM,EAAE,iBAAiB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3D;IAAE,MAAM,EAAE,qBAAqB,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AACpE,MAAM,MAAM,kBAAkB,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,kBAAkB,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,mBAAmB,CAAA;CAAE,CAAC;AAEvH,oFAAoF;AACpF,MAAM,MAAM,mBAAmB,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CAAC;AAWrF,mFAAmF;AACnF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI,CAIvG;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,CAAC,SAAS,mBAAmB,EACrE,GAAG,EAAE,UAAU,EACf,QAAQ,EAAE,SAAS,CAAC,EAAE,EACtB,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,WAAW,EACrC,SAAS,SAAI,GACZ,kBAAkB,CAiCpB;AAED,eAAO,MAAM,wBAAwB,MAAM,CAAC;AAI5C,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,mCAAmC,CAAC;IAC5C,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,4CAA4C;AAC5C,qBAAa,oBAAqB,SAAQ,KAAK;IACjC,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,gBAAgB;IAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM;gBAA9D,MAAM,EAAE,UAAU,GAAG,gBAAgB,EAAW,KAAK,CAAC,EAAE,MAAM,YAAA;CAMpF;AAeD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,GAAG,mBAAmB,CA0B7F"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interference and wall-thickness analysis over kernel solids (#380).
|
|
3
|
+
*
|
|
4
|
+
* Kernel-agnostic on purpose, like `exactBooleanSolids`: the REST API runs it
|
|
5
|
+
* under Node on solids placed from the stored project, and the editor's CAD
|
|
6
|
+
* worker runs it in the browser on solids rebuilt from the parts it sends. Both
|
|
7
|
+
* then give the same answer, refuse the same oversized requests, and disclose
|
|
8
|
+
* the same method, because there is only one implementation of each.
|
|
9
|
+
*
|
|
10
|
+
* Neither function changes anything: they read solids and return numbers.
|
|
11
|
+
*/
|
|
12
|
+
export const MAX_INTERFERENCE_SHAPES = 128;
|
|
13
|
+
export const MAX_INTERFERENCE_CANDIDATES = 512;
|
|
14
|
+
export const INTERFERENCE_METHOD = "OCCT exact distance and common volume; AABB candidate prefilter";
|
|
15
|
+
const CONTACT_EPSILON_MM = 1e-7;
|
|
16
|
+
function boundsWithinClearance(a, b, clearance) {
|
|
17
|
+
const dx = Math.max(0, b.xmin - a.xmax, a.xmin - b.xmax);
|
|
18
|
+
const dy = Math.max(0, b.ymin - a.ymax, a.ymin - b.ymax);
|
|
19
|
+
const dz = Math.max(0, b.zmin - a.zmax, a.zmin - b.zmax);
|
|
20
|
+
return Math.hypot(dx, dy, dz) <= clearance;
|
|
21
|
+
}
|
|
22
|
+
/** Why a request is refused before any solid is built, or null when it may run. */
|
|
23
|
+
export function interferenceRequestRefusal(count, clearance) {
|
|
24
|
+
if (!Number.isFinite(clearance) || clearance < 0)
|
|
25
|
+
return { reason: "invalid_clearance" };
|
|
26
|
+
if (count > MAX_INTERFERENCE_SHAPES)
|
|
27
|
+
return { reason: "too_many_shapes", limit: MAX_INTERFERENCE_SHAPES, given: count };
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Exact gaps and overlap volumes between every pair of operands within
|
|
32
|
+
* `clearance`. Axis-aligned bounds only discard pairs that cannot be that
|
|
33
|
+
* close; every pair left is measured by OCCT. Exceeding either limit refuses
|
|
34
|
+
* the request whole -- half a report would read as "nothing else collides".
|
|
35
|
+
*
|
|
36
|
+
* `solidFor` builds an operand's solid where it stands in the project.
|
|
37
|
+
*/
|
|
38
|
+
export function interferenceBetweenSolids(cad, operands, solidFor, clearance = 0) {
|
|
39
|
+
const refusal = interferenceRequestRefusal(operands.length, clearance);
|
|
40
|
+
if (refusal)
|
|
41
|
+
return { ok: false, refusal };
|
|
42
|
+
const solids = operands.map(solidFor);
|
|
43
|
+
const queries = cad.queryBatch(solids);
|
|
44
|
+
const candidates = [];
|
|
45
|
+
for (let i = 0; i < operands.length; i += 1)
|
|
46
|
+
for (let j = i + 1; j < operands.length; j += 1) {
|
|
47
|
+
const a = queries[i];
|
|
48
|
+
const b = queries[j];
|
|
49
|
+
if (a && b && boundsWithinClearance(a.bbox, b.bbox, clearance))
|
|
50
|
+
candidates.push([i, j]);
|
|
51
|
+
if (candidates.length > MAX_INTERFERENCE_CANDIDATES) {
|
|
52
|
+
return { ok: false, refusal: { reason: "too_many_candidates", limit: MAX_INTERFERENCE_CANDIDATES, given: candidates.length } };
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const pairs = [];
|
|
56
|
+
for (const [i, j] of candidates) {
|
|
57
|
+
const gap = cad.distanceBetween(solids[i], solids[j]);
|
|
58
|
+
if (gap > clearance + CONTACT_EPSILON_MM)
|
|
59
|
+
continue;
|
|
60
|
+
const overlapVolume = gap <= CONTACT_EPSILON_MM
|
|
61
|
+
? Math.max(0, cad.getVolume(cad.common(solids[i], solids[j])))
|
|
62
|
+
: 0;
|
|
63
|
+
const a = operands[i];
|
|
64
|
+
const b = operands[j];
|
|
65
|
+
pairs.push({
|
|
66
|
+
a: { id: a.id, name: a.name },
|
|
67
|
+
b: { id: b.id, name: b.name },
|
|
68
|
+
gap,
|
|
69
|
+
overlapVolume,
|
|
70
|
+
precision: a.tessellated || b.tessellated ? "tessellated" : "exact",
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
pairs.sort((a, b) => a.gap - b.gap || b.overlapVolume - a.overlapVolume || a.a.id.localeCompare(b.a.id));
|
|
74
|
+
return { ok: true, value: { shapesChecked: operands.length, candidatePairsChecked: candidates.length, clearance, method: INTERFERENCE_METHOD, pairs } };
|
|
75
|
+
}
|
|
76
|
+
export const WALL_THICKNESS_MAX_FACES = 256;
|
|
77
|
+
/** Samples per face are a GRID x GRID lattice over the face's parameter range. */
|
|
78
|
+
const WALL_THICKNESS_GRID = 5;
|
|
79
|
+
/** Why a solid cannot be sampled at all. */
|
|
80
|
+
export class WallThicknessRefusal extends Error {
|
|
81
|
+
reason;
|
|
82
|
+
limit;
|
|
83
|
+
constructor(reason, limit) {
|
|
84
|
+
super(reason === "no_faces"
|
|
85
|
+
? "The shape has no faces to analyze."
|
|
86
|
+
: `Wall-thickness analysis supports at most ${limit} faces.`);
|
|
87
|
+
this.reason = reason;
|
|
88
|
+
this.limit = limit;
|
|
89
|
+
this.name = "WallThicknessRefusal";
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
function faceSamples(cad, face) {
|
|
93
|
+
const uv = cad.uvBounds(face);
|
|
94
|
+
const points = [];
|
|
95
|
+
for (let i = 0; i < WALL_THICKNESS_GRID; i += 1)
|
|
96
|
+
for (let j = 0; j < WALL_THICKNESS_GRID; j += 1) {
|
|
97
|
+
const u = uv.uMin + (uv.uMax - uv.uMin) * (i + 0.5) / WALL_THICKNESS_GRID;
|
|
98
|
+
const v = uv.vMin + (uv.vMax - uv.vMin) * (j + 0.5) / WALL_THICKNESS_GRID;
|
|
99
|
+
if (cad.classifyPointOnFace(face, u, v) !== "out") {
|
|
100
|
+
points.push({ point: cad.pointOnSurface(face, u, v), normal: cad.surfaceNormal(face, u, v) });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return points;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* The smallest sampled distance between opposing faces of `solid`. This is a
|
|
107
|
+
* screening estimate, not a medial-axis or certified minimum-thickness result:
|
|
108
|
+
* a wall thinner between two sample points than at any of them is missed.
|
|
109
|
+
*/
|
|
110
|
+
export function sampledWallThickness(cad, solid) {
|
|
111
|
+
const faces = cad.getSubShapes(solid, "face");
|
|
112
|
+
if (!faces.length)
|
|
113
|
+
throw new WallThicknessRefusal("no_faces");
|
|
114
|
+
if (faces.length > WALL_THICKNESS_MAX_FACES)
|
|
115
|
+
throw new WallThicknessRefusal("too_many_faces", WALL_THICKNESS_MAX_FACES);
|
|
116
|
+
const sampled = faces.map((face) => faceSamples(cad, face));
|
|
117
|
+
let minimum = Infinity;
|
|
118
|
+
for (let i = 0; i < faces.length; i += 1)
|
|
119
|
+
for (let j = i + 1; j < faces.length; j += 1) {
|
|
120
|
+
for (const source of sampled[i]) {
|
|
121
|
+
for (const target of sampled[j]) {
|
|
122
|
+
const dot = source.normal.x * target.normal.x + source.normal.y * target.normal.y + source.normal.z * target.normal.z;
|
|
123
|
+
if (dot > -0.5)
|
|
124
|
+
continue;
|
|
125
|
+
const uv = cad.uvFromPoint(faces[j], source.point);
|
|
126
|
+
if (cad.classifyPointOnFace(faces[j], uv.u, uv.v) === "out")
|
|
127
|
+
continue;
|
|
128
|
+
const projected = cad.pointOnSurface(faces[j], uv.u, uv.v);
|
|
129
|
+
const distance = Math.hypot(source.point.x - projected.x, source.point.y - projected.y, source.point.z - projected.z);
|
|
130
|
+
if (distance > 1e-7 && distance < minimum)
|
|
131
|
+
minimum = distance;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
minimum: Number.isFinite(minimum) ? minimum : null,
|
|
137
|
+
unit: "mm",
|
|
138
|
+
method: "sampled-opposing-surface-distance",
|
|
139
|
+
samplesPerFace: WALL_THICKNESS_GRID * WALL_THICKNESS_GRID,
|
|
140
|
+
facesChecked: faces.length,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=cadAnalysis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cadAnalysis.js","sourceRoot":"","sources":["../src/cadAnalysis.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hollowing a solid with a wall of a given thickness, on any OCCT kernel.
|
|
3
|
+
*
|
|
4
|
+
* The REST endpoint (`serverCadShell.ts`) and the editor's CAD worker both
|
|
5
|
+
* hollow through this module, so a part shelled in the browser and the same
|
|
6
|
+
* part shelled over the API come out of the same code at the same tolerance.
|
|
7
|
+
* It imports nothing Node-only: the caller hands it a kernel and a solid.
|
|
8
|
+
*
|
|
9
|
+
* OCCT does the work with `BRepOffsetAPI_MakeThickSolid`, which the bundled
|
|
10
|
+
* kernel exposes as `shell`. Two things about it are worth knowing before
|
|
11
|
+
* changing any of this, both found by measuring rather than by reading:
|
|
12
|
+
*
|
|
13
|
+
* - With no faces removed it does not hollow anything. It returns the *inner*
|
|
14
|
+
* solid -- the original offset inwards by the thickness -- so a sealed
|
|
15
|
+
* hollow has to be the original cut by that, which is what `hollowedSolid`
|
|
16
|
+
* does. Asking it to hollow a closed solid directly gives you back a
|
|
17
|
+
* smaller solid part, which looks plausible and is not what was asked for.
|
|
18
|
+
* - A thickness that does not fit does not reliably fail. Past half the
|
|
19
|
+
* part it variously returns an empty compound, a solid that reports
|
|
20
|
+
* `isValid: false` with a correct bounding box, or the original solid
|
|
21
|
+
* untouched with every extent and the validity flag intact. Only the volume
|
|
22
|
+
* tells those apart from a real answer, which is why `hollowedSolid`
|
|
23
|
+
* measures it rather than trusting the call to throw.
|
|
24
|
+
*
|
|
25
|
+
* Refusals are `CadShellError`s carrying a `reason`, so the REST path can
|
|
26
|
+
* answer with its English message and status while the editor says the same
|
|
27
|
+
* thing in the person's language.
|
|
28
|
+
*/
|
|
29
|
+
import type { OcctKernel, ShapeHandle, Vec3 } from "occt-wasm";
|
|
30
|
+
/**
|
|
31
|
+
* Names for the faces a request is likely to want open, by where they point.
|
|
32
|
+
*
|
|
33
|
+
* A caller that knows the geometry can name face indexes from the listing, but
|
|
34
|
+
* nobody wants to list a box's faces to find out which one is the lid. The
|
|
35
|
+
* directions are the solid's own axes: +Y up, +Z towards the viewer. Which of
|
|
36
|
+
* several parallel faces a name means is settled by how far out each sits, so
|
|
37
|
+
* the solid may stand anywhere.
|
|
38
|
+
*/
|
|
39
|
+
declare const FACE_DIRECTIONS: {
|
|
40
|
+
readonly top: {
|
|
41
|
+
readonly x: 0;
|
|
42
|
+
readonly y: 1;
|
|
43
|
+
readonly z: 0;
|
|
44
|
+
};
|
|
45
|
+
readonly bottom: {
|
|
46
|
+
readonly x: 0;
|
|
47
|
+
readonly y: -1;
|
|
48
|
+
readonly z: 0;
|
|
49
|
+
};
|
|
50
|
+
readonly right: {
|
|
51
|
+
readonly x: 1;
|
|
52
|
+
readonly y: 0;
|
|
53
|
+
readonly z: 0;
|
|
54
|
+
};
|
|
55
|
+
readonly left: {
|
|
56
|
+
readonly x: -1;
|
|
57
|
+
readonly y: 0;
|
|
58
|
+
readonly z: 0;
|
|
59
|
+
};
|
|
60
|
+
readonly front: {
|
|
61
|
+
readonly x: 0;
|
|
62
|
+
readonly y: 0;
|
|
63
|
+
readonly z: 1;
|
|
64
|
+
};
|
|
65
|
+
readonly back: {
|
|
66
|
+
readonly x: 0;
|
|
67
|
+
readonly y: 0;
|
|
68
|
+
readonly z: -1;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
export type FaceDirection = keyof typeof FACE_DIRECTIONS;
|
|
72
|
+
export declare const FACE_DIRECTION_NAMES: FaceDirection[];
|
|
73
|
+
/** What a shell request can be refused for, independent of how it is said. */
|
|
74
|
+
export type CadShellRefusal = "thickness" | "no-volume" | "no-faces" | "face-index" | "direction" | "no-flat-face" | "every-face-open" | "too-thick" | "cannot-offset";
|
|
75
|
+
export declare class CadShellError extends Error {
|
|
76
|
+
readonly reason: CadShellRefusal;
|
|
77
|
+
/** The HTTP status the REST path answers with. */
|
|
78
|
+
readonly status: number;
|
|
79
|
+
constructor(reason: CadShellRefusal, message: string, status?: number);
|
|
80
|
+
}
|
|
81
|
+
export type CadShellFace = {
|
|
82
|
+
index: number;
|
|
83
|
+
/** As OCCT names the underlying surface: `plane`, `cylinder`, `bspline`... */
|
|
84
|
+
surfaceType: string;
|
|
85
|
+
area: number;
|
|
86
|
+
/** Area-weighted centre of the face, which is a real point on a curved one. */
|
|
87
|
+
centroid: {
|
|
88
|
+
x: number;
|
|
89
|
+
y: number;
|
|
90
|
+
z: number;
|
|
91
|
+
};
|
|
92
|
+
/** The outward normal, or null for a surface that cannot report one. */
|
|
93
|
+
normal: {
|
|
94
|
+
x: number;
|
|
95
|
+
y: number;
|
|
96
|
+
z: number;
|
|
97
|
+
} | null;
|
|
98
|
+
/**
|
|
99
|
+
* The direction name this face answers to, when it is the outermost flat face
|
|
100
|
+
* pointing that way. A cavity floor points up as surely as a lid does, so a
|
|
101
|
+
* face only takes a name if nothing it is parallel to sits further out.
|
|
102
|
+
*/
|
|
103
|
+
facing: FaceDirection | null;
|
|
104
|
+
};
|
|
105
|
+
export type CadShellRequest = {
|
|
106
|
+
/** Wall thickness in mm, measured inwards from the surface. */
|
|
107
|
+
thickness: number;
|
|
108
|
+
/** Faces to leave open, as direction names or face indexes. */
|
|
109
|
+
openFaces?: ReadonlyArray<number | string>;
|
|
110
|
+
};
|
|
111
|
+
/**
|
|
112
|
+
* The normal pointing out of the solid at the middle of a face.
|
|
113
|
+
*
|
|
114
|
+
* Exported because the measurement endpoint needs the same normal to answer
|
|
115
|
+
* "what is the angle between these two faces", and a second copy of this would
|
|
116
|
+
* be free to drift from the one the face listing and the shell request agree on.
|
|
117
|
+
*/
|
|
118
|
+
export declare function faceOutwardNormal(cad: OcctKernel, face: ShapeHandle): Vec3 | null;
|
|
119
|
+
/** A solid's faces in kernel order, with the direction each one answers to. */
|
|
120
|
+
export declare function describeShellFaces(cad: OcctKernel, solid: ShapeHandle): CadShellFace[];
|
|
121
|
+
/**
|
|
122
|
+
* The face indexes a request's `openFaces` names, in listing order.
|
|
123
|
+
*
|
|
124
|
+
* Mixed on purpose: `["top"]` is what a script asking for a tray wants to write,
|
|
125
|
+
* and an index from the listing is the only way to name a face that no direction
|
|
126
|
+
* describes -- one wall of a hexagonal pot, say.
|
|
127
|
+
*/
|
|
128
|
+
export declare function resolveShellOpenFaces(requested: ReadonlyArray<number | string>, faces: ReadonlyArray<Pick<CadShellFace, "index" | "facing">>): number[];
|
|
129
|
+
export declare function shellVolumeOf(cad: OcctKernel, shape: ShapeHandle): number | null;
|
|
130
|
+
/**
|
|
131
|
+
* Hollow `solid` out to a wall of `request.thickness`, leaving `openFaces` off.
|
|
132
|
+
*
|
|
133
|
+
* `faces` is the listing the request's indexes refer to; it is described from
|
|
134
|
+
* the solid when not given. Returns the hollow and the volumes either side of
|
|
135
|
+
* it, or throws a `CadShellError`.
|
|
136
|
+
*/
|
|
137
|
+
export declare function shellSolid(cad: OcctKernel, solid: ShapeHandle, request: CadShellRequest, faces?: CadShellFace[]): {
|
|
138
|
+
solid: ShapeHandle;
|
|
139
|
+
volume: number;
|
|
140
|
+
sourceVolume: number;
|
|
141
|
+
};
|
|
142
|
+
export {};
|
|
143
|
+
//# sourceMappingURL=cadShell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cadShell.d.ts","sourceRoot":"","sources":["../src/cadShell.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAe/D;;;;;;;;GAQG;AACH,QAAA,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAOoB,CAAC;AAE1C,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,eAAe,CAAC;AAEzD,eAAO,MAAM,oBAAoB,EAAmC,aAAa,EAAE,CAAC;AAEpF,8EAA8E;AAC9E,MAAM,MAAM,eAAe,GACvB,WAAW,GACX,WAAW,GACX,UAAU,GACV,YAAY,GACZ,WAAW,GACX,cAAc,GACd,iBAAiB,GACjB,WAAW,GACX,eAAe,CAAC;AAEpB,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,kDAAkD;IAClD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE,eAAe,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,SAAM;CAMnE;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,8EAA8E;IAC9E,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,+EAA+E;IAC/E,QAAQ,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,wEAAwE;IACxE,MAAM,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACnD;;;;OAIG;IACH,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;CAC5C,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,eAanE;AAiBD,+EAA+E;AAC/E,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,GAAG,YAAY,EAAE,CA0CtF;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,GAAG,QAAQ,CAAC,CAAC,YA6B5I;AAQD,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,iBAOhE;AA+FD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,iBAAiC;;;;EAoB/H"}
|