@toolpath/dfm 0.4.0 → 1.0.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 +42 -153
- package/dist/chunk-XHYPKN4E.js +3422 -0
- package/dist/index.d.ts +1 -373
- package/dist/index.js +97 -2593
- package/dist/model/index.d.ts +742 -15
- package/dist/model/index.js +72 -1186
- package/package.json +5 -23
- package/dfm.css +0 -10
- package/dist/chunk-5MPHT7BC.js +0 -1599
- package/dist/feature-record-DHbkVpx0.d.ts +0 -535
package/README.md
CHANGED
|
@@ -1,194 +1,83 @@
|
|
|
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
|
-
|
|
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.
|
|
41
|
+
## Turning rules
|
|
83
42
|
|
|
84
|
-
|
|
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.
|
|
85
48
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
on the right, with their heights and their distances from the feature written
|
|
89
|
-
on. Pointing at the walls reads the curve at that distance.
|
|
49
|
+
```ts
|
|
50
|
+
import { checkTurnedPart, turnedStretches } from '@toolpath/dfm'
|
|
90
51
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const curve = readReachCurve(datasheet) // null where the feature has none
|
|
96
|
-
const feature = featureProfile(sheets[tag], featureType)
|
|
97
|
-
|
|
98
|
-
export const Reach = () =>
|
|
99
|
-
curve ? <ReachChart curve={curve} units="mm" feature={feature} /> : null
|
|
52
|
+
// From a part analysis's `turning.features`.
|
|
53
|
+
const stretches = turnedStretches(report.turning.features)
|
|
54
|
+
const check = checkTurnedPart(stretches, rules)
|
|
100
55
|
```
|
|
101
56
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
draws the walls beside a cutting tool, to show whether the tool fits. This
|
|
109
|
-
draws the walls alone.
|
|
57
|
+
The Engine reports a stretch both ends of the part reach as two features, one
|
|
58
|
+
per end; `turnedStretches` makes them one again, under the first one's tag. A
|
|
59
|
+
stretch breaks a rule only if it breaks it from every end it is cut from, and
|
|
60
|
+
every stretch counts — a turned face has one reading — so nothing is left in
|
|
61
|
+
`otherTags`. Turning is experimental in the API, so a datasheet field that is
|
|
62
|
+
missing or malformed is no figure, never an error.
|
|
110
63
|
|
|
111
|
-
##
|
|
112
|
-
|
|
113
|
-
`FeaturePanel` is the card a click on the part opens: every feature the face
|
|
114
|
-
belongs to, then the details of the one being read. With several faces
|
|
115
|
-
shift-clicked, each face's candidates sit under a letter, above a table of
|
|
116
|
-
what each was read as. It fills what it is put in — where it sits, and
|
|
117
|
-
whether it can be dragged, is the app's — and the app decides what a click
|
|
118
|
-
means: which faces, which candidates in which order, which is read.
|
|
119
|
-
|
|
120
|
-
```tsx
|
|
121
|
-
import { FeatureDetails, FeaturePanel, storageFolds } from '@toolpath/dfm'
|
|
122
|
-
import { brokenRules, featureMeasurements, featureProfile } from '@toolpath/dfm/model'
|
|
123
|
-
|
|
124
|
-
const folds = storageFolds(localStorage, 'toolpath.fold.')
|
|
125
|
-
|
|
126
|
-
export const Inspector = () => (
|
|
127
|
-
<FeaturePanel
|
|
128
|
-
faces={[{ region, rows, selected }]}
|
|
129
|
-
active={0}
|
|
130
|
-
onSelect={(tag) => setSelected(tag)}
|
|
131
|
-
onHover={setHovered}
|
|
132
|
-
onClose={close}
|
|
133
|
-
folds={folds}
|
|
134
|
-
>
|
|
135
|
-
<FeatureDetails
|
|
136
|
-
feature={feature}
|
|
137
|
-
units="mm"
|
|
138
|
-
directionColor={directionHex}
|
|
139
|
-
profile={featureProfile(sheets[key], feature.featureType)}
|
|
140
|
-
required={check.required.has(key)}
|
|
141
|
-
onFrame={() => frame(feature.tag)}
|
|
142
|
-
rules={brokenRules(check, feature.tag, 'mm')}
|
|
143
|
-
measurements={{
|
|
144
|
-
status: 'ready',
|
|
145
|
-
value: featureMeasurements({ features, feature, sheets, units: 'mm' }),
|
|
146
|
-
}}
|
|
147
|
-
record={{ status: 'ready', value: records[key] ?? null }}
|
|
148
|
-
PopOut={AppWindow}
|
|
149
|
-
folds={folds}
|
|
150
|
-
/>
|
|
151
|
-
</FeaturePanel>
|
|
152
|
-
)
|
|
153
|
-
```
|
|
64
|
+
## Rule-set files and the LLM prompt
|
|
154
65
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
- **Rules broken** are `BrokenRule` rows: a colour, the rule's text, the figure
|
|
161
|
-
that broke it, and optionally the limit and a note on hover. `brokenRules`
|
|
162
|
-
builds them from this package's check; an app with a checker of its own
|
|
163
|
-
builds them from its hits.
|
|
164
|
-
- **Measurements** are `featureMeasurements` rows, each with how it was worked
|
|
165
|
-
out behind an ⓘ. `inchMark` writes inches as `0.46"`.
|
|
166
|
-
- **Reach, the datasheet fields and the raw record** read the feature's
|
|
167
|
-
`FeatureRecord`: its report entry and datasheet as the API sent them.
|
|
168
|
-
- **Reads take time.** `measurements` and `record` are `Loadable`. While
|
|
169
|
-
`loading`, a section says what it is reading; on `error` it shows the app's
|
|
170
|
-
message and a Retry, held until `retryAt`.
|
|
171
|
-
- **The look** differs where apps want it to: `look.rules`, `look.selected` and
|
|
172
|
-
`look.muted`. Left out, it is the CAD viewer's.
|
|
173
|
-
- **Folds** are kept in the app's `FoldStore`; `storageFolds(storage, prefix)`
|
|
174
|
-
builds one over a `Storage`. Without one, a section remembers only while it
|
|
175
|
-
is mounted.
|
|
176
|
-
- **Pop-outs** need `PopOut`, the app's window component: the panel decides
|
|
177
|
-
what is open and fills it, and the app draws the frame. Define it at module
|
|
178
|
-
level, and render it through a portal to the page's body: the panel's blur
|
|
179
|
-
makes it the box a `fixed` window inside it would be placed in.
|
|
180
|
-
- **Keys:** Escape closes the panel and the arrow keys walk the candidates. On
|
|
181
|
-
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`.
|
|
182
70
|
|
|
183
71
|
## Pinch points
|
|
184
72
|
|
|
185
73
|
The widest tool a feature admits, standing where the feature is tightest. The
|
|
186
|
-
data is here
|
|
187
|
-
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:
|
|
188
77
|
|
|
189
78
|
```tsx
|
|
190
79
|
import { useMemo } from 'react'
|
|
191
|
-
import { pinchLabel, pinchMark, placePinchTool } from '@toolpath/dfm
|
|
80
|
+
import { pinchLabel, pinchMark, placePinchTool } from '@toolpath/dfm'
|
|
192
81
|
import { featureTriangles, ToolMarks, usePartContext } from '@toolpath/viewer'
|
|
193
82
|
|
|
194
83
|
// A child of <EnginePart> or <PartMesh>, which gives it the part.
|