@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/README.md
CHANGED
|
@@ -1,113 +1,57 @@
|
|
|
1
1
|
# Toolpath DFM
|
|
2
2
|
|
|
3
|
-
`@toolpath/dfm` is the DFM (design for manufacturing)
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
as one JSON file.
|
|
3
|
+
`@toolpath/dfm` is the DFM (design for manufacturing) rules and the part
|
|
4
|
+
checker: what a rule is, how a part's features break it, and the rule-set file
|
|
5
|
+
a set is shared in. **It is logic, data types and functions only** — no React,
|
|
6
|
+
no DOM, no CSS — so a server route can import it as readily as a browser.
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
And it shows a feature as the Engine read it — the feature panel: the features
|
|
13
|
-
a clicked face could mean, the rules the chosen one breaks, what was measured
|
|
14
|
-
of it, its reach, and its datasheet as sent. Its pinch points, the widest tool
|
|
15
|
-
standing where the feature is tightest, are placed here and drawn by
|
|
16
|
-
`@toolpath/viewer`.
|
|
17
|
-
|
|
18
|
-
The rules and the checker that counts them ship too, with no React, under
|
|
19
|
-
`@toolpath/dfm/model`.
|
|
8
|
+
The views that show and edit the rules — `RuleList`, `ReachChart`,
|
|
9
|
+
`FeaturePanel` — are in [`@toolpath/ui`](https://www.npmjs.com/package/@toolpath/ui).
|
|
20
10
|
|
|
21
11
|
## Install
|
|
22
12
|
|
|
23
13
|
```sh
|
|
24
|
-
npm install @toolpath/dfm
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
Add the styles after Tailwind and the `@toolpath/ui` theme:
|
|
28
|
-
|
|
29
|
-
```css
|
|
30
|
-
@import 'tailwindcss';
|
|
31
|
-
@import '@toolpath/ui/theme.css';
|
|
32
|
-
@import '@toolpath/dfm/dfm.css';
|
|
14
|
+
npm install @toolpath/dfm
|
|
33
15
|
```
|
|
34
16
|
|
|
35
17
|
## Exports
|
|
36
18
|
|
|
37
|
-
| Entry point
|
|
38
|
-
|
|
|
39
|
-
| `@toolpath/dfm`
|
|
40
|
-
| `@toolpath/dfm/model`
|
|
41
|
-
| `@toolpath/dfm/dfm.css` | Lets the app's Tailwind see the list's and chart's classes |
|
|
19
|
+
| Entry point | What it is |
|
|
20
|
+
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
21
|
+
| `@toolpath/dfm` | The rules and both vocabularies (`MILLING_RULES`, `TURNING_RULES`), `checkPart` and `checkTurnedPart`, the rule-set file and `llmRulePrompt`, the feature panel's rows, pinch points |
|
|
22
|
+
| `@toolpath/dfm/model` | The same entry, under its name from before the views moved |
|
|
42
23
|
|
|
43
24
|
## The rules are an input
|
|
44
25
|
|
|
45
|
-
The package ships no default rules and stores nothing
|
|
46
|
-
|
|
47
|
-
— in memory, `localStorage`, a server — and passes them in with the functions
|
|
48
|
-
that change them:
|
|
49
|
-
|
|
50
|
-
```tsx
|
|
51
|
-
import { RuleList, type DfmRules } from '@toolpath/dfm'
|
|
52
|
-
import { checkPart, dfmFeatures } from '@toolpath/dfm/model'
|
|
26
|
+
The package ships no default rules and stores nothing. The app keeps the rules
|
|
27
|
+
— in memory, `localStorage`, a server — and checks a part against them:
|
|
53
28
|
|
|
54
|
-
|
|
29
|
+
```ts
|
|
30
|
+
import { checkPart, dfmFeatures } from '@toolpath/dfm'
|
|
55
31
|
|
|
56
32
|
// From a part analysis: the Engine's report, and each feature's datasheet.
|
|
57
33
|
const features = dfmFeatures(report.features)
|
|
58
|
-
const check = checkPart(features, { sheets, datasheets, regionAreas }, rules
|
|
59
|
-
|
|
60
|
-
<RuleList
|
|
61
|
-
rules={rules}
|
|
62
|
-
check={check} // null while the part is still being analysed
|
|
63
|
-
features={features}
|
|
64
|
-
sheets={sheets}
|
|
65
|
-
units="mm"
|
|
66
|
-
selected={selectedTag}
|
|
67
|
-
selectedGroup={selectedGroup}
|
|
68
|
-
onInspect={(tag, group) => inspect(tag, group)}
|
|
69
|
-
onHover={(hovered) => highlight(hovered)}
|
|
70
|
-
/>
|
|
34
|
+
const check = checkPart(features, { sheets, datasheets, regionAreas }, rules)
|
|
71
35
|
```
|
|
72
36
|
|
|
73
37
|
`sheets` is each feature's measurements, built with `featureSheet` from its
|
|
74
38
|
datasheet; `datasheets` is the datasheets as the API sent them, both by
|
|
75
39
|
lower-cased feature tag; `regionAreas` is each face's area by region index.
|
|
76
40
|
|
|
77
|
-
Put `ruleListKeys` on the panel that holds the list, so the arrow keys walk the
|
|
78
|
-
rules from anywhere in it.
|
|
79
|
-
|
|
80
|
-
`actions` puts the app's own buttons at the end of the footer's row, after
|
|
81
|
-
Import…, Export and Copy LLM prompt — a way back to the app's default rules,
|
|
82
|
-
say, since the package has none of its own.
|
|
83
|
-
|
|
84
41
|
## Turning rules
|
|
85
42
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
Every helper that reads a rule takes the vocabulary last, and reads milling
|
|
92
|
-
where it is left out.
|
|
43
|
+
`TURNING_RULES` is the turning vocabulary: turned subjects (grooves, threads,
|
|
44
|
+
axial holes, OD and ID features) and their measures. Each vocabulary keeps its
|
|
45
|
+
own rules: a rule-set file of the other process is refused, and
|
|
46
|
+
`parseRules(raw, TURNING_RULES)` drops milling ones. Every helper that reads a
|
|
47
|
+
rule takes the vocabulary last, and reads milling where it is left out.
|
|
93
48
|
|
|
94
|
-
```
|
|
95
|
-
import {
|
|
96
|
-
import { checkTurnedPart, turnedStretches } from '@toolpath/dfm/model'
|
|
49
|
+
```ts
|
|
50
|
+
import { checkTurnedPart, turnedStretches } from '@toolpath/dfm'
|
|
97
51
|
|
|
98
52
|
// From a part analysis's `turning.features`.
|
|
99
53
|
const stretches = turnedStretches(report.turning.features)
|
|
100
|
-
const check = checkTurnedPart(stretches, rules
|
|
101
|
-
|
|
102
|
-
<RuleList
|
|
103
|
-
rules={rules}
|
|
104
|
-
vocabulary={TURNING_RULES}
|
|
105
|
-
check={check}
|
|
106
|
-
features={stretches}
|
|
107
|
-
sheets={{}}
|
|
108
|
-
units="mm"
|
|
109
|
-
{...rest}
|
|
110
|
-
/>
|
|
54
|
+
const check = checkTurnedPart(stretches, rules)
|
|
111
55
|
```
|
|
112
56
|
|
|
113
57
|
The Engine reports a stretch both ends of the part reach as two features, one
|
|
@@ -117,120 +61,23 @@ every stretch counts — a turned face has one reading — so nothing is left in
|
|
|
117
61
|
`otherTags`. Turning is experimental in the API, so a datasheet field that is
|
|
118
62
|
missing or malformed is no figure, never an error.
|
|
119
63
|
|
|
120
|
-
##
|
|
121
|
-
|
|
122
|
-
`ReachChart` draws a feature's reach curve: the section through the part at the
|
|
123
|
-
feature's wall, to scale. The feature is on the left, in blue; the walls step up
|
|
124
|
-
on the right, with their heights and their distances from the feature written
|
|
125
|
-
on. Pointing at the walls reads the curve at that distance.
|
|
126
|
-
|
|
127
|
-
```tsx
|
|
128
|
-
import { ReachChart, ReachDrawing } from '@toolpath/dfm'
|
|
129
|
-
import { featureProfile, readReachCurve } from '@toolpath/dfm/model'
|
|
130
|
-
|
|
131
|
-
const curve = readReachCurve(datasheet) // null where the feature has none
|
|
132
|
-
const feature = featureProfile(sheets[tag], featureType)
|
|
133
|
-
|
|
134
|
-
export const Reach = () =>
|
|
135
|
-
curve ? <ReachChart curve={curve} units="mm" feature={feature} /> : null
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
`ReachChart` is as wide as its container. `ReachDrawing` is the same section
|
|
139
|
-
with a caption and a note on how to read it, for a larger window of its own.
|
|
140
|
-
Both stop drawing the curve half an inch past where the walls reach full
|
|
141
|
-
height; `ReachDrawing` says so in its note.
|
|
142
|
-
|
|
143
|
-
This is not the clearance overlay in `@toolpath/tool-drawing/clearance`: that
|
|
144
|
-
draws the walls beside a cutting tool, to show whether the tool fits. This
|
|
145
|
-
draws the walls alone.
|
|
146
|
-
|
|
147
|
-
## Feature panel
|
|
148
|
-
|
|
149
|
-
`FeaturePanel` is the card a click on the part opens: every feature the face
|
|
150
|
-
belongs to, then the details of the one being read. With several faces
|
|
151
|
-
shift-clicked, each face's candidates sit under a letter, above a table of
|
|
152
|
-
what each was read as. It fills what it is put in — where it sits, and
|
|
153
|
-
whether it can be dragged, is the app's — and the app decides what a click
|
|
154
|
-
means: which faces, which candidates in which order, which is read.
|
|
155
|
-
|
|
156
|
-
```tsx
|
|
157
|
-
import { FeatureDetails, FeaturePanel, storageFolds } from '@toolpath/dfm'
|
|
158
|
-
import { brokenRules, featureMeasurements, featureProfile } from '@toolpath/dfm/model'
|
|
159
|
-
|
|
160
|
-
const folds = storageFolds(localStorage, 'toolpath.fold.')
|
|
161
|
-
|
|
162
|
-
export const Inspector = () => (
|
|
163
|
-
<FeaturePanel
|
|
164
|
-
faces={[{ region, rows, selected }]}
|
|
165
|
-
active={0}
|
|
166
|
-
onSelect={(tag) => setSelected(tag)}
|
|
167
|
-
onHover={setHovered}
|
|
168
|
-
onClose={close}
|
|
169
|
-
folds={folds}
|
|
170
|
-
>
|
|
171
|
-
<FeatureDetails
|
|
172
|
-
feature={feature}
|
|
173
|
-
units="mm"
|
|
174
|
-
directionColor={directionHex}
|
|
175
|
-
profile={featureProfile(sheets[key], feature.featureType)}
|
|
176
|
-
required={check.required.has(key)}
|
|
177
|
-
onFrame={() => frame(feature.tag)}
|
|
178
|
-
rules={brokenRules(check, feature.tag, 'mm')}
|
|
179
|
-
measurements={{
|
|
180
|
-
status: 'ready',
|
|
181
|
-
value: featureMeasurements({ features, feature, sheets, units: 'mm' }),
|
|
182
|
-
}}
|
|
183
|
-
record={{ status: 'ready', value: records[key] ?? null }}
|
|
184
|
-
PopOut={AppWindow}
|
|
185
|
-
folds={folds}
|
|
186
|
-
/>
|
|
187
|
-
</FeaturePanel>
|
|
188
|
-
)
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
The parts work alone too. An app with an inspect panel of its own puts
|
|
192
|
-
`CandidateList` and `FeatureDetails` in it and fills their slots with its own
|
|
193
|
-
controls — a folder in a row's `detail`, a Pin button in its `action`, Zoom to
|
|
194
|
-
in the details' `actions`, a folder badge in `status`.
|
|
195
|
-
|
|
196
|
-
A turned feature reads the same way: give `FeaturePanel`, `CandidateList` and
|
|
197
|
-
`FeatureDetails` `vocabulary={TURNING_RULES}` and a stretch from
|
|
198
|
-
`turnedStretches`, and the feature is named as a turned one — "OD groove from
|
|
199
|
-
both ends", "Machined from both ends" — with its considerations under
|
|
200
|
-
"Turning considerations". Milling is the default.
|
|
64
|
+
## Rule-set files and the LLM prompt
|
|
201
65
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
- **Measurements** are `featureMeasurements` rows, each with how it was worked
|
|
207
|
-
out behind an ⓘ. `inchMark` writes inches as `0.46"`.
|
|
208
|
-
- **Reach, the datasheet fields and the raw record** read the feature's
|
|
209
|
-
`FeatureRecord`: its report entry and datasheet as the API sent them.
|
|
210
|
-
- **Reads take time.** `measurements` and `record` are `Loadable`. While
|
|
211
|
-
`loading`, a section says what it is reading; on `error` it shows the app's
|
|
212
|
-
message and a Retry, held until `retryAt`.
|
|
213
|
-
- **The look** differs where apps want it to: `look.rules`, `look.selected` and
|
|
214
|
-
`look.muted`. Left out, it is the CAD viewer's.
|
|
215
|
-
- **Folds** are kept in the app's `FoldStore`; `storageFolds(storage, prefix)`
|
|
216
|
-
builds one over a `Storage`. Without one, a section remembers only while it
|
|
217
|
-
is mounted.
|
|
218
|
-
- **Pop-outs** need `PopOut`, the app's window component: the panel decides
|
|
219
|
-
what is open and fills it, and the app draws the frame. Define it at module
|
|
220
|
-
level, and render it through a portal to the page's body: the panel's blur
|
|
221
|
-
makes it the box a `fixed` window inside it would be placed in.
|
|
222
|
-
- **Keys:** Escape closes the panel and the arrow keys walk the candidates. On
|
|
223
|
-
a `CandidateList` used alone, put `candidateListKeys` on whatever holds it.
|
|
66
|
+
`serializeRuleSet` writes a set as one JSON file and `parseRuleSetFile` reads
|
|
67
|
+
one back. `llmRulePrompt(rules, vocabulary)` is a prompt that walks an LLM
|
|
68
|
+
through writing a set for a shop. The rule list in `@toolpath/ui` has no button
|
|
69
|
+
for it; an app that wants one adds it through the list's `actions`.
|
|
224
70
|
|
|
225
71
|
## Pinch points
|
|
226
72
|
|
|
227
73
|
The widest tool a feature admits, standing where the feature is tightest. The
|
|
228
|
-
data is here
|
|
229
|
-
nothing of
|
|
74
|
+
data is here. **Drawing it is the viewer's job, and needs `@toolpath/viewer`**;
|
|
75
|
+
this package does not depend on it. The viewer's `<ToolMarks>` knows nothing of
|
|
76
|
+
datasheets:
|
|
230
77
|
|
|
231
78
|
```tsx
|
|
232
79
|
import { useMemo } from 'react'
|
|
233
|
-
import { pinchLabel, pinchMark, placePinchTool } from '@toolpath/dfm
|
|
80
|
+
import { pinchLabel, pinchMark, placePinchTool } from '@toolpath/dfm'
|
|
234
81
|
import { featureTriangles, ToolMarks, usePartContext } from '@toolpath/viewer'
|
|
235
82
|
|
|
236
83
|
// A child of <EnginePart> or <PartMesh>, which gives it the part.
|