@toolpath/tool-drawing 0.1.0 → 0.3.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/README.md +69 -5
- package/dist/{chunk-OUMNS4RI.js → chunk-WYHJGR7P.js} +116 -64
- package/dist/clearance/index.d.ts +10 -32
- package/dist/clearance/index.js +1 -8
- package/dist/geometry/index.d.ts +54 -32
- package/dist/geometry/index.js +5 -3
- package/dist/index.d.ts +83 -132
- package/dist/index.js +296 -352
- package/dist/{sheet-D0LSO7qP.d.ts → sheet-DicKQYfF.d.ts} +10 -0
- package/package.json +9 -6
package/README.md
CHANGED
|
@@ -14,6 +14,12 @@ in 3D; this one draws a catalog tool in 2D.
|
|
|
14
14
|
npm install @toolpath/tool-drawing react react-dom
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
+
Its one runtime dependency is [`@toolpath/tool-support`](../tool-support), the
|
|
18
|
+
shared cutting-tool domain, which itself depends on nothing. `Provenance`,
|
|
19
|
+
`ViewerTool`, `ViewerHolder` and `ViewerHolderProfile` are aliases of its types
|
|
20
|
+
and are re-exported here, so a consumer that also uses `@toolpath/tool-support`
|
|
21
|
+
gets the same types and needs no adapter between them.
|
|
22
|
+
|
|
17
23
|
## Exports
|
|
18
24
|
|
|
19
25
|
| Entry point | What it is |
|
|
@@ -24,6 +30,7 @@ npm install @toolpath/tool-drawing react react-dom
|
|
|
24
30
|
|
|
25
31
|
`/geometry` is pure and server-safe: it touches no DOM and imports no React, so
|
|
26
32
|
a Node server can measure an assembly without paying for a renderer.
|
|
33
|
+
`tests/subpaths.test.ts` asserts that from the import graph.
|
|
27
34
|
|
|
28
35
|
## Geometry
|
|
29
36
|
|
|
@@ -45,6 +52,30 @@ chamfer. Where a number has to be assumed to draw at all — a drill point angle
|
|
|
45
52
|
the vendor never published — the segment says so in its `provenance`, and a
|
|
46
53
|
renderer is expected to show it.
|
|
47
54
|
|
|
55
|
+
## Two kinds of holder
|
|
56
|
+
|
|
57
|
+
`holder` is a union, and the two members are different inputs rather than two
|
|
58
|
+
grades of one:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
// What a vendor's table states: a nose, a body, a flange.
|
|
62
|
+
holder: { noseDiameter: 28, noseLength: null, gaugeLength: 50, /* … */ }
|
|
63
|
+
|
|
64
|
+
// What the vendor's own CAD model measures: the silhouette, `[z, r]` in mm.
|
|
65
|
+
holder: { points: [[-48.4, 16], /* … */ [60, 8.5]], datum: 'gage-line', /* … */ }
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
A measured profile is **not** projected onto the parametric fields — the
|
|
69
|
+
V-flange groove and the thread relief are the reason to measure at all, and a
|
|
70
|
+
nose diameter and a body length cannot carry them. It is drawn as measured,
|
|
71
|
+
vertex for vertex, with its nose face at the stickout. `isHolderProfile`
|
|
72
|
+
narrows the union for an adapter that holds both.
|
|
73
|
+
|
|
74
|
+
On a `gage-line` profile the drawing splits at `z = 0` — the spindle face — so
|
|
75
|
+
everything above it is shaded as the spindle connection, exactly as the
|
|
76
|
+
parametric flange is. A `nose`-datumed profile has no spindle face to split on
|
|
77
|
+
and no gauge length to state, and the note under the drawing says so.
|
|
78
|
+
|
|
48
79
|
`geometry` keys are the scraper's own field names (`DC`, `SFDM`, `OAL`, `LCF`,
|
|
49
80
|
`RE`, `SIG`, `NOF`, `shoulder-diameter`, `shoulder-length`). They are not
|
|
50
81
|
renamed here: a translation table between two vocabularies is where an `SFDM`
|
|
@@ -68,19 +99,52 @@ as a plausible cylinder.
|
|
|
68
99
|
## Dimensions
|
|
69
100
|
|
|
70
101
|
```tsx
|
|
71
|
-
<ToolDrawing
|
|
102
|
+
<ToolDrawing
|
|
103
|
+
assembly={assembly}
|
|
104
|
+
dimensions
|
|
105
|
+
dimensionSides="both"
|
|
106
|
+
highlight={hovered}
|
|
107
|
+
onDimensionHover={setHovered}
|
|
108
|
+
/>
|
|
72
109
|
```
|
|
73
110
|
|
|
74
111
|
Every stated length and width, each in its own lane, nested shortest-innermost
|
|
75
|
-
so no two lines cross
|
|
76
|
-
|
|
77
|
-
|
|
112
|
+
so no two lines cross. Only stated numbers are dimensioned.
|
|
113
|
+
|
|
114
|
+
**The drawing letters none of them.** The numbers belong in your own table,
|
|
115
|
+
where they can be read; six two-line figures fighting for the margin said the
|
|
116
|
+
same numbers a second time and worse. Which line is which is answered by
|
|
117
|
+
pointing at it instead:
|
|
118
|
+
|
|
119
|
+
- `highlight` names the dimension or dimensions to draw in the sheet's accent,
|
|
120
|
+
by ISO 13399 code — `DC`, `LCF`, `OAL`, `SFDM`, `LBH`, `stickout`, `SIG`, and
|
|
121
|
+
the two `shoulder-` codes. A code the tool does not dimension highlights
|
|
122
|
+
nothing.
|
|
123
|
+
- `onDimensionHover` is told the code under the pointer and `null` when it
|
|
124
|
+
leaves, so your table can be lit from the drawing as well as the other way
|
|
125
|
+
about. Passing it puts hit targets on the lines; leaving it off draws none.
|
|
126
|
+
|
|
127
|
+
Where two codes are one span the drawing carries one line, not two. A shop that
|
|
128
|
+
clamps to its own rule states the stickout and the below-holder length as the
|
|
129
|
+
same number, and a tool stood out to its flutes states it again as the flute
|
|
130
|
+
length; with nothing lettered, identical lines in two lanes cannot be told
|
|
131
|
+
apart. The first code named keeps the line — the tool's own number ahead of the
|
|
132
|
+
shop's — and the others light it too. Hover reports the code the line is drawn
|
|
133
|
+
under.
|
|
134
|
+
|
|
135
|
+
**The stickout is yours.** `assembly.stickout` is where the holder nose goes,
|
|
136
|
+
and nothing here derives it — pass `LBH` as the stickout if standing the tool
|
|
137
|
+
out to its below-holder length is the rule you want drawn. Where the two
|
|
138
|
+
disagree and `LBH` ends up inside the holder, it is not dimensioned: the
|
|
139
|
+
drawing will not run a line to a face it has drawn a holder over.
|
|
140
|
+
|
|
141
|
+
A highlighted line is drawn in the accent **and heavier**, so the highlight
|
|
142
|
+
survives a reader who cannot tell the two colours apart.
|
|
78
143
|
|
|
79
144
|
## Clearance overlay
|
|
80
145
|
|
|
81
146
|
```tsx
|
|
82
147
|
import { ClearanceOverlay, tightestGaps, describeGaps } from '@toolpath/tool-drawing/clearance'
|
|
83
|
-
|
|
84
148
|
;<ToolDrawing assembly={assembly} collisions={collisions} verdict={{ clears, note }}>
|
|
85
149
|
<ClearanceOverlay
|
|
86
150
|
profile={profile}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
// src/model/types.ts
|
|
2
|
+
import { isHolderProfile } from "@toolpath/tool-support";
|
|
3
|
+
|
|
1
4
|
// src/model/outline.ts
|
|
5
|
+
import { hasNeck } from "@toolpath/tool-support";
|
|
2
6
|
var EPSILON = 1e-6;
|
|
3
7
|
var stated = (tool, code) => tool.provenance?.[code] ?? "vendor-stated";
|
|
4
8
|
var arc = (centre, radius, fromDeg, toDeg, steps = 6) => Array.from({ length: steps + 1 }, (_, index) => {
|
|
@@ -9,16 +13,6 @@ var arc = (centre, radius, fromDeg, toDeg, steps = 6) => Array.from({ length: st
|
|
|
9
13
|
z: exact(centre.z + radius * Math.sin(angle))
|
|
10
14
|
};
|
|
11
15
|
});
|
|
12
|
-
var hasNeck = (tool) => {
|
|
13
|
-
const { LCF, SFDM, DC } = tool.geometry;
|
|
14
|
-
const shoulder = tool.geometry["shoulder-length"];
|
|
15
|
-
const relief = tool.geometry["shoulder-diameter"];
|
|
16
|
-
if (shoulder === void 0 || relief === void 0 || LCF === void 0 || shoulder <= LCF) {
|
|
17
|
-
return false;
|
|
18
|
-
}
|
|
19
|
-
const shank = SFDM ?? DC;
|
|
20
|
-
return shank === void 0 ? true : relief < shank - EPSILON;
|
|
21
|
-
};
|
|
22
16
|
var cone = (tool, r, whenUnstated) => {
|
|
23
17
|
const angle = tool.geometry.SIG;
|
|
24
18
|
const half = (angle ?? whenUnstated) / 2 * (Math.PI / 180);
|
|
@@ -96,6 +90,93 @@ var tip = (tool, LCF) => {
|
|
|
96
90
|
return null;
|
|
97
91
|
}
|
|
98
92
|
};
|
|
93
|
+
var profileSegments = (holder, stickout) => {
|
|
94
|
+
const nose = holder.points[holder.points.length - 1];
|
|
95
|
+
if (holder.points.length < 2 || nose === void 0) {
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
const provenance = holder.provenance?.["points"] ?? "vendor-stated";
|
|
99
|
+
const gage = stickout + nose[0];
|
|
100
|
+
const up = [...holder.points].reverse().map(([z, r]) => ({ r, z: stickout + (nose[0] - z) }));
|
|
101
|
+
const cut = holder.datum === "gage-line" ? up.findIndex((point) => point.z > gage) : -1;
|
|
102
|
+
if (cut <= 0) {
|
|
103
|
+
return [{ part: "body", points: up, provenance }];
|
|
104
|
+
}
|
|
105
|
+
const below = up.slice(0, cut);
|
|
106
|
+
const above = up.slice(cut);
|
|
107
|
+
const last = below[below.length - 1];
|
|
108
|
+
const first = above[0];
|
|
109
|
+
const meet = last.z === gage ? last : {
|
|
110
|
+
r: last.r + (gage - last.z) / (first.z - last.z) * (first.r - last.r),
|
|
111
|
+
z: gage
|
|
112
|
+
};
|
|
113
|
+
if (meet !== last) {
|
|
114
|
+
below.push(meet);
|
|
115
|
+
}
|
|
116
|
+
above.unshift(meet);
|
|
117
|
+
return [
|
|
118
|
+
{ part: "body", points: below, provenance },
|
|
119
|
+
{ part: "flange", points: above, provenance }
|
|
120
|
+
];
|
|
121
|
+
};
|
|
122
|
+
var parametricSegments = (holder, stickout, DC) => {
|
|
123
|
+
if (holder.noseDiameter === null) {
|
|
124
|
+
return [];
|
|
125
|
+
}
|
|
126
|
+
const segments = [];
|
|
127
|
+
const rh = holder.noseDiameter / 2;
|
|
128
|
+
const holderStated = (code) => holder.provenance?.[code] ?? "vendor-stated";
|
|
129
|
+
let top = stickout;
|
|
130
|
+
const noseLength = holder.noseLength ?? holder.gaugeLength ?? Math.max(20, DC * 3);
|
|
131
|
+
segments.push({
|
|
132
|
+
part: "nose",
|
|
133
|
+
points: [
|
|
134
|
+
{ r: rh, z: stickout },
|
|
135
|
+
{ r: rh, z: stickout + noseLength }
|
|
136
|
+
],
|
|
137
|
+
provenance: holder.noseLength !== null ? holderStated("noseLength") : holder.gaugeLength === null ? "assumed" : holderStated("noseDiameter")
|
|
138
|
+
});
|
|
139
|
+
top = stickout + noseLength;
|
|
140
|
+
let radius = rh;
|
|
141
|
+
if (holder.bodyDiameter !== null && holder.bodyLength !== null) {
|
|
142
|
+
const rb = holder.bodyDiameter / 2;
|
|
143
|
+
segments.push({
|
|
144
|
+
part: "body",
|
|
145
|
+
points: [
|
|
146
|
+
{ r: rb, z: top },
|
|
147
|
+
{ r: rb, z: top + holder.bodyLength }
|
|
148
|
+
],
|
|
149
|
+
provenance: holderStated("bodyDiameter")
|
|
150
|
+
});
|
|
151
|
+
top += holder.bodyLength;
|
|
152
|
+
radius = rb;
|
|
153
|
+
}
|
|
154
|
+
if (holder.projection !== null && holder.flangeDiameter !== null) {
|
|
155
|
+
const flangeAt = stickout + holder.projection;
|
|
156
|
+
const rf = holder.flangeDiameter / 2;
|
|
157
|
+
if (flangeAt > top) {
|
|
158
|
+
segments.push({
|
|
159
|
+
part: "body",
|
|
160
|
+
points: [
|
|
161
|
+
{ r: radius, z: top },
|
|
162
|
+
{ r: radius, z: flangeAt }
|
|
163
|
+
],
|
|
164
|
+
provenance: "assumed"
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
const flangeTop = holder.gaugeLength !== null && holder.gaugeLength > holder.projection ? stickout + holder.gaugeLength : flangeAt + 20;
|
|
168
|
+
segments.push({
|
|
169
|
+
part: "flange",
|
|
170
|
+
points: [
|
|
171
|
+
{ r: rf, z: flangeAt },
|
|
172
|
+
{ r: rf, z: flangeTop }
|
|
173
|
+
],
|
|
174
|
+
provenance: holder.gaugeLength === null ? "assumed" : holderStated("flangeDiameter")
|
|
175
|
+
});
|
|
176
|
+
top = flangeTop;
|
|
177
|
+
}
|
|
178
|
+
return segments;
|
|
179
|
+
};
|
|
99
180
|
var assemblyOutline = (assembly) => {
|
|
100
181
|
const { tool, holder, stickout } = assembly;
|
|
101
182
|
const { DC, LCF, SFDM } = tool.geometry;
|
|
@@ -151,9 +232,8 @@ var assemblyOutline = (assembly) => {
|
|
|
151
232
|
});
|
|
152
233
|
top = shankTop;
|
|
153
234
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
const holderStated = (code) => holder.provenance?.[code] ?? "vendor-stated";
|
|
235
|
+
const holderSegments = stickout === null || holder === null ? [] : isHolderProfile(holder) ? profileSegments(holder, stickout) : parametricSegments(holder, stickout, DC);
|
|
236
|
+
if (stickout !== null && holder !== null && holderSegments.length > 0) {
|
|
157
237
|
const series = /(\d+(?:\.\d+)?)/.exec(holder.colletSeries ?? "");
|
|
158
238
|
if (holder.colletProtrusion !== null && series) {
|
|
159
239
|
const rc = Number(series[1]) / 2;
|
|
@@ -163,63 +243,35 @@ var assemblyOutline = (assembly) => {
|
|
|
163
243
|
{ r: rc, z: stickout - holder.colletProtrusion },
|
|
164
244
|
{ r: rc, z: stickout }
|
|
165
245
|
],
|
|
166
|
-
provenance:
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
const noseLength = holder.noseLength ?? holder.gaugeLength ?? Math.max(20, DC * 3);
|
|
170
|
-
segments.push({
|
|
171
|
-
part: "nose",
|
|
172
|
-
points: [
|
|
173
|
-
{ r: rh, z: stickout },
|
|
174
|
-
{ r: rh, z: stickout + noseLength }
|
|
175
|
-
],
|
|
176
|
-
provenance: holder.noseLength !== null ? holderStated("noseLength") : holder.gaugeLength === null ? "assumed" : holderStated("noseDiameter")
|
|
177
|
-
});
|
|
178
|
-
top = stickout + noseLength;
|
|
179
|
-
let radius2 = rh;
|
|
180
|
-
if (holder.bodyDiameter !== null && holder.bodyLength !== null) {
|
|
181
|
-
const rb = holder.bodyDiameter / 2;
|
|
182
|
-
segments.push({
|
|
183
|
-
part: "body",
|
|
184
|
-
points: [
|
|
185
|
-
{ r: rb, z: top },
|
|
186
|
-
{ r: rb, z: top + holder.bodyLength }
|
|
187
|
-
],
|
|
188
|
-
provenance: holderStated("bodyDiameter")
|
|
246
|
+
provenance: holder.provenance?.["colletProtrusion"] ?? "vendor-stated"
|
|
189
247
|
});
|
|
190
|
-
top += holder.bodyLength;
|
|
191
|
-
radius2 = rb;
|
|
192
|
-
}
|
|
193
|
-
if (holder.projection !== null && holder.flangeDiameter !== null) {
|
|
194
|
-
const flangeAt = stickout + holder.projection;
|
|
195
|
-
const rf = holder.flangeDiameter / 2;
|
|
196
|
-
if (flangeAt > top) {
|
|
197
|
-
segments.push({
|
|
198
|
-
part: "body",
|
|
199
|
-
points: [
|
|
200
|
-
{ r: radius2, z: top },
|
|
201
|
-
{ r: radius2, z: flangeAt }
|
|
202
|
-
],
|
|
203
|
-
provenance: "assumed"
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
const flangeTop = holder.gaugeLength !== null && holder.gaugeLength > holder.projection ? stickout + holder.gaugeLength : flangeAt + 20;
|
|
207
|
-
segments.push({
|
|
208
|
-
part: "flange",
|
|
209
|
-
points: [
|
|
210
|
-
{ r: rf, z: flangeAt },
|
|
211
|
-
{ r: rf, z: flangeTop }
|
|
212
|
-
],
|
|
213
|
-
provenance: holder.gaugeLength === null ? "assumed" : holderStated("flangeDiameter")
|
|
214
|
-
});
|
|
215
|
-
top = flangeTop;
|
|
216
248
|
}
|
|
249
|
+
segments.push(...holderSegments);
|
|
250
|
+
top = holderSegments[holderSegments.length - 1].points.at(-1)?.z ?? top;
|
|
217
251
|
}
|
|
218
252
|
const radius = Math.max(...segments.flatMap((segment) => segment.points.map((point2) => point2.r)));
|
|
219
253
|
return { segments, height: top, radius };
|
|
220
254
|
};
|
|
255
|
+
var edgeRadius = (from, to, z) => {
|
|
256
|
+
const low = Math.min(from.z, to.z);
|
|
257
|
+
const high = Math.max(from.z, to.z);
|
|
258
|
+
if (z < low - EPSILON || z > high + EPSILON) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
if (high - low <= EPSILON) {
|
|
262
|
+
return Math.max(from.r, to.r);
|
|
263
|
+
}
|
|
264
|
+
return from.r + (z - from.z) / (to.z - from.z) * (to.r - from.r);
|
|
265
|
+
};
|
|
266
|
+
var radiusAt = (outline, z) => Math.max(
|
|
267
|
+
0,
|
|
268
|
+
...outline.segments.flatMap(
|
|
269
|
+
(segment) => segment.points.slice(1).map((point, index) => edgeRadius(segment.points[index], point, z)).filter((radius) => radius !== null)
|
|
270
|
+
)
|
|
271
|
+
);
|
|
221
272
|
|
|
222
273
|
export {
|
|
223
|
-
|
|
224
|
-
assemblyOutline
|
|
274
|
+
isHolderProfile,
|
|
275
|
+
assemblyOutline,
|
|
276
|
+
radiusAt
|
|
225
277
|
};
|
|
@@ -1,47 +1,25 @@
|
|
|
1
|
+
import { ReachCurve } from '@toolpath/tool-support';
|
|
2
|
+
export { ReachCurve, heightAt } from '@toolpath/tool-support';
|
|
1
3
|
import { OutlinePart, OutlineSegment, OutlinePoint } from '../geometry/index.js';
|
|
2
4
|
import * as react from 'react';
|
|
3
|
-
import { F as Frame, E as Extent, S as Sheet } from '../sheet-
|
|
5
|
+
import { F as Frame, E as Extent, S as Sheet } from '../sheet-DicKQYfF.js';
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* The feature's reach curve, and how the drawing reads it.
|
|
7
9
|
*
|
|
8
|
-
* **
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* **Still declared structurally, one package up.** `@toolpath/tool-support`
|
|
11
|
+
* names the shape and imports no Toolpath schema to do it, which is one of the
|
|
12
|
+
* three senses in which this overlay stays optional: a consumer that draws a
|
|
13
|
+
* tool alone pulls in no OpenAPI contract. A `ReachCurve` off a report
|
|
14
|
+
* satisfies it by structure, with no adapter, exactly as before.
|
|
13
15
|
*/
|
|
14
|
-
|
|
15
|
-
* The worst-case material around a feature, as a staircase.
|
|
16
|
-
*
|
|
17
|
-
* Read as "material within `horizontalOffset[i]` of the cut rises to
|
|
18
|
-
* `verticalOffset[i]`". Both are in millimetres; the offsets run outward from
|
|
19
|
-
* the cutting edge and the heights up from the bottom of the feature.
|
|
20
|
-
*/
|
|
21
|
-
interface ReachCurve {
|
|
22
|
-
readonly horizontalOffset: ReadonlyArray<number>;
|
|
23
|
-
readonly verticalOffset: ReadonlyArray<number>;
|
|
24
|
-
}
|
|
16
|
+
|
|
25
17
|
/** Room the shop wants kept between the stack and the part, in millimetres. */
|
|
26
18
|
interface Margins {
|
|
27
19
|
readonly radial: number;
|
|
28
20
|
readonly axial: number;
|
|
29
21
|
}
|
|
30
22
|
declare const NO_MARGINS: Margins;
|
|
31
|
-
/**
|
|
32
|
-
* The tallest material within `offset` mm of the cut, above the feature's bottom.
|
|
33
|
-
*
|
|
34
|
-
* **The one piece of the verdict's own arithmetic that had to travel.** The
|
|
35
|
-
* decision — whether an assembly clears — stays with the catalog's
|
|
36
|
-
* tool-selection engine, which has a dozen callers that never draw anything.
|
|
37
|
-
* This is not that decision: it is the reading of the curve that the drawn
|
|
38
|
-
* staircase is drawn from, and the gaps this overlay dimensions are measured
|
|
39
|
-
* against. It is here because {@link tightestGaps} cannot be written without
|
|
40
|
-
* it, and it must keep agreeing with whatever draws the material profile — the
|
|
41
|
-
* rise comes at the *start* of each run, so everything out to a knot is
|
|
42
|
-
* already as tall as that knot says.
|
|
43
|
-
*/
|
|
44
|
-
declare const heightAt: (curve: ReachCurve, offset: number) => number;
|
|
45
23
|
/**
|
|
46
24
|
* Where the wall face stands at a given height, as an offset from the cut:
|
|
47
25
|
* the start of the first run of the staircase that rises above that height.
|
|
@@ -202,4 +180,4 @@ declare const ClearanceOverlay: ({ profile, frame: framed, outline: extent, cutt
|
|
|
202
180
|
*/
|
|
203
181
|
declare const describeGaps: (gaps: Gaps, margins: Margins, formatLength: (millimetres: number) => string) => string | null;
|
|
204
182
|
|
|
205
|
-
export { type AxialGap, ClearanceOverlay, type ClearanceOverlayProps, type Gap, type Gaps, type Margins, NO_MARGINS,
|
|
183
|
+
export { type AxialGap, ClearanceOverlay, type ClearanceOverlayProps, type Gap, type Gaps, type Margins, NO_MARGINS, clipped, describeGaps, lastRise, tightestGaps, wallCorners, wallFaceAt, wallPath, zigzag };
|
package/dist/clearance/index.js
CHANGED
|
@@ -8,16 +8,9 @@ import {
|
|
|
8
8
|
} from "../chunk-7ZID4QRO.js";
|
|
9
9
|
|
|
10
10
|
// src/clearance/model/curve.ts
|
|
11
|
+
import { heightAt } from "@toolpath/tool-support";
|
|
11
12
|
var NO_MARGINS = { radial: 0, axial: 0 };
|
|
12
13
|
var GAP_TOLERANCE = 1e-6;
|
|
13
|
-
var heightAt = (curve, offset) => {
|
|
14
|
-
for (let index = 0; index < curve.horizontalOffset.length; index += 1) {
|
|
15
|
-
if ((curve.horizontalOffset[index] ?? 0) >= offset) {
|
|
16
|
-
return curve.verticalOffset[index] ?? 0;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
return curve.verticalOffset[curve.verticalOffset.length - 1] ?? 0;
|
|
20
|
-
};
|
|
21
14
|
var wallFaceAt = (curve, z) => {
|
|
22
15
|
let from = 0;
|
|
23
16
|
for (let index = 0; index < curve.horizontalOffset.length; index += 1) {
|
package/dist/geometry/index.d.ts
CHANGED
|
@@ -1,44 +1,66 @@
|
|
|
1
|
+
import { Tool, Holder, HolderProfile, Provenance } from '@toolpath/tool-support';
|
|
2
|
+
export { Provenance, isHolderProfile } from '@toolpath/tool-support';
|
|
3
|
+
|
|
1
4
|
/**
|
|
2
|
-
* What this package needs to draw an assembly
|
|
5
|
+
* What this package needs to draw an assembly — which is the shared cutting-tool
|
|
6
|
+
* domain, under the names this package has always published.
|
|
7
|
+
*
|
|
8
|
+
* These four were declared here until `@toolpath/tool-support` existed, and the
|
|
9
|
+
* declarations were three-way duplicates: the same provenance strings, the same
|
|
10
|
+
* geometry codes and three shapes called "holder" of which no two agreed on
|
|
11
|
+
* which fields exist. A drawing and the number printed beside it were free to
|
|
12
|
+
* disagree about one tool, and once did — the stickout the details table showed
|
|
13
|
+
* was not the stickout the dimension line drew.
|
|
14
|
+
*
|
|
15
|
+
* So the shapes now come from the one declaration and these are **aliases**,
|
|
16
|
+
* exported from `.` and from `/geometry` exactly as before. A consumer's adapter
|
|
17
|
+
* does not move: `ViewerTool` is `Tool`, and a catalog record that satisfied one
|
|
18
|
+
* satisfies the other by structure.
|
|
19
|
+
*
|
|
20
|
+
* ## Why the alias and not a rename
|
|
3
21
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
22
|
+
* A consumer's adapter is the single file that fails loudly when either side
|
|
23
|
+
* moves, and renaming the type it targets would be that failure for no gain. The
|
|
24
|
+
* `Viewer*` names are also what the two entry points publish, so dropping them
|
|
25
|
+
* is a major bump this change has no reason to spend. `@toolpath/tool-support`
|
|
26
|
+
* is where the domain is documented; this file is the seam.
|
|
8
27
|
*
|
|
9
|
-
* `geometry` keeps the scraper's own field names — `DC`, `SFDM`, `OAL`,
|
|
10
|
-
* `RE`, `SIG`, `NOF`, `shoulder-diameter`, `shoulder-length
|
|
11
|
-
*
|
|
12
|
-
*
|
|
28
|
+
* `geometry` still keeps the scraper's own field names — `DC`, `SFDM`, `OAL`,
|
|
29
|
+
* `LCF`, `RE`, `SIG`, `NOF`, `shoulder-diameter`, `shoulder-length` — and
|
|
30
|
+
* `@toolpath/tool-support`'s `GEOMETRY_FIELDS` is now the dictionary behind
|
|
31
|
+
* them.
|
|
13
32
|
*
|
|
14
33
|
* All lengths are in millimetres and all angles in degrees, and every generator
|
|
15
34
|
* works in whatever unit system it is handed: an inch tool yields an inch
|
|
16
35
|
* outline. Converting is the caller's, at the seam where a tool meets a holder.
|
|
17
36
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
|
|
38
|
+
/** A cutting tool, as the drawing needs one. */
|
|
39
|
+
type ViewerTool = Tool;
|
|
40
|
+
/** A holder as its vendor publishes it: a nose, a body, a projection. */
|
|
41
|
+
type ViewerHolder = Holder;
|
|
42
|
+
/**
|
|
43
|
+
* A holder as its own CAD model measures it: the silhouette, and nothing
|
|
44
|
+
* parametric.
|
|
45
|
+
*
|
|
46
|
+
* Not a refinement of {@link ViewerHolder} and it does not project onto one —
|
|
47
|
+
* reducing a measured envelope to a nose and a body throws away the only reason
|
|
48
|
+
* to measure. The two are a union and {@link isHolderProfile} tells them apart;
|
|
49
|
+
* a consumer that has neither passes `null` and the tool is drawn alone.
|
|
50
|
+
*/
|
|
51
|
+
type ViewerHolderProfile = HolderProfile;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* A tool, the holder it is clamped in, and how far it stands out.
|
|
55
|
+
*
|
|
56
|
+
* Deliberately **not** `@toolpath/tool-support`'s `Assembly`, which also carries
|
|
57
|
+
* the collet: a drawing reads a collet only through the holder's own series and
|
|
58
|
+
* protrusion, and taking one it never reads would be a field every adapter has
|
|
59
|
+
* to fill for nothing.
|
|
60
|
+
*/
|
|
39
61
|
interface ViewerAssembly {
|
|
40
62
|
readonly tool: ViewerTool;
|
|
41
|
-
readonly holder: ViewerHolder | null;
|
|
63
|
+
readonly holder: ViewerHolder | ViewerHolderProfile | null;
|
|
42
64
|
/**
|
|
43
65
|
* How far the tool stands out of the holder nose, in millimetres — the
|
|
44
66
|
* shop's number, nobody's else. Null draws the tool alone.
|
|
@@ -99,4 +121,4 @@ interface Outline {
|
|
|
99
121
|
*/
|
|
100
122
|
declare const assemblyOutline: (assembly: ViewerAssembly) => Outline | null;
|
|
101
123
|
|
|
102
|
-
export { type Outline, type OutlinePart, type OutlinePoint, type OutlineSegment, type
|
|
124
|
+
export { type Outline, type OutlinePart, type OutlinePoint, type OutlineSegment, type ViewerAssembly, type ViewerHolder, type ViewerHolderProfile, type ViewerTool, assemblyOutline };
|