@toolpath/dfm 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +97 -2
- package/dfm.css +9 -0
- package/dist/chunk-5MPHT7BC.js +1599 -0
- package/dist/index.d.ts +117 -0
- package/dist/index.js +1628 -0
- package/dist/model/index.d.ts +109 -0
- package/dist/model/index.js +775 -0
- package/dist/reach-CfmYU_yQ.d.ts +415 -0
- package/package.json +72 -3
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
/** The unit a length is shown in. The Engine's meshes are always millimetres. */
|
|
2
|
+
type Units = 'mm' | 'inch';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* At or above, above, at or below, below, equal, not equal, or between —
|
|
6
|
+
* equal meaning within half a percent, since figures are measured, and not
|
|
7
|
+
* equal anything further off; between from a low end up to, not including, a
|
|
8
|
+
* high one.
|
|
9
|
+
*/
|
|
10
|
+
type DfmOp = 'gte' | 'gt' | 'lte' | 'lt' | 'eq' | 'ne' | 'between';
|
|
11
|
+
/**
|
|
12
|
+
* How a figure is read and typed: a length (mm), an area (mm²), an angle
|
|
13
|
+
* (degrees), a plain ratio, a count, a percentage, yes/no, or — for "any
|
|
14
|
+
* size" — nothing at all.
|
|
15
|
+
*/
|
|
16
|
+
type DfmQuantity = 'length' | 'area' | 'angle' | 'ratio' | 'count' | 'percent' | 'flag' | 'presence';
|
|
17
|
+
/** A datasheet's `facts.kind`: which family of measurements the Engine took. */
|
|
18
|
+
type FactsKind = 'Hole' | 'Pocket' | 'Boss' | 'Wall' | 'Face' | 'Three' | 'Chamfer' | 'Profile' | 'Dovetail' | 'Tslot';
|
|
19
|
+
interface DfmMetric {
|
|
20
|
+
key: string;
|
|
21
|
+
/** As the rule sentence reads it: "L/D", "depth below top". */
|
|
22
|
+
label: string;
|
|
23
|
+
/** The heading it is listed under when choosing. */
|
|
24
|
+
group: string;
|
|
25
|
+
quantity: DfmQuantity;
|
|
26
|
+
/** Which way is worse, for a new rule: deep is bad (≥), a tiny corner is bad (≤). */
|
|
27
|
+
op: DfmOp;
|
|
28
|
+
/** What a new rule starts at: millimetres and inches kept apart, so both read as round numbers. */
|
|
29
|
+
start: Record<Units, number>;
|
|
30
|
+
/** What it means, in a few plain words. */
|
|
31
|
+
hint: string;
|
|
32
|
+
/** The kinds of datasheet that report it; every kind when left out. */
|
|
33
|
+
kinds?: readonly FactsKind[];
|
|
34
|
+
/**
|
|
35
|
+
* Where it sits in the datasheet, first found wins: a chamfer keeps its
|
|
36
|
+
* cutter band under its surface reading (`facts.three.cd`). Left out for a
|
|
37
|
+
* measure worked out rather than read (see `dfm-flags.ts`).
|
|
38
|
+
*/
|
|
39
|
+
path?: readonly string[];
|
|
40
|
+
/** Whether a rule may name a value below zero: a height, or a signed radius. */
|
|
41
|
+
signed?: true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** How a range holds its low end: at or above it, or above it. */
|
|
45
|
+
type RangeLow = 'gte' | 'gt';
|
|
46
|
+
/** How a range holds its high end: below it, or at or below it. */
|
|
47
|
+
type RangeHigh = 'lt' | 'lte';
|
|
48
|
+
interface DfmRule {
|
|
49
|
+
/** Stable, so a list can key its rows and a feature can name the rule it broke. */
|
|
50
|
+
id: string;
|
|
51
|
+
/** Which features: a value from {@link FEATURE_SUBJECTS}. */
|
|
52
|
+
subject: string;
|
|
53
|
+
/** What is measured: a key from {@link FEATURE_METRICS}. */
|
|
54
|
+
metric: string;
|
|
55
|
+
op: DfmOp;
|
|
56
|
+
/** Canonical — mm or a ratio. Ignored by a yes/no metric. The low end of a range. */
|
|
57
|
+
value: number;
|
|
58
|
+
/** A range's high end. Only a `between` rule has one. */
|
|
59
|
+
max?: number;
|
|
60
|
+
/** How a range holds its low end; ≥ where unsaid. Only a `between` rule has one. */
|
|
61
|
+
lowOp?: RangeLow;
|
|
62
|
+
/** How a range holds its high end; < where unsaid. Only a `between` rule has one. */
|
|
63
|
+
highOp?: RangeHigh;
|
|
64
|
+
/** `#rrggbb`: what the features that break it are painted. */
|
|
65
|
+
color: string;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* The colours a rule can wear: vivid, and far enough apart in hue and
|
|
69
|
+
* lightness to tell apart on the part at a glance (no two closer than ΔE 37,
|
|
70
|
+
* and none within 50 of the selection's blue). Warm first, since most
|
|
71
|
+
* rules call out trouble; then cool ones for a rule that marks something
|
|
72
|
+
* good.
|
|
73
|
+
*/
|
|
74
|
+
declare const RULE_COLORS: readonly {
|
|
75
|
+
name: string;
|
|
76
|
+
value: string;
|
|
77
|
+
}[];
|
|
78
|
+
/**
|
|
79
|
+
* Which colour shows where a feature breaks rules of two: the one earliest in
|
|
80
|
+
* the palette, so red over yellow. Colours from outside it come after, in an
|
|
81
|
+
* order of their own, so a tie never falls back on the list.
|
|
82
|
+
*/
|
|
83
|
+
declare const compareColors: (a: string, b: string) => number;
|
|
84
|
+
/** The quoting app's two severities, as the colours a rule starts in. */
|
|
85
|
+
declare const CRITICAL_COLOR = "#e5484d";
|
|
86
|
+
declare const WARNING_COLOR = "#ffd60a";
|
|
87
|
+
/**
|
|
88
|
+
* A rule as one plain line: "Holes with L/D ≥ 8", "Holes with 4 ≤ L/D < 8",
|
|
89
|
+
* "Any feature with a sharp inside corner", "Undercut T-slots, any size".
|
|
90
|
+
*/
|
|
91
|
+
declare const describeRule: (rule: DfmRule, units: Units) => string;
|
|
92
|
+
/** A new rule for a subject and metric, at the metric's own starting value in the reader's units. */
|
|
93
|
+
declare const makeRule: (subject: string, metricKey: string, units: Units, color?: string) => DfmRule;
|
|
94
|
+
/** Stored rules, the ones that read; null when what is stored is not a list at all. */
|
|
95
|
+
declare const parseRules: (raw: unknown) => DfmRule[] | null;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Where a feature is at its tightest (the datasheet's `pinchPoints`, API
|
|
99
|
+
* 1.12.1): one disc per stretch of the feature that reaches its minimum
|
|
100
|
+
* clearance, tightest first and never more than ten.
|
|
101
|
+
*
|
|
102
|
+
* As the API defines it, a disc fits in the space the clearance was measured
|
|
103
|
+
* in and touches the feature's boundary, so a cylinder of its diameter
|
|
104
|
+
* standing at its centre and spanning the datasheet's `zMin`..`zMax` is
|
|
105
|
+
* exactly the widest tool that reaches the boundary there. That is what makes
|
|
106
|
+
* them drawable: each is the tool the feature allows, standing where the
|
|
107
|
+
* feature stops a larger one.
|
|
108
|
+
*
|
|
109
|
+
* The Engine measures each disc to a tolerance (`toleranceBand.atolIgnore`),
|
|
110
|
+
* which lets it read a little wider than the gap it sits in. The discs here
|
|
111
|
+
* have that slack taken out (see {@link clearanceFit}), so each is the
|
|
112
|
+
* clearance itself: in a 2.5 mm corner, a 5 mm disc.
|
|
113
|
+
*
|
|
114
|
+
* Empty for the kinds whose clearance is not measured off a single medial
|
|
115
|
+
* axis (a hole, a facing pass, the undercut and layered kinds), so empty is
|
|
116
|
+
* "nowhere to point at", never "nowhere is tight".
|
|
117
|
+
*
|
|
118
|
+
* Millimetres, in the datasheet's tool frame: x and y across the tool, z up
|
|
119
|
+
* it.
|
|
120
|
+
*/
|
|
121
|
+
/** One disc: its centre across the tool, and its diameter. */
|
|
122
|
+
interface PinchDisc {
|
|
123
|
+
x: number;
|
|
124
|
+
y: number;
|
|
125
|
+
diameter: number;
|
|
126
|
+
}
|
|
127
|
+
/** A feature's pinch discs, and the band along the tool they stand through. */
|
|
128
|
+
interface FeaturePinch {
|
|
129
|
+
discs: readonly PinchDisc[];
|
|
130
|
+
zMin: number;
|
|
131
|
+
zMax: number;
|
|
132
|
+
/**
|
|
133
|
+
* The Engine measured the clearance at one tolerance only, so the slack
|
|
134
|
+
* could not be taken out: each disc is as measured, the most the clearance
|
|
135
|
+
* can be.
|
|
136
|
+
*/
|
|
137
|
+
unresolved?: true;
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* The figures a feature's clearance is run back from, as the datasheet has
|
|
141
|
+
* them: the widest tool that reaches every point (`min` of the cutter band,
|
|
142
|
+
* which is also its tightest pinch disc) at the strict tolerance, and at the
|
|
143
|
+
* looser one where the Engine reports it.
|
|
144
|
+
*/
|
|
145
|
+
interface ClearanceFit {
|
|
146
|
+
/** `facts.cd`, or `facts.three.cd` for a chamfer. */
|
|
147
|
+
bandPath: string;
|
|
148
|
+
strict: number;
|
|
149
|
+
loose?: number;
|
|
150
|
+
atStrict?: number;
|
|
151
|
+
atLoose?: number;
|
|
152
|
+
/**
|
|
153
|
+
* How much wider, mm, the tolerance lets the widest tool read than the
|
|
154
|
+
* clearance it fits: what to take off a measured disc. Zero where the
|
|
155
|
+
* Engine measured at one tolerance only (`resolved` false), or where the
|
|
156
|
+
* tool does not grow with tolerance (a gap between walls, not a corner).
|
|
157
|
+
*/
|
|
158
|
+
slack: number;
|
|
159
|
+
resolved: boolean;
|
|
160
|
+
}
|
|
161
|
+
/** A datasheet's pinch discs, the tolerance taken out of each, or null where it has none to draw. */
|
|
162
|
+
declare const readPinch: (datasheet: unknown) => FeaturePinch | null;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* The few numbers of a feature's datasheet that the DFM rules and the
|
|
166
|
+
* feature details read. All millimetres, as the Engine reports them. Each is
|
|
167
|
+
* left out where this kind of feature does not report it, rather than sent as
|
|
168
|
+
* a zero that reads as measured.
|
|
169
|
+
*
|
|
170
|
+
* From the quoting app (quoting-ui `server/lib/engine.ts`). A datasheet is
|
|
171
|
+
* large, so the worker cuts each one down to this before it sends it.
|
|
172
|
+
*/
|
|
173
|
+
interface FeatureSheet {
|
|
174
|
+
/** The Engine's family for it: `Hole`, `Pocket`, … */
|
|
175
|
+
kind?: string;
|
|
176
|
+
/** Along the machining direction, the feature's own bottom and top. */
|
|
177
|
+
zMin?: number;
|
|
178
|
+
zMax?: number;
|
|
179
|
+
/** Its top extended to the stock, which the highest of stands in for the part's top. */
|
|
180
|
+
extendedZMax?: number;
|
|
181
|
+
/** The widest cutter that still reaches the tightest corner. */
|
|
182
|
+
maxTool?: number;
|
|
183
|
+
diameter?: number;
|
|
184
|
+
/** For a hole: the full angle of the cone at its bottom, degrees; 180 for a flat bottom. */
|
|
185
|
+
tipAngle?: number;
|
|
186
|
+
filletRadius?: number;
|
|
187
|
+
chamferAngle?: number;
|
|
188
|
+
/**
|
|
189
|
+
* For a milled feature with walls: the radius of its tightest inside corner
|
|
190
|
+
* between walls, as the geometry has it rather than as a tool reaches it —
|
|
191
|
+
* zero for a sharp one. Half its minimum clearance: see {@link insideCornerRadius}.
|
|
192
|
+
*/
|
|
193
|
+
cornerRadius?: number;
|
|
194
|
+
/**
|
|
195
|
+
* The Engine measured the clearance at one tolerance only, so neither
|
|
196
|
+
* `cornerRadius` nor `pinchDiameter` could be run back to none: each is as
|
|
197
|
+
* a tool reads it at that tolerance, the most the clearance can be.
|
|
198
|
+
*/
|
|
199
|
+
cornerRadiusUnresolved?: true;
|
|
200
|
+
/** What the clearance was worked out from, so a reader can follow it. See {@link ClearanceFit}. */
|
|
201
|
+
clearance?: ClearanceFit;
|
|
202
|
+
/**
|
|
203
|
+
* A vertical inside corner between its walls with no radius, which no end
|
|
204
|
+
* mill makes; and where, in the datasheet's tool frame (x, y across the
|
|
205
|
+
* tool; its `zMin`..`zMax` along it).
|
|
206
|
+
*/
|
|
207
|
+
sharpCorners?: readonly {
|
|
208
|
+
x: number;
|
|
209
|
+
y: number;
|
|
210
|
+
}[];
|
|
211
|
+
/**
|
|
212
|
+
* For a contour surface: the largest tool its shape admits (`facts.toolFit`)
|
|
213
|
+
* — its diameter, and the radius on its corner, no larger than the
|
|
214
|
+
* surface's tightest concave curve; half the diameter for a ball.
|
|
215
|
+
*/
|
|
216
|
+
fitToolDiameter?: number;
|
|
217
|
+
fitCornerRadius?: number;
|
|
218
|
+
/** Where the tool fit was read: `facts.toolFit` or `facts.three.toolFit`. */
|
|
219
|
+
toolFitPath?: string;
|
|
220
|
+
/** For a contour surface: only a ball end mill can finish it, not a bull nose. */
|
|
221
|
+
ballOnly?: true;
|
|
222
|
+
/**
|
|
223
|
+
* The feature's minimum clearance: the smallest of its pinch discs
|
|
224
|
+
* (`pinchPoints`), the tolerance taken out, leaving out the zero-wide ones
|
|
225
|
+
* a sharp corner reports. The widest tool that fits where it is tightest,
|
|
226
|
+
* and what a milled feature's L/D is taken over.
|
|
227
|
+
*/
|
|
228
|
+
pinchDiameter?: number;
|
|
229
|
+
/** How many places are that tight: the pinch discs counted in `pinchDiameter`. */
|
|
230
|
+
pinchPlaces?: number;
|
|
231
|
+
/** No cutter fits anywhere in the feature. */
|
|
232
|
+
noToolFits?: true;
|
|
233
|
+
/** For a hole the model threads: its thread. */
|
|
234
|
+
threading?: FeatureThreading;
|
|
235
|
+
}
|
|
236
|
+
/** A modelled thread, from a hole's `facts.threading`. Millimetres. */
|
|
237
|
+
interface FeatureThreading {
|
|
238
|
+
basicDiameter: number;
|
|
239
|
+
threadPitch: number;
|
|
240
|
+
}
|
|
241
|
+
/** Feature tag, lower-cased → its sheet. */
|
|
242
|
+
type FeatureSheets = Record<string, FeatureSheet>;
|
|
243
|
+
/** Narrower than this, mm, a pinch disc is a sharp corner, which no tool fits: not a pinch tool. */
|
|
244
|
+
declare const PINCH_TOOL_MM = 0.01;
|
|
245
|
+
/** A feature that is no reading of its faces at all, which the analysis leaves out. */
|
|
246
|
+
declare const isNoReading: (featureType: unknown, datasheet: unknown) => boolean;
|
|
247
|
+
/** One datasheet, cut down to what the rules read. Read loosely: kinds report different fields. */
|
|
248
|
+
declare const featureSheet: (datasheet: unknown) => FeatureSheet;
|
|
249
|
+
|
|
250
|
+
type Direction = {
|
|
251
|
+
readonly x: number;
|
|
252
|
+
readonly y: number;
|
|
253
|
+
readonly z: number;
|
|
254
|
+
};
|
|
255
|
+
/**
|
|
256
|
+
* A feature as the Engine's report gives it, cut down to the fields the rules
|
|
257
|
+
* read. `@toolpath/api`'s `PartFeature` is one, so the package takes no
|
|
258
|
+
* dependency on the SDK for a type.
|
|
259
|
+
*/
|
|
260
|
+
interface ReportFeature {
|
|
261
|
+
readonly featureTag: string;
|
|
262
|
+
readonly featureType: string;
|
|
263
|
+
readonly machiningDirection: Direction;
|
|
264
|
+
readonly regionIdxs: readonly number[];
|
|
265
|
+
}
|
|
266
|
+
/** A feature as the DFM rules read it: which it is, what kind, the way it is machined, and its faces. */
|
|
267
|
+
interface DfmFeature {
|
|
268
|
+
readonly tag: string;
|
|
269
|
+
readonly featureType: string;
|
|
270
|
+
readonly machiningDirection: Direction;
|
|
271
|
+
readonly regionIdxs: readonly number[];
|
|
272
|
+
/**
|
|
273
|
+
* What the panels call it, after its type: 1, 2, 3… across the part,
|
|
274
|
+
* numbered a machining direction at a time, so the features cut one way
|
|
275
|
+
* run together. Arbitrary otherwise, but steady for one analysis.
|
|
276
|
+
*/
|
|
277
|
+
readonly number: number;
|
|
278
|
+
}
|
|
279
|
+
/** The report's features, cut down to what the rules read, and numbered by direction. */
|
|
280
|
+
declare const dfmFeatures: (features: readonly ReportFeature[]) => DfmFeature[];
|
|
281
|
+
/** `through_hole` as `Through hole`. The Engine's feature types are open-ended snake case. */
|
|
282
|
+
declare const featureTypeLabel: (featureType: string) => string;
|
|
283
|
+
|
|
284
|
+
/** What the checks read of the part, beyond its features. */
|
|
285
|
+
interface DfmSources {
|
|
286
|
+
/** Each feature's measurements, cut down (`feature-sheet.ts`), by lower-cased tag. */
|
|
287
|
+
sheets: FeatureSheets;
|
|
288
|
+
/** Each feature's datasheet as the API sent it, by lower-cased tag. */
|
|
289
|
+
datasheets: Readonly<Record<string, unknown>>;
|
|
290
|
+
/** Each face's area, mm², by region index. */
|
|
291
|
+
regionAreas: ReadonlyMap<number, number>;
|
|
292
|
+
}
|
|
293
|
+
/** One rule a feature broke, with the figure that broke it. */
|
|
294
|
+
interface DfmHit {
|
|
295
|
+
rule: DfmRule;
|
|
296
|
+
metric: DfmMetric;
|
|
297
|
+
/** What was measured, canonical. */
|
|
298
|
+
value: number;
|
|
299
|
+
/** For an L/D: against a drill's bore rather than the widest cutter. */
|
|
300
|
+
drilling?: boolean;
|
|
301
|
+
}
|
|
302
|
+
/** One rule and the features that break it. */
|
|
303
|
+
interface RuleResult {
|
|
304
|
+
rule: DfmRule;
|
|
305
|
+
/** The required features' tags, as the report spells them: the worst first, the furthest past the rule. */
|
|
306
|
+
tags: string[];
|
|
307
|
+
/**
|
|
308
|
+
* The other readings that break it, worst first: features some other
|
|
309
|
+
* reading could stand in for, so they are not counted or painted, but a
|
|
310
|
+
* reader opening the rule should see everything it caught.
|
|
311
|
+
*/
|
|
312
|
+
otherTags: string[];
|
|
313
|
+
}
|
|
314
|
+
/** The part checked against the rules. */
|
|
315
|
+
interface DfmCheck {
|
|
316
|
+
/** Lower-cased tag → the rules the feature breaks, in the rules' order. Every feature, required or not. */
|
|
317
|
+
hitsByTag: ReadonlyMap<string, DfmHit[]>;
|
|
318
|
+
/** Lower-cased tags of the features a plan cannot do without. */
|
|
319
|
+
required: ReadonlySet<string>;
|
|
320
|
+
/** Each rule in order, with the required features that break it. */
|
|
321
|
+
byRule: RuleResult[];
|
|
322
|
+
/**
|
|
323
|
+
* Region → the colour a face is painted alone, and the reading it is painted for. See
|
|
324
|
+
* {@link unavoidableFaces}, and {@link withSurroundedFaces} for the faces painted with their surroundings.
|
|
325
|
+
*/
|
|
326
|
+
paintedFaces: ReadonlyMap<number, {
|
|
327
|
+
tag: string;
|
|
328
|
+
color: string;
|
|
329
|
+
}>;
|
|
330
|
+
/** Lower-cased tag → a contour surface painted whole in its own worst colour. See {@link unavoidableFaces}. */
|
|
331
|
+
paintedWhole: ReadonlyMap<string, {
|
|
332
|
+
tag: string;
|
|
333
|
+
color: string;
|
|
334
|
+
}>;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* The check with the faces its paint surrounds painted too. A face some
|
|
338
|
+
* reading cuts clean is left unpainted, but where that face is one of the
|
|
339
|
+
* feature that paints most of its painted neighbours, it is part of that
|
|
340
|
+
* feature, cut with it: a through hole in a flagged pocket's wall, say, read
|
|
341
|
+
* clean as a hole drilled from a floor far below that no plan would drill it
|
|
342
|
+
* from. Leaving it bare punches a hole in the feature's paint, so it takes
|
|
343
|
+
* the feature's colour. Where two features paint as many neighbours, the
|
|
344
|
+
* face takes the worse colour of those it is one of.
|
|
345
|
+
*
|
|
346
|
+
* One pass, over the paint as the check left it, so paint never spreads
|
|
347
|
+
* from a face that was itself only surrounded.
|
|
348
|
+
*/
|
|
349
|
+
declare const withSurroundedFaces: (check: DfmCheck, features: readonly DfmFeature[], adjacency: ReadonlyMap<number, ReadonlySet<number>>) => DfmCheck;
|
|
350
|
+
/**
|
|
351
|
+
* Checks every feature against every rule. Only the required features count
|
|
352
|
+
* against a rule: a feature some other reading could stand in for may never
|
|
353
|
+
* be cut, so flagging it would bury the ones that will be.
|
|
354
|
+
*/
|
|
355
|
+
declare const checkPart: (features: readonly DfmFeature[], sources: DfmSources, rules: readonly DfmRule[]) => DfmCheck;
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* A feature's reach curve (the datasheet's `reachCurve`, API 1.12.1): how
|
|
359
|
+
* high the material around a feature stands, by how far out from it.
|
|
360
|
+
*
|
|
361
|
+
* As the API defines it: material within `horizontalOffset[i]` of the
|
|
362
|
+
* feature rises to `verticalOffset[i]` above it. Both lists ascend, the
|
|
363
|
+
* curve is a step that never falls, and past its last knot it holds. So the
|
|
364
|
+
* rise comes at the *start* of each run, not at its knot: between two knots
|
|
365
|
+
* the material could stand anywhere out to the next one, and the next one's
|
|
366
|
+
* height is the bound — as the tool catalog's sweep reads it
|
|
367
|
+
* (`@toolpath/tool-support` `heightAt`), so a stack clears here where it
|
|
368
|
+
* clears there. Offsets
|
|
369
|
+
* are measured from the feature — zero is the wall of the cut — so material
|
|
370
|
+
* at offset `d` meets a tool at radius `d` plus the cutter's radius. Each
|
|
371
|
+
* reading is the worst case over the whole feature, with no direction to it.
|
|
372
|
+
*
|
|
373
|
+
* Millimetres throughout.
|
|
374
|
+
*/
|
|
375
|
+
|
|
376
|
+
interface ReachCurve {
|
|
377
|
+
/** Outward from the feature's wall, ascending. */
|
|
378
|
+
offsets: readonly number[];
|
|
379
|
+
/** How high the material within each offset rises above the feature, ascending. */
|
|
380
|
+
heights: readonly number[];
|
|
381
|
+
}
|
|
382
|
+
/** A datasheet's reach curve, or null where it has none worth drawing. */
|
|
383
|
+
declare const readReachCurve: (datasheet: unknown) => ReachCurve | null;
|
|
384
|
+
/** Where a knot's run starts, and so the nearest its material may stand: just past the knot before. */
|
|
385
|
+
declare const runStart: ({ offsets }: ReachCurve, index: number) => number;
|
|
386
|
+
/** The tallest the material stands anywhere the curve reaches. */
|
|
387
|
+
declare const peakHeight: ({ heights }: ReachCurve) => number;
|
|
388
|
+
/**
|
|
389
|
+
* The curve as the drawings show it: whole, where it keeps rising nearly to
|
|
390
|
+
* its end, and otherwise cut off {@link TAIL_MM} past where it reaches its
|
|
391
|
+
* full height, the height there held to the cut. `cut` says which, so the
|
|
392
|
+
* drawing can mark the break.
|
|
393
|
+
*/
|
|
394
|
+
declare const trimmedCurve: (curve: ReachCurve) => {
|
|
395
|
+
curve: ReachCurve;
|
|
396
|
+
cut: boolean;
|
|
397
|
+
};
|
|
398
|
+
/** How wide the feature itself is, across the tool, and what that width is. */
|
|
399
|
+
interface FeatureAcross {
|
|
400
|
+
width: number;
|
|
401
|
+
/** A hole's bore, or a milled feature's tightest clearance (its smallest pinch disc). */
|
|
402
|
+
kind: 'diameter' | 'clearance';
|
|
403
|
+
}
|
|
404
|
+
/** The feature as the reach section draws it, left of its wall. */
|
|
405
|
+
interface FeatureProfile {
|
|
406
|
+
/** Its width, to draw it to scale; null draws it at a set share. */
|
|
407
|
+
across: FeatureAcross | null;
|
|
408
|
+
/** Its own depth, top to bottom (`zMax − zMin`), over the same floor the curve stands on. */
|
|
409
|
+
depth: number | null;
|
|
410
|
+
/** It runs out through the part, so there is no floor under it. */
|
|
411
|
+
through: boolean;
|
|
412
|
+
}
|
|
413
|
+
declare const featureProfile: (sheet: FeatureSheet | undefined, featureType: string) => FeatureProfile;
|
|
414
|
+
|
|
415
|
+
export { featureTypeLabel as A, isNoReading as B, CRITICAL_COLOR as C, type DfmRule as D, makeRule as E, type FeatureSheets as F, parseRules as G, peakHeight as H, readPinch as I, readReachCurve as J, runStart as K, trimmedCurve as L, withSurroundedFaces as M, PINCH_TOOL_MM as P, type ReachCurve as R, type Units as U, WARNING_COLOR as W, type DfmCheck as a, type DfmFeature as b, type FeatureProfile as c, type DfmHit as d, type FeatureSheet as e, type ClearanceFit as f, type DfmMetric as g, type DfmOp as h, type DfmQuantity as i, type DfmSources as j, type FactsKind as k, type FeatureAcross as l, type FeaturePinch as m, type FeatureThreading as n, type PinchDisc as o, RULE_COLORS as p, type RangeHigh as q, type RangeLow as r, type ReportFeature as s, type RuleResult as t, checkPart as u, compareColors as v, describeRule as w, dfmFeatures as x, featureProfile as y, featureSheet as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,75 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toolpath/dfm",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Toolpath DFM rules: the rule list component, the rules and the part checker",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=20"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "https://github.com/toolpath/ui-packages.git",
|
|
12
|
+
"directory": "packages/dfm"
|
|
13
|
+
},
|
|
14
|
+
"homepage": "https://developers.toolpath.com",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/toolpath/ui-packages/issues"
|
|
17
|
+
},
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public",
|
|
20
|
+
"registry": "https://registry.npmjs.org"
|
|
21
|
+
},
|
|
22
|
+
"type": "module",
|
|
23
|
+
"main": "./dist/index.js",
|
|
24
|
+
"types": "./dist/index.d.ts",
|
|
25
|
+
"exports": {
|
|
26
|
+
".": {
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"import": "./dist/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./model": {
|
|
31
|
+
"types": "./dist/model/index.d.ts",
|
|
32
|
+
"import": "./dist/model/index.js"
|
|
33
|
+
},
|
|
34
|
+
"./dfm.css": "./dfm.css",
|
|
35
|
+
"./package.json": "./package.json"
|
|
36
|
+
},
|
|
37
|
+
"files": [
|
|
38
|
+
"dist",
|
|
39
|
+
"dfm.css",
|
|
40
|
+
"LICENSE",
|
|
41
|
+
"README.md"
|
|
42
|
+
],
|
|
43
|
+
"sideEffects": [
|
|
44
|
+
"*.css"
|
|
45
|
+
],
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"@phosphor-icons/react": "2.1.10",
|
|
48
|
+
"@toolpath/tool-support": "^0.6.0"
|
|
49
|
+
},
|
|
50
|
+
"peerDependencies": {
|
|
51
|
+
"@toolpath/ui": "^1.0.0",
|
|
52
|
+
"react": "^19.0.0",
|
|
53
|
+
"react-dom": "^19.0.0"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@testing-library/jest-dom": "^7.0.1",
|
|
57
|
+
"@testing-library/react": "^16.3.2",
|
|
58
|
+
"@types/node": "24.10.1",
|
|
59
|
+
"@types/react": "^19.0.0",
|
|
60
|
+
"@types/react-dom": "^19.0.0",
|
|
61
|
+
"jsdom": "^30.0.1",
|
|
62
|
+
"react": "19.2.8",
|
|
63
|
+
"react-dom": "19.2.8",
|
|
64
|
+
"tsup": "8.5.1",
|
|
65
|
+
"typescript": "5.9.3",
|
|
66
|
+
"vitest": "4.1.10",
|
|
67
|
+
"@toolpath/api": "^0.6.0",
|
|
68
|
+
"@toolpath/ui": "^1.0.0"
|
|
69
|
+
},
|
|
70
|
+
"scripts": {
|
|
71
|
+
"build": "tsup src/index.ts src/model/index.ts --format esm --dts --clean --external react --external react-dom --external @toolpath/ui",
|
|
72
|
+
"check-types": "tsc --noEmit",
|
|
73
|
+
"test": "vitest run"
|
|
74
|
+
}
|
|
6
75
|
}
|