@toolpath/dfm 0.5.0 → 1.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/README.md +33 -186
- package/dist/{chunk-4IRNLDE6.js → chunk-IB42AM6A.js} +1517 -96
- package/dist/index.d.ts +1 -389
- package/dist/index.js +93 -2610
- package/dist/model/index.d.ts +690 -3
- package/dist/model/index.js +64 -1388
- package/package.json +5 -23
- package/dfm.css +0 -10
- package/dist/feature-record-CfjgDCJU.d.ts +0 -599
package/dist/model/index.d.ts
CHANGED
|
@@ -1,11 +1,640 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Where a feature is at its tightest (the datasheet's `pinchPoints`, API
|
|
3
|
+
* 1.12.1): one disc per stretch of the feature that reaches its minimum
|
|
4
|
+
* clearance, tightest first and never more than ten.
|
|
5
|
+
*
|
|
6
|
+
* As the API defines it, a disc fits in the space the clearance was measured
|
|
7
|
+
* in and touches the feature's boundary, so a cylinder of its diameter
|
|
8
|
+
* standing at its centre and spanning the datasheet's `zMin`..`zMax` is
|
|
9
|
+
* exactly the widest tool that reaches the boundary there. That is what makes
|
|
10
|
+
* them drawable: each is the tool the feature allows, standing where the
|
|
11
|
+
* feature stops a larger one.
|
|
12
|
+
*
|
|
13
|
+
* The Engine measures each disc to a tolerance (`toleranceBand.atolIgnore`),
|
|
14
|
+
* which lets it read a little wider than the gap it sits in. The discs here
|
|
15
|
+
* have that slack taken out (see {@link clearanceFit}), so each is the
|
|
16
|
+
* clearance itself: in a 2.5 mm corner, a 5 mm disc.
|
|
17
|
+
*
|
|
18
|
+
* Empty for the kinds whose clearance is not measured off a single medial
|
|
19
|
+
* axis (a hole, a facing pass, the undercut and layered kinds), so empty is
|
|
20
|
+
* "nowhere to point at", never "nowhere is tight".
|
|
21
|
+
*
|
|
22
|
+
* Millimetres, in the datasheet's tool frame: x and y across the tool, z up
|
|
23
|
+
* it.
|
|
24
|
+
*/
|
|
25
|
+
/** One disc: its centre across the tool, and its diameter. */
|
|
26
|
+
interface PinchDisc {
|
|
27
|
+
x: number;
|
|
28
|
+
y: number;
|
|
29
|
+
diameter: number;
|
|
30
|
+
}
|
|
31
|
+
/** A feature's pinch discs, and the band along the tool they stand through. */
|
|
32
|
+
interface FeaturePinch {
|
|
33
|
+
discs: readonly PinchDisc[];
|
|
34
|
+
zMin: number;
|
|
35
|
+
zMax: number;
|
|
36
|
+
/**
|
|
37
|
+
* The Engine measured the clearance at one tolerance only, so the slack
|
|
38
|
+
* could not be taken out: each disc is as measured, the most the clearance
|
|
39
|
+
* can be.
|
|
40
|
+
*/
|
|
41
|
+
unresolved?: true;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The figures a feature's clearance is run back from, as the datasheet has
|
|
45
|
+
* them: the widest tool that reaches every point (`min` of the cutter band,
|
|
46
|
+
* which is also its tightest pinch disc) at the strict tolerance, and at the
|
|
47
|
+
* looser one where the Engine reports it.
|
|
48
|
+
*/
|
|
49
|
+
interface ClearanceFit {
|
|
50
|
+
/** `facts.cd`, or `facts.three.cd` for a chamfer. */
|
|
51
|
+
bandPath: string;
|
|
52
|
+
strict: number;
|
|
53
|
+
loose?: number;
|
|
54
|
+
atStrict?: number;
|
|
55
|
+
atLoose?: number;
|
|
56
|
+
/**
|
|
57
|
+
* How much wider, mm, the tolerance lets the widest tool read than the
|
|
58
|
+
* clearance it fits: what to take off a measured disc. Zero where the
|
|
59
|
+
* Engine measured at one tolerance only (`resolved` false), or where the
|
|
60
|
+
* tool does not grow with tolerance (a gap between walls, not a corner).
|
|
61
|
+
*/
|
|
62
|
+
slack: number;
|
|
63
|
+
resolved: boolean;
|
|
64
|
+
}
|
|
65
|
+
/** A datasheet's pinch discs, the tolerance taken out of each, or null where it has none to draw. */
|
|
66
|
+
declare const readPinch: (datasheet: unknown) => FeaturePinch | null;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* The few numbers of a feature's datasheet that the DFM rules and the
|
|
70
|
+
* feature details read. All millimetres, as the Engine reports them. Each is
|
|
71
|
+
* left out where this kind of feature does not report it, rather than sent as
|
|
72
|
+
* a zero that reads as measured.
|
|
73
|
+
*
|
|
74
|
+
* From the quoting app (quoting-ui `server/lib/engine.ts`). A datasheet is
|
|
75
|
+
* large, so the worker cuts each one down to this before it sends it.
|
|
76
|
+
*/
|
|
77
|
+
interface FeatureSheet {
|
|
78
|
+
/** The Engine's family for it: `Hole`, `Pocket`, … */
|
|
79
|
+
kind?: string;
|
|
80
|
+
/** Along the machining direction, the feature's own bottom and top. */
|
|
81
|
+
zMin?: number;
|
|
82
|
+
zMax?: number;
|
|
83
|
+
/** Its top extended to the stock, which the highest of stands in for the part's top. */
|
|
84
|
+
extendedZMax?: number;
|
|
85
|
+
/** The widest cutter that still reaches the tightest corner. */
|
|
86
|
+
maxTool?: number;
|
|
87
|
+
diameter?: number;
|
|
88
|
+
/** For a hole: the full angle of the cone at its bottom, degrees; 180 for a flat bottom. */
|
|
89
|
+
tipAngle?: number;
|
|
90
|
+
filletRadius?: number;
|
|
91
|
+
chamferAngle?: number;
|
|
92
|
+
/**
|
|
93
|
+
* For a milled feature with walls: the radius of its tightest inside corner
|
|
94
|
+
* between walls, as the geometry has it rather than as a tool reaches it —
|
|
95
|
+
* zero for a sharp one. Half its minimum clearance: see {@link insideCornerRadius}.
|
|
96
|
+
*/
|
|
97
|
+
cornerRadius?: number;
|
|
98
|
+
/**
|
|
99
|
+
* The Engine measured the clearance at one tolerance only, so neither
|
|
100
|
+
* `cornerRadius` nor `pinchDiameter` could be run back to none: each is as
|
|
101
|
+
* a tool reads it at that tolerance, the most the clearance can be.
|
|
102
|
+
*/
|
|
103
|
+
cornerRadiusUnresolved?: true;
|
|
104
|
+
/** What the clearance was worked out from, so a reader can follow it. See {@link ClearanceFit}. */
|
|
105
|
+
clearance?: ClearanceFit;
|
|
106
|
+
/**
|
|
107
|
+
* A vertical inside corner between its walls with no radius, which no end
|
|
108
|
+
* mill makes; and where, in the datasheet's tool frame (x, y across the
|
|
109
|
+
* tool; its `zMin`..`zMax` along it).
|
|
110
|
+
*/
|
|
111
|
+
sharpCorners?: readonly {
|
|
112
|
+
x: number;
|
|
113
|
+
y: number;
|
|
114
|
+
}[];
|
|
115
|
+
/**
|
|
116
|
+
* For a contour surface: the largest tool its shape admits (`facts.toolFit`)
|
|
117
|
+
* — its diameter, and the radius on its corner, no larger than the
|
|
118
|
+
* surface's tightest concave curve; half the diameter for a ball.
|
|
119
|
+
*/
|
|
120
|
+
fitToolDiameter?: number;
|
|
121
|
+
fitCornerRadius?: number;
|
|
122
|
+
/** Where the tool fit was read: `facts.toolFit` or `facts.three.toolFit`. */
|
|
123
|
+
toolFitPath?: string;
|
|
124
|
+
/** For a contour surface: only a ball end mill can finish it, not a bull nose. */
|
|
125
|
+
ballOnly?: true;
|
|
126
|
+
/**
|
|
127
|
+
* For a circular wall — the outside of a whole cylinder: it rises from a
|
|
128
|
+
* floor, so it is machined as a boss, as a stud or round boss is, rather than
|
|
129
|
+
* as a wall, as a turned part's outline is.
|
|
130
|
+
*/
|
|
131
|
+
standsOnAFloor?: true;
|
|
132
|
+
/**
|
|
133
|
+
* The feature's minimum clearance: the smallest of its pinch discs
|
|
134
|
+
* (`pinchPoints`), the tolerance taken out, leaving out the zero-wide ones
|
|
135
|
+
* a sharp corner reports. The widest tool that fits where it is tightest,
|
|
136
|
+
* and what a milled feature's L/D is taken over.
|
|
137
|
+
*/
|
|
138
|
+
pinchDiameter?: number;
|
|
139
|
+
/** How many places are that tight: the pinch discs counted in `pinchDiameter`. */
|
|
140
|
+
pinchPlaces?: number;
|
|
141
|
+
/** No cutter fits anywhere in the feature. */
|
|
142
|
+
noToolFits?: true;
|
|
143
|
+
/** For a hole the model threads: its thread. */
|
|
144
|
+
threading?: FeatureThreading;
|
|
145
|
+
/** For an undercut — a T-slot or a dovetail: what its cutter is held to. */
|
|
146
|
+
undercut?: FeatureUndercut;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* An undercut's own figures, from its `facts`: a T-slot's or a dovetail's.
|
|
150
|
+
* Millimetres and degrees. Each is left out where the Engine did not measure
|
|
151
|
+
* it, or where nothing limits it.
|
|
152
|
+
*/
|
|
153
|
+
interface FeatureUndercut {
|
|
154
|
+
/** T-slot: how far the groove runs back from its opening, radially (`facts.undercutDepth`). */
|
|
155
|
+
undercutDepth?: number;
|
|
156
|
+
/**
|
|
157
|
+
* T-slot: the widest tool that comes down through the opening above it
|
|
158
|
+
* (`facts.maxEntryCd`), which holds the cutter's shaft. Left out where
|
|
159
|
+
* nothing above limits it; zero where nothing fits.
|
|
160
|
+
*/
|
|
161
|
+
maxEntry?: number;
|
|
162
|
+
/** Dovetail: between the overhanging wall and the tool axis, degrees (`facts.taperDeg`). */
|
|
163
|
+
taperDeg?: number;
|
|
164
|
+
/** Dovetail: the widest clearance over the floor, the width the groove cuts at. */
|
|
165
|
+
floorWidth?: number;
|
|
166
|
+
/** Dovetail: the clearance through the opening at the top of the groove. */
|
|
167
|
+
topOpeningWidth?: number;
|
|
168
|
+
/** Dovetail: the groove's widths vary from place to place — it runs out somewhere. */
|
|
169
|
+
isExternal?: true;
|
|
170
|
+
/** T-slot: its walls close on themselves in plan view, so a cutter's head comes down through its opening. */
|
|
171
|
+
isClosed?: true;
|
|
172
|
+
/**
|
|
173
|
+
* The Engine could not measure it (`facts.isInvalidGeometry` or
|
|
174
|
+
* `facts.cd.measurementFailed`), so its figures offer no cutter.
|
|
175
|
+
*/
|
|
176
|
+
unmeasured?: true;
|
|
177
|
+
}
|
|
178
|
+
/** A modelled thread, from a hole's `facts.threading`. Millimetres. */
|
|
179
|
+
interface FeatureThreading {
|
|
180
|
+
basicDiameter: number;
|
|
181
|
+
threadPitch: number;
|
|
182
|
+
}
|
|
183
|
+
/** Feature tag, lower-cased → its sheet. */
|
|
184
|
+
type FeatureSheets = Record<string, FeatureSheet>;
|
|
185
|
+
/** Narrower than this, mm, a pinch disc is a sharp corner, which no tool fits: not a pinch tool. */
|
|
186
|
+
declare const PINCH_TOOL_MM = 0.01;
|
|
187
|
+
/** A feature that is no reading of its faces at all, which the analysis leaves out. */
|
|
188
|
+
declare const isNoReading: (featureType: unknown, datasheet: unknown) => boolean;
|
|
189
|
+
/** One datasheet, cut down to what the rules read. Read loosely: kinds report different fields. */
|
|
190
|
+
declare const featureSheet: (datasheet: unknown) => FeatureSheet;
|
|
191
|
+
|
|
192
|
+
type Direction = {
|
|
193
|
+
readonly x: number;
|
|
194
|
+
readonly y: number;
|
|
195
|
+
readonly z: number;
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* A feature as the Engine's report gives it, cut down to the fields the rules
|
|
199
|
+
* read. `@toolpath/api`'s `PartFeature` is one, so the package takes no
|
|
200
|
+
* dependency on the SDK for a type.
|
|
201
|
+
*/
|
|
202
|
+
interface ReportFeature {
|
|
203
|
+
readonly featureTag: string;
|
|
204
|
+
readonly featureType: string;
|
|
205
|
+
readonly machiningDirection: Direction;
|
|
206
|
+
readonly regionIdxs: readonly number[];
|
|
207
|
+
}
|
|
208
|
+
/** A feature as the DFM rules read it: which it is, what kind, the way it is machined, and its faces. */
|
|
209
|
+
interface DfmFeature {
|
|
210
|
+
readonly tag: string;
|
|
211
|
+
readonly featureType: string;
|
|
212
|
+
readonly machiningDirection: Direction;
|
|
213
|
+
readonly regionIdxs: readonly number[];
|
|
214
|
+
/**
|
|
215
|
+
* What the panels call it, after its type: 1, 2, 3… across the part,
|
|
216
|
+
* numbered a machining direction at a time, so the features cut one way
|
|
217
|
+
* run together. Arbitrary otherwise, but steady for one analysis.
|
|
218
|
+
*/
|
|
219
|
+
readonly number: number;
|
|
220
|
+
}
|
|
221
|
+
/** The report's features, cut down to what the rules read, and numbered by direction. */
|
|
222
|
+
declare const dfmFeatures: (features: readonly ReportFeature[]) => DfmFeature[];
|
|
223
|
+
/** `through_hole` as `Through hole`. The Engine's feature types are open-ended snake case. */
|
|
224
|
+
declare const featureTypeLabel: (featureType: string) => string;
|
|
225
|
+
|
|
226
|
+
/** A turning datasheet's `facts.kind`, and `Unknown` for a stretch the Engine could not name. */
|
|
227
|
+
type TurnedFactsKind = 'AxialHole' | 'Face' | 'FaceGroove' | 'FaceProfile' | 'IdGroove' | 'IdProfile' | 'IdThread' | 'OdGroove' | 'OdProfile' | 'OdThread' | 'Unknown';
|
|
228
|
+
/**
|
|
229
|
+
* `od_groove` as `OD groove`, `axial_hole` as `Axial hole`. The Engine's
|
|
230
|
+
* turned feature types are open-ended snake case, so a type it adds later
|
|
231
|
+
* reads as its words.
|
|
232
|
+
*/
|
|
233
|
+
declare const turnedTypeLabel: (featureType: string) => string;
|
|
234
|
+
/** Turning rules: the measures and subjects of the Engine's turned features. */
|
|
235
|
+
declare const TURNING_RULES: RuleVocabulary;
|
|
236
|
+
|
|
237
|
+
/** The unit a length is shown in. The Engine's meshes are always millimetres. */
|
|
238
|
+
type Units = 'mm' | 'inch';
|
|
239
|
+
/** The number alone, for a line of several lengths that names the unit once. */
|
|
240
|
+
declare const lengthValue: (mm: number, units: Units) => string;
|
|
241
|
+
declare const unitLabel: (units: Units) => string;
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* At or above, above, at or below, below, equal, not equal, or between —
|
|
245
|
+
* equal meaning within half a percent, since figures are measured, and not
|
|
246
|
+
* equal anything further off; between from a low end up to, not including, a
|
|
247
|
+
* high one.
|
|
248
|
+
*/
|
|
249
|
+
type DfmOp = 'gte' | 'gt' | 'lte' | 'lt' | 'eq' | 'ne' | 'between';
|
|
250
|
+
/**
|
|
251
|
+
* How a figure is read and typed: a length (mm), an area (mm²), an angle
|
|
252
|
+
* (degrees), a plain ratio, a count, a percentage, yes/no, or — for "any
|
|
253
|
+
* size" — nothing at all.
|
|
254
|
+
*/
|
|
255
|
+
type DfmQuantity = 'length' | 'area' | 'angle' | 'ratio' | 'count' | 'percent' | 'flag' | 'presence';
|
|
256
|
+
/** A datasheet's `facts.kind`: which family of measurements the Engine took. */
|
|
257
|
+
type FactsKind = 'Hole' | 'Pocket' | 'Boss' | 'Wall' | 'CircularWall' | 'Face' | 'Three' | 'Chamfer' | 'Profile' | 'Dovetail' | 'Tslot';
|
|
258
|
+
/** A datasheet's `facts.kind`, milled or turned. */
|
|
259
|
+
type AnyFactsKind = FactsKind | TurnedFactsKind;
|
|
260
|
+
interface DfmMetric {
|
|
261
|
+
key: string;
|
|
262
|
+
/** As the rule sentence reads it: "L/D", "depth below top". */
|
|
263
|
+
label: string;
|
|
264
|
+
/** The heading it is listed under when choosing. */
|
|
265
|
+
group: string;
|
|
266
|
+
quantity: DfmQuantity;
|
|
267
|
+
/** Which way is worse, for a new rule: deep is bad (≥), a tiny corner is bad (≤). */
|
|
268
|
+
op: DfmOp;
|
|
269
|
+
/** What a new rule starts at: millimetres and inches kept apart, so both read as round numbers. */
|
|
270
|
+
start: Record<Units, number>;
|
|
271
|
+
/** What it means, in a few plain words. */
|
|
272
|
+
hint: string;
|
|
273
|
+
/** The kinds of datasheet that report it; every kind when left out. */
|
|
274
|
+
kinds?: readonly AnyFactsKind[];
|
|
275
|
+
/**
|
|
276
|
+
* Where it sits in the datasheet, first found wins: a chamfer keeps its
|
|
277
|
+
* cutter band under its surface reading (`facts.three.cd`). Left out for a
|
|
278
|
+
* measure worked out rather than read (see `dfm-flags.ts`).
|
|
279
|
+
*/
|
|
280
|
+
path?: readonly string[];
|
|
281
|
+
/** Whether a rule may name a value below zero: a height, or a signed radius. */
|
|
282
|
+
signed?: true;
|
|
283
|
+
}
|
|
284
|
+
declare const PRESENCE_METRIC: DfmMetric;
|
|
285
|
+
interface DfmSubject {
|
|
286
|
+
value: string;
|
|
287
|
+
/** Plural, as the rule sentence starts: "Holes", "Undercut T-slots". */
|
|
288
|
+
label: string;
|
|
289
|
+
/** "Groups" or "Feature types", for choosing. */
|
|
290
|
+
group: string;
|
|
291
|
+
/** The datasheet kinds its features report; every kind when left out. */
|
|
292
|
+
kinds?: readonly AnyFactsKind[];
|
|
293
|
+
}
|
|
294
|
+
/** The common subjects, one list — broad groups and the few types worth naming alone. */
|
|
295
|
+
declare const QUICK_SUBJECTS: readonly string[];
|
|
296
|
+
/** Which kind of machining a set of rules is about: a milled part's features, or a turned part's. */
|
|
297
|
+
type RuleProcess = 'milling' | 'turning';
|
|
298
|
+
/**
|
|
299
|
+
* Everything a set of rules can say, for one process: its measures, its
|
|
300
|
+
* subjects, the short lists offered first, and how a feature that breaks a
|
|
301
|
+
* rule is named in a list. Pure data, so the editor, the checker and the
|
|
302
|
+
* rule-set file read milling and turning rules the same way.
|
|
303
|
+
*/
|
|
304
|
+
interface RuleVocabulary {
|
|
305
|
+
process: RuleProcess;
|
|
306
|
+
metrics: readonly DfmMetric[];
|
|
307
|
+
subjects: readonly DfmSubject[];
|
|
308
|
+
quickSubjects: readonly string[];
|
|
309
|
+
quickMetrics: readonly string[];
|
|
310
|
+
/** What a new or moved rule falls back on when its own measure is unknown: L/D for milling, "any size" for turning. */
|
|
311
|
+
fallbackMetric: DfmMetric;
|
|
312
|
+
/**
|
|
313
|
+
* A feature as a list or the feature panel names it: `{ name: 'Blind hole',
|
|
314
|
+
* detail: 'from +Z' }`, or for a turned one `{ name: 'OD groove', detail:
|
|
315
|
+
* 'from both ends' }`. The detail follows "Machined" in the feature panel.
|
|
316
|
+
*/
|
|
317
|
+
featureLabel: (feature: Pick<DfmFeature, 'featureType' | 'machiningDirection'>) => {
|
|
318
|
+
name: string;
|
|
319
|
+
detail: string;
|
|
320
|
+
};
|
|
321
|
+
/** The feature panel's heading over what a feature asks of the machining: `Milling considerations`. */
|
|
322
|
+
considerationsTitle: string;
|
|
323
|
+
/** What an exported set is saved as. */
|
|
324
|
+
fileName: string;
|
|
325
|
+
}
|
|
326
|
+
/** Milling rules: the measures and subjects above, which the Engine's milled features report. */
|
|
327
|
+
declare const MILLING_RULES: RuleVocabulary;
|
|
328
|
+
declare const metricInfo: (key: string, vocabulary?: RuleVocabulary) => DfmMetric | undefined;
|
|
329
|
+
/**
|
|
330
|
+
* The measures a subject's features can have: those every kind reports, and
|
|
331
|
+
* those its kinds do. Any feature, of whatever kind, can have any of them.
|
|
332
|
+
*/
|
|
333
|
+
declare const metricsForSubject: (subject: string, vocabulary?: RuleVocabulary) => readonly DfmMetric[];
|
|
334
|
+
|
|
335
|
+
declare const OPS: readonly DfmOp[];
|
|
336
|
+
/** How a range holds its low end: at or above it, or above it. */
|
|
337
|
+
type RangeLow = 'gte' | 'gt';
|
|
338
|
+
/** How a range holds its high end: below it, or at or below it. */
|
|
339
|
+
type RangeHigh = 'lt' | 'lte';
|
|
340
|
+
declare const RANGE_LOWS: readonly RangeLow[];
|
|
341
|
+
declare const RANGE_HIGHS: readonly RangeHigh[];
|
|
342
|
+
declare const opSymbol: (op: DfmOp) => string;
|
|
343
|
+
interface DfmRule {
|
|
344
|
+
/** Stable, so a list can key its rows and a feature can name the rule it broke. */
|
|
345
|
+
id: string;
|
|
346
|
+
/** Which features: a value from its vocabulary's subjects — `FEATURE_SUBJECTS` for milling. */
|
|
347
|
+
subject: string;
|
|
348
|
+
/** What is measured: a key from its vocabulary's metrics — `FEATURE_METRICS` for milling. */
|
|
349
|
+
metric: string;
|
|
350
|
+
op: DfmOp;
|
|
351
|
+
/** Canonical — mm or a ratio. Ignored by a yes/no metric. The low end of a range. */
|
|
352
|
+
value: number;
|
|
353
|
+
/** A range's high end. Only a `between` rule has one. */
|
|
354
|
+
max?: number;
|
|
355
|
+
/** How a range holds its low end; ≥ where unsaid. Only a `between` rule has one. */
|
|
356
|
+
lowOp?: RangeLow;
|
|
357
|
+
/** How a range holds its high end; < where unsaid. Only a `between` rule has one. */
|
|
358
|
+
highOp?: RangeHigh;
|
|
359
|
+
/** `#rrggbb`: what the features that break it are painted. */
|
|
360
|
+
color: string;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* The colours a rule can wear: vivid, and far enough apart in hue and
|
|
364
|
+
* lightness to tell apart on the part at a glance (no two closer than ΔE 37,
|
|
365
|
+
* and none within 50 of the selection's blue). Warm first, since most
|
|
366
|
+
* rules call out trouble; then cool ones for a rule that marks something
|
|
367
|
+
* good.
|
|
368
|
+
*/
|
|
369
|
+
declare const RULE_COLORS: readonly {
|
|
370
|
+
name: string;
|
|
371
|
+
value: string;
|
|
372
|
+
}[];
|
|
373
|
+
/**
|
|
374
|
+
* Which colour shows where a feature breaks rules of two: the one earliest in
|
|
375
|
+
* the palette, so red over yellow. Colours from outside it come after, in an
|
|
376
|
+
* order of their own, so a tie never falls back on the list.
|
|
377
|
+
*/
|
|
378
|
+
declare const compareColors: (a: string, b: string) => number;
|
|
379
|
+
/** The quoting app's two severities, as the colours a rule starts in. */
|
|
380
|
+
declare const CRITICAL_COLOR = "#e5484d";
|
|
381
|
+
declare const WARNING_COLOR = "#ffd60a";
|
|
382
|
+
declare const subjectLabel: (value: string, vocabulary?: RuleVocabulary) => string;
|
|
383
|
+
/** The unit a value is typed in, beside its field. */
|
|
384
|
+
declare const quantityUnit: (quantity: DfmQuantity, units: Units) => string;
|
|
385
|
+
/** A canonical value as its field shows it. */
|
|
386
|
+
declare const toField: (quantity: DfmQuantity, value: number, units: Units) => string;
|
|
387
|
+
/**
|
|
388
|
+
* What a field says, back to canonical — or null when it is not a number,
|
|
389
|
+
* is below zero where the measure cannot be, or is a fraction of a count.
|
|
390
|
+
*/
|
|
391
|
+
declare const fromField: (metric: DfmMetric, text: string, units: Units) => number | null;
|
|
392
|
+
/** A measured value, as a row says it: `7.5`, `1.25"`, `3.2 mm`, `1,200 mm²`. */
|
|
393
|
+
declare const formatMeasured: (quantity: DfmQuantity, value: number, units: Units) => string;
|
|
394
|
+
/**
|
|
395
|
+
* A rule as one plain line: "Holes with L/D ≥ 8", "Holes with 4 ≤ L/D < 8",
|
|
396
|
+
* "Any feature with a sharp inside corner", "Undercut T-slots, any size".
|
|
397
|
+
*/
|
|
398
|
+
declare const describeRule: (rule: DfmRule, units: Units, vocabulary?: RuleVocabulary) => string;
|
|
399
|
+
/**
|
|
400
|
+
* A new rule for a subject and metric, at the metric's own starting value in
|
|
401
|
+
* the reader's units. A metric the vocabulary does not know is its fallback.
|
|
402
|
+
*/
|
|
403
|
+
declare const makeRule: (subject: string, metricKey: string, units: Units, color?: string, vocabulary?: RuleVocabulary) => DfmRule;
|
|
404
|
+
/** A range's high end: its own, or as far again above its low one (at least 1) where it has none yet. */
|
|
405
|
+
declare const upperOf: (rule: DfmRule) => number;
|
|
406
|
+
/** How a range holds its low end. */
|
|
407
|
+
declare const lowOf: (rule: DfmRule) => RangeLow;
|
|
408
|
+
/** How a range holds its high end. */
|
|
409
|
+
declare const highOf: (rule: DfmRule) => RangeHigh;
|
|
410
|
+
/** A rule with its metric moved: the metric's own way and starting value, since the old ones meant something else. */
|
|
411
|
+
declare const withMetric: (rule: DfmRule, metricKey: string, units: Units, vocabulary?: RuleVocabulary) => DfmRule;
|
|
412
|
+
/** A rule with its comparison changed: a range gets a high end, and anything else loses it. */
|
|
413
|
+
declare const withOp: (rule: DfmRule, op: DfmOp) => DfmRule;
|
|
414
|
+
/** A rule with its subject moved, and its metric too when the new subject has no such measure. */
|
|
415
|
+
declare const withSubject: (rule: DfmRule, subject: string, units: Units, vocabulary?: RuleVocabulary) => DfmRule;
|
|
416
|
+
/**
|
|
417
|
+
* Stored rules, the ones that read in this vocabulary — a turning rule is
|
|
418
|
+
* dropped as milling reads it, and the other way round; null when what is
|
|
419
|
+
* stored is not a list at all.
|
|
420
|
+
*/
|
|
421
|
+
declare const parseRules: (raw: unknown, vocabulary?: RuleVocabulary) => DfmRule[] | null;
|
|
422
|
+
|
|
423
|
+
/** What the checks read of the part, beyond its features. */
|
|
424
|
+
interface DfmSources {
|
|
425
|
+
/** Each feature's measurements, cut down (`feature-sheet.ts`), by lower-cased tag. */
|
|
426
|
+
sheets: FeatureSheets;
|
|
427
|
+
/** Each feature's datasheet as the API sent it, by lower-cased tag. */
|
|
428
|
+
datasheets: Readonly<Record<string, unknown>>;
|
|
429
|
+
/** Each face's area, mm², by region index. */
|
|
430
|
+
regionAreas: ReadonlyMap<number, number>;
|
|
431
|
+
}
|
|
432
|
+
/** One rule a feature broke, with the figure that broke it. */
|
|
433
|
+
interface DfmHit {
|
|
434
|
+
rule: DfmRule;
|
|
435
|
+
metric: DfmMetric;
|
|
436
|
+
/** What was measured, canonical. */
|
|
437
|
+
value: number;
|
|
438
|
+
/** For an L/D: against a drill's bore rather than the widest cutter. */
|
|
439
|
+
drilling?: boolean;
|
|
440
|
+
}
|
|
441
|
+
/** One rule and the features that break it. */
|
|
442
|
+
interface RuleResult {
|
|
443
|
+
rule: DfmRule;
|
|
444
|
+
/** The required features' tags, as the report spells them: the worst first, the furthest past the rule. */
|
|
445
|
+
tags: string[];
|
|
446
|
+
/**
|
|
447
|
+
* The other readings that break it, worst first: features some other
|
|
448
|
+
* reading could stand in for, so they are not counted or painted, but a
|
|
449
|
+
* reader opening the rule should see everything it caught.
|
|
450
|
+
*/
|
|
451
|
+
otherTags: string[];
|
|
452
|
+
}
|
|
453
|
+
/** The part checked against the rules. */
|
|
454
|
+
interface DfmCheck {
|
|
455
|
+
/** Lower-cased tag → the rules the feature breaks, in the rules' order. Every feature, required or not. */
|
|
456
|
+
hitsByTag: ReadonlyMap<string, DfmHit[]>;
|
|
457
|
+
/** Lower-cased tags of the features a plan cannot do without. */
|
|
458
|
+
required: ReadonlySet<string>;
|
|
459
|
+
/** Each rule in order, with the required features that break it. */
|
|
460
|
+
byRule: RuleResult[];
|
|
461
|
+
/**
|
|
462
|
+
* Region → the colour a face is painted alone, and the reading it is painted for. See
|
|
463
|
+
* {@link unavoidableFaces}, and {@link withSurroundedFaces} for the faces painted with their surroundings.
|
|
464
|
+
*/
|
|
465
|
+
paintedFaces: ReadonlyMap<number, {
|
|
466
|
+
tag: string;
|
|
467
|
+
color: string;
|
|
468
|
+
}>;
|
|
469
|
+
/** Lower-cased tag → a contour surface painted whole in its own worst colour. See {@link unavoidableFaces}. */
|
|
470
|
+
paintedWhole: ReadonlyMap<string, {
|
|
471
|
+
tag: string;
|
|
472
|
+
color: string;
|
|
473
|
+
}>;
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
476
|
+
* The check with the faces its paint surrounds painted too. A face some
|
|
477
|
+
* reading cuts clean is left unpainted, but where that face is one of the
|
|
478
|
+
* feature that paints most of its painted neighbours, it is part of that
|
|
479
|
+
* feature, cut with it: a through hole in a flagged pocket's wall, say, read
|
|
480
|
+
* clean as a hole drilled from a floor far below that no plan would drill it
|
|
481
|
+
* from. Leaving it bare punches a hole in the feature's paint, so it takes
|
|
482
|
+
* the feature's colour. Where two features paint as many neighbours, the
|
|
483
|
+
* face takes the worse colour of those it is one of.
|
|
484
|
+
*
|
|
485
|
+
* One pass, over the paint as the check left it, so paint never spreads
|
|
486
|
+
* from a face that was itself only surrounded.
|
|
487
|
+
*/
|
|
488
|
+
declare const withSurroundedFaces: (check: DfmCheck, features: readonly DfmFeature[], adjacency: ReadonlyMap<number, ReadonlySet<number>>) => DfmCheck;
|
|
489
|
+
/**
|
|
490
|
+
* Checks every feature against every rule. Only the required features count
|
|
491
|
+
* against a rule: a feature some other reading could stand in for may never
|
|
492
|
+
* be cut, so flagging it would bury the ones that will be.
|
|
493
|
+
*/
|
|
494
|
+
declare const checkPart: (features: readonly DfmFeature[], sources: DfmSources, rules: readonly DfmRule[]) => DfmCheck;
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* A rule a feature breaks, as a row of its details says it: a coloured dot,
|
|
498
|
+
* the rule, and the figure that broke it. Neutral, so an app with rules of its
|
|
499
|
+
* own — the quoting app's, by severity — fills it from those, and an app on
|
|
500
|
+
* this package's checker fills it with {@link brokenRules}.
|
|
501
|
+
*/
|
|
502
|
+
interface BrokenRule {
|
|
503
|
+
/** Unique among one feature's rows: the rule's id. */
|
|
504
|
+
readonly key: string;
|
|
505
|
+
/** The dot: the rule's colour, or the app's colour for its severity. */
|
|
506
|
+
readonly color: string;
|
|
507
|
+
/** The rule: `Holes with L/D to top of part ≥ 8`, or a short label where `limit` says the rest. */
|
|
508
|
+
readonly text: string;
|
|
509
|
+
/** What the feature measured: `9.8`. Absent for a yes/no. */
|
|
510
|
+
readonly figure?: string;
|
|
511
|
+
/** The line it crossed, where `text` does not already say it: `≥ 8`. */
|
|
512
|
+
readonly limit?: string;
|
|
513
|
+
/** On hover: the rule written out, and why it matters. */
|
|
514
|
+
readonly note?: string;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* The rules a feature breaks, as its details list them: one a measure, the
|
|
518
|
+
* worst, palette first, each written in the vocabulary its rules are in.
|
|
519
|
+
*/
|
|
520
|
+
declare const brokenRules: (check: DfmCheck, tag: string, units: Units, vocabulary?: RuleVocabulary) => BrokenRule[];
|
|
521
|
+
/**
|
|
522
|
+
* The colour a feature is painted on the part: the one earliest in the
|
|
523
|
+
* palette of the rules it breaks, for a required feature. Read from a face
|
|
524
|
+
* painted alone (`region`), that face's colour where it is painted for this
|
|
525
|
+
* feature; a feature painted whole, its colour. Undefined otherwise.
|
|
526
|
+
*/
|
|
527
|
+
declare const featureColor: (check: DfmCheck, tag: string, region?: number | null) => string | undefined;
|
|
3
528
|
|
|
4
529
|
/** The figure that broke a rule, bare: `7.5`, `0.05"`. Empty for a yes/no or "any size". */
|
|
5
530
|
declare const hitFigure: (hit: DfmHit, units: Units) => string;
|
|
6
531
|
|
|
532
|
+
/** One row of a feature's details. */
|
|
533
|
+
interface Measurement {
|
|
534
|
+
/** Stable, so a list can key its rows. */
|
|
535
|
+
readonly key: string;
|
|
536
|
+
readonly label: string;
|
|
537
|
+
readonly value: string;
|
|
538
|
+
/** The same number in the other unit. Absent on a ratio or a count. */
|
|
539
|
+
readonly alt?: string;
|
|
540
|
+
/**
|
|
541
|
+
* How it was worked out from the datasheet, a line at a time: the fields it
|
|
542
|
+
* reads, by their path in the raw record, and the arithmetic, in the
|
|
543
|
+
* Engine's millimetres.
|
|
544
|
+
*/
|
|
545
|
+
readonly derivation: readonly string[];
|
|
546
|
+
/**
|
|
547
|
+
* A machining consideration rather than a measurement of the feature's own
|
|
548
|
+
* shape: the tool that cuts it, and how far it has to reach. The panel lists
|
|
549
|
+
* these under their own heading, for every kind of feature.
|
|
550
|
+
*/
|
|
551
|
+
readonly milling?: true;
|
|
552
|
+
/** A row that stands for a tool the viewer can draw on the part, by its kind. */
|
|
553
|
+
readonly tool?: SurfaceToolKind;
|
|
554
|
+
}
|
|
555
|
+
/** Which of a surface's finishing tools: a ball nose, or a bull nose with a flat between its corners. */
|
|
556
|
+
type SurfaceToolKind = 'ball' | 'bull';
|
|
557
|
+
/** Whether a feature type is read as a surface: see `SURFACE_TYPES`. */
|
|
558
|
+
declare const isSurfaceType: (featureType: string) => boolean;
|
|
559
|
+
/**
|
|
560
|
+
* The biggest ball nose a surface admits, mm: a ball's corner radius is half
|
|
561
|
+
* its diameter, so it is held under the tool fit's diameter and corner radius
|
|
562
|
+
* at once. None where the surface reports no fit, or admits no corner at all.
|
|
563
|
+
*/
|
|
564
|
+
declare const maxBallDiameter: (sheet: Pick<FeatureSheet, "fitToolDiameter" | "fitCornerRadius">) => number | undefined;
|
|
565
|
+
/**
|
|
566
|
+
* The rows a feature gets, in {@link ROW_ORDER}: its own geometry first, then
|
|
567
|
+
* where it sits in the part and the reach that makes, then the tools a
|
|
568
|
+
* surface admits. A row is left out rather than shown empty: "—" against a
|
|
569
|
+
* field this kind never reports reads as a measurement that failed.
|
|
570
|
+
*/
|
|
571
|
+
declare const featureMeasurements: ({ features, feature, sheets, units, inchMark, }: {
|
|
572
|
+
features: readonly DfmFeature[];
|
|
573
|
+
feature: DfmFeature;
|
|
574
|
+
sheets: FeatureSheets;
|
|
575
|
+
units: Units;
|
|
576
|
+
/** Writes inches as `0.46"` rather than `0.46 in`. */
|
|
577
|
+
inchMark?: boolean;
|
|
578
|
+
}) => Measurement[];
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Everything the API said about one feature: its entry in the part report and
|
|
582
|
+
* its datasheet, both as sent, so fields newer than any SDK are still there.
|
|
583
|
+
*/
|
|
584
|
+
interface FeatureRecord {
|
|
585
|
+
readonly feature: unknown;
|
|
586
|
+
/** Null where the API sent no datasheet for the feature. */
|
|
587
|
+
readonly datasheet: unknown;
|
|
588
|
+
}
|
|
589
|
+
/** One leaf of a datasheet: where it sits — `facts.bevel.angleDeg` — and what it says. */
|
|
590
|
+
interface DatasheetField {
|
|
591
|
+
readonly path: string;
|
|
592
|
+
readonly value: string;
|
|
593
|
+
}
|
|
594
|
+
/** More rows than this and the list stops, rather than read a long curve out point by point. */
|
|
595
|
+
declare const MAX_DATASHEET_FIELDS = 500;
|
|
596
|
+
/**
|
|
597
|
+
* Every leaf of a datasheet by its path, as sent: millimetres and degrees,
|
|
598
|
+
* numbers to four places. A list of plain values is one row; a list of records
|
|
599
|
+
* is walked by index; an empty list or record is a row of its own. Stops at
|
|
600
|
+
* {@link MAX_DATASHEET_FIELDS}, and says so with `more`.
|
|
601
|
+
*/
|
|
602
|
+
declare const datasheetFields: (datasheet: unknown) => {
|
|
603
|
+
fields: DatasheetField[];
|
|
604
|
+
more: boolean;
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* A machining direction as a reader names it: `+Z` along an axis, the vector
|
|
609
|
+
* otherwise. The same words `@toolpath/viewer` uses, kept here so the rule
|
|
610
|
+
* list does not pull in three.js for one label.
|
|
611
|
+
*/
|
|
612
|
+
declare const directionLabel: (direction: {
|
|
613
|
+
readonly x: number;
|
|
614
|
+
readonly y: number;
|
|
615
|
+
readonly z: number;
|
|
616
|
+
}) => string;
|
|
617
|
+
|
|
7
618
|
/** Whether two depths are one depth, as the quoting app counts them: within a twentieth, or a hundredth of a mm. */
|
|
8
619
|
declare const sameDepth: (a: number, b: number) => boolean;
|
|
620
|
+
/** A row in a list of features: one feature, or a group of the same hole. */
|
|
621
|
+
type FeatureRow = {
|
|
622
|
+
kind: 'feature';
|
|
623
|
+
tag: string;
|
|
624
|
+
} | {
|
|
625
|
+
kind: 'holes';
|
|
626
|
+
/** Stable: the first hole's tag. */
|
|
627
|
+
key: string;
|
|
628
|
+
/** In list order, the first standing for them all. */
|
|
629
|
+
tags: [string, ...string[]];
|
|
630
|
+
diameter: number;
|
|
631
|
+
};
|
|
632
|
+
/**
|
|
633
|
+
* These features as a list's rows, identical holes gathered into one where
|
|
634
|
+
* the first of them was. Holes the Engine did not measure, and anything not
|
|
635
|
+
* a hole, stay a row each.
|
|
636
|
+
*/
|
|
637
|
+
declare const featureRows: (tags: readonly string[], features: readonly DfmFeature[], sheets: FeatureSheets) => FeatureRow[];
|
|
9
638
|
|
|
10
639
|
/**
|
|
11
640
|
* A feature's pinch discs as the widest tool that fits stands in them: the
|
|
@@ -72,6 +701,64 @@ interface PlacedTool {
|
|
|
72
701
|
*/
|
|
73
702
|
declare const placePinchTool: (mark: PinchMark, triangles: FaceTriangles, direction: Vec3, origin?: Vec3) => PlacedTool | null;
|
|
74
703
|
|
|
704
|
+
/**
|
|
705
|
+
* A feature's reach curve (the datasheet's `reachCurve`, API 1.12.1): how
|
|
706
|
+
* high the material around a feature stands, by how far out from it.
|
|
707
|
+
*
|
|
708
|
+
* As the API defines it: material within `horizontalOffset[i]` of the
|
|
709
|
+
* feature rises to `verticalOffset[i]` above it. Both lists ascend, the
|
|
710
|
+
* curve is a step that never falls, and past its last knot it holds. So the
|
|
711
|
+
* rise comes at the *start* of each run, not at its knot: between two knots
|
|
712
|
+
* the material could stand anywhere out to the next one, and the next one's
|
|
713
|
+
* height is the bound — as the tool catalog's sweep reads it
|
|
714
|
+
* (`@toolpath/tool-support` `heightAt`), so a stack clears here where it
|
|
715
|
+
* clears there. Offsets
|
|
716
|
+
* are measured from the feature — zero is the wall of the cut — so material
|
|
717
|
+
* at offset `d` meets a tool at radius `d` plus the cutter's radius. Each
|
|
718
|
+
* reading is the worst case over the whole feature, with no direction to it.
|
|
719
|
+
*
|
|
720
|
+
* Millimetres throughout.
|
|
721
|
+
*/
|
|
722
|
+
|
|
723
|
+
interface ReachCurve {
|
|
724
|
+
/** Outward from the feature's wall, ascending. */
|
|
725
|
+
offsets: readonly number[];
|
|
726
|
+
/** How high the material within each offset rises above the feature, ascending. */
|
|
727
|
+
heights: readonly number[];
|
|
728
|
+
}
|
|
729
|
+
/** A datasheet's reach curve, or null where it has none worth drawing. */
|
|
730
|
+
declare const readReachCurve: (datasheet: unknown) => ReachCurve | null;
|
|
731
|
+
/** Where a knot's run starts, and so the nearest its material may stand: just past the knot before. */
|
|
732
|
+
declare const runStart: ({ offsets }: ReachCurve, index: number) => number;
|
|
733
|
+
/** The tallest the material stands anywhere the curve reaches. */
|
|
734
|
+
declare const peakHeight: ({ heights }: ReachCurve) => number;
|
|
735
|
+
/**
|
|
736
|
+
* The curve as the drawings show it: whole, where it keeps rising nearly to
|
|
737
|
+
* its end, and otherwise cut off {@link TAIL_MM} past where it reaches its
|
|
738
|
+
* full height, the height there held to the cut. `cut` says which, so the
|
|
739
|
+
* drawing can mark the break.
|
|
740
|
+
*/
|
|
741
|
+
declare const trimmedCurve: (curve: ReachCurve) => {
|
|
742
|
+
curve: ReachCurve;
|
|
743
|
+
cut: boolean;
|
|
744
|
+
};
|
|
745
|
+
/** How wide the feature itself is, across the tool, and what that width is. */
|
|
746
|
+
interface FeatureAcross {
|
|
747
|
+
width: number;
|
|
748
|
+
/** A hole's bore, or a milled feature's tightest clearance (its smallest pinch disc). */
|
|
749
|
+
kind: 'diameter' | 'clearance';
|
|
750
|
+
}
|
|
751
|
+
/** The feature as the reach section draws it, left of its wall. */
|
|
752
|
+
interface FeatureProfile {
|
|
753
|
+
/** Its width, to draw it to scale; null draws it at a set share. */
|
|
754
|
+
across: FeatureAcross | null;
|
|
755
|
+
/** Its own depth, top to bottom (`zMax − zMin`), over the same floor the curve stands on. */
|
|
756
|
+
depth: number | null;
|
|
757
|
+
/** It runs out through the part, so there is no floor under it. */
|
|
758
|
+
through: boolean;
|
|
759
|
+
}
|
|
760
|
+
declare const featureProfile: (sheet: FeatureSheet | undefined, featureType: string) => FeatureProfile;
|
|
761
|
+
|
|
75
762
|
/**
|
|
76
763
|
* A set of DFM rules as a file: what Export writes, Import reads, and what
|
|
77
764
|
* an LLM is asked to produce. One JSON object, so a shop can keep a set per
|
|
@@ -171,4 +858,4 @@ declare const turnedStretches: (features: readonly TurnedReportFeature[]) => Tur
|
|
|
171
858
|
*/
|
|
172
859
|
declare const checkTurnedPart: (stretches: readonly TurnedStretch[], rules: readonly DfmRule[]) => DfmCheck;
|
|
173
860
|
|
|
174
|
-
export { DfmCheck, DfmFeature, DfmHit, DfmRule, FILE_KIND, type FaceTriangles, FeaturePinch, FeatureSheet, type PinchMark, type PlacedTool, RuleProcess, type RuleSetFile, RuleVocabulary, type TurnedReportFeature, type TurnedStretch, Units, type Vec3, checkTurnedPart, hitFigure, llmRulePrompt, parseRuleSetFile, pinchLabel, pinchMark, placePinchTool, sameDepth, serializeRuleSet, turnedStretches };
|
|
861
|
+
export { type BrokenRule, CRITICAL_COLOR, type ClearanceFit, type DfmCheck, type DfmFeature, type DfmHit, type DfmMetric, type DfmOp, type DfmQuantity, type DfmRule, type DfmSources, type DfmSubject, FILE_KIND, type FaceTriangles, type FactsKind, type FeatureAcross, type FeaturePinch, type FeatureProfile, type FeatureRecord, type FeatureRow, type FeatureSheet, type FeatureSheets, type FeatureThreading, type FeatureUndercut, MAX_DATASHEET_FIELDS, MILLING_RULES, type Measurement, OPS, PINCH_TOOL_MM, PRESENCE_METRIC, type PinchDisc, type PinchMark, type PlacedTool, QUICK_SUBJECTS, RANGE_HIGHS, RANGE_LOWS, RULE_COLORS, type RangeHigh, type RangeLow, type ReachCurve, type ReportFeature, type RuleProcess, type RuleResult, type RuleSetFile, type RuleVocabulary, type SurfaceToolKind, TURNING_RULES, type TurnedFactsKind, type TurnedReportFeature, type TurnedStretch, type Units, type Vec3, WARNING_COLOR, brokenRules, checkPart, checkTurnedPart, compareColors, datasheetFields, describeRule, dfmFeatures, directionLabel, featureColor, featureMeasurements, featureProfile, featureRows, featureSheet, featureTypeLabel, formatMeasured, fromField, highOf, hitFigure, isNoReading, isSurfaceType, lengthValue, llmRulePrompt, lowOf, makeRule, maxBallDiameter, metricInfo, metricsForSubject, opSymbol, parseRuleSetFile, parseRules, peakHeight, pinchLabel, pinchMark, placePinchTool, quantityUnit, readPinch, readReachCurve, runStart, sameDepth, serializeRuleSet, subjectLabel, toField, trimmedCurve, turnedStretches, turnedTypeLabel, unitLabel, upperOf, withMetric, withOp, withSubject, withSurroundedFaces };
|