axstack 0.36.1 → 0.38.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 +5 -4
- package/bin/axstack.js +4 -18
- package/docs/getting-started.md +6 -6
- package/docs/host-operations.md +9 -5
- package/docs/installation.md +20 -41
- package/docs/workflows.md +12 -9
- package/package.json +1 -1
- package/profiles/presets/claude-only.json +3 -3
- package/profiles/presets/codex-only.json +3 -3
- package/profiles/presets/mixed.json +5 -4
- package/skills/axstack/references/automations.md +7 -2
- package/skills/axstack/references/lifecycle.md +2 -1
- package/skills/axstack/references/review-manager-prompt.md +44 -3
- package/skills/axstack/references/role-roster.md +13 -6
- package/skills/axstack/references/routing.md +2 -1
- package/skills/axstack/references/run-record.md +2 -0
- package/skills/axstack/references/ui-verification.md +6 -10
- package/skills/axstack-anatomy/ANATOMY.md +172 -0
- package/skills/axstack-anatomy/CHANGELOG.md +70 -0
- package/skills/axstack-anatomy/LICENSE +21 -0
- package/skills/axstack-anatomy/PROVENANCE.md +21 -0
- package/skills/axstack-anatomy/README.md +316 -0
- package/skills/axstack-anatomy/SKILL.md +74 -0
- package/skills/axstack-anatomy/SOURCE-PROOF.json +107 -0
- package/skills/axstack-anatomy/examples/arcade-cabinet/arcade-cabinet.css +44 -0
- package/skills/axstack-anatomy/examples/arcade-cabinet/build.mjs +714 -0
- package/skills/axstack-anatomy/examples/arcade-cabinet/live.js +597 -0
- package/skills/axstack-anatomy/examples/arcade-cabinet/parts.mjs +89 -0
- package/skills/axstack-anatomy/examples/arcade-cabinet/screen.mjs +114 -0
- package/skills/axstack-anatomy/examples/desk-computer/build.mjs +435 -0
- package/skills/axstack-anatomy/examples/dial-indicator/build.mjs +275 -0
- package/skills/axstack-anatomy/examples/raptor-engine/build.mjs +938 -0
- package/skills/axstack-anatomy/examples/raptor-engine/live.js +907 -0
- package/skills/axstack-anatomy/examples/raptor-engine/raptor.css +359 -0
- package/skills/axstack-anatomy/examples/ripple-tank/build.mjs +558 -0
- package/skills/axstack-anatomy/examples/ripple-tank/live.js +579 -0
- package/skills/axstack-anatomy/examples/ripple-tank/model.mjs +131 -0
- package/skills/axstack-anatomy/examples/ripple-tank/ripple.css +103 -0
- package/skills/axstack-anatomy/examples/spot-plate/art.tsx +110 -0
- package/skills/axstack-anatomy/examples/spot-plate/drops.ts +541 -0
- package/skills/axstack-anatomy/examples/spot-plate/fan.ts +84 -0
- package/skills/axstack-anatomy/examples/spot-plate/figure.tsx +25 -0
- package/skills/axstack-anatomy/examples/spot-plate/geometry.ts +280 -0
- package/skills/axstack-anatomy/examples/spot-plate/live.tsx +339 -0
- package/skills/axstack-anatomy/examples/spot-plate/rig.ts +230 -0
- package/skills/axstack-anatomy/examples/spot-plate/spot-plate.css +92 -0
- package/skills/axstack-anatomy/examples/test-rig/art.tsx +196 -0
- package/skills/axstack-anatomy/examples/test-rig/figure.tsx +23 -0
- package/skills/axstack-anatomy/examples/test-rig/geometry.ts +305 -0
- package/skills/axstack-anatomy/examples/test-rig/live.tsx +511 -0
- package/skills/axstack-anatomy/examples/test-rig/pose.ts +107 -0
- package/skills/axstack-anatomy/examples/test-rig/rig.ts +170 -0
- package/skills/axstack-anatomy/examples/test-rig/stretch.css +80 -0
- package/skills/axstack-anatomy/examples/test-rig/view.ts +99 -0
- package/skills/axstack-anatomy/examples/turning-dial/build.mjs +479 -0
- package/skills/axstack-anatomy/examples/turning-dial/dial.css +10 -0
- package/skills/axstack-anatomy/examples/turning-dial/live.js +342 -0
- package/skills/axstack-anatomy/examples/turning-dial/stress.mjs +269 -0
- package/skills/axstack-anatomy/kit/audit.mjs +1913 -0
- package/skills/axstack-anatomy/kit/canvas-painter.mjs +722 -0
- package/skills/axstack-anatomy/kit/gl-shared.mjs +184 -0
- package/skills/axstack-anatomy/kit/gl.mjs +184 -0
- package/skills/axstack-anatomy/kit/iso-kit.mjs +674 -0
- package/skills/axstack-anatomy/kit/iso-kit.ts +842 -0
- package/skills/axstack-anatomy/kit/iso.css +106 -0
- package/skills/axstack-anatomy/kit/lathe.mjs +1184 -0
- package/skills/axstack-anatomy/kit/react/draw.tsx +205 -0
- package/skills/axstack-anatomy/kit/react/live.tsx +140 -0
- package/skills/axstack-anatomy/kit/tube.mjs +306 -0
- package/skills/axstack-anatomy/kit/turn-audit.mjs +1096 -0
- package/skills/axstack-anatomy/kit/turn-build.mjs +1355 -0
- package/skills/axstack-anatomy/kit/turn-fixed.mjs +3800 -0
- package/skills/axstack-anatomy/kit/turn.mjs +3610 -0
- package/skills/axstack-anatomy/references/3d.md +352 -0
- package/skills/axstack-anatomy/references/craft.md +325 -0
- package/skills/axstack-anatomy/references/kit.md +419 -0
- package/skills/axstack-anatomy/references/motion.md +165 -0
- package/skills/axstack-anatomy/references/react.md +42 -0
- package/skills/axstack-anatomy/references/verify.md +351 -0
- package/skills/axstack-anatomy/references/walkthrough.md +75 -0
- package/skills/axstack-anatomy/references/webgl.md +473 -0
- package/skills/axstack-anatomy/scripts/audit-affine-bounds.test.mjs +54 -0
- package/skills/axstack-anatomy/scripts/audit-cache.test.mjs +37 -0
- package/skills/axstack-anatomy/scripts/audit-clearance-envelope.test.mjs +39 -0
- package/skills/axstack-anatomy/scripts/audit-empty-clipping.test.mjs +38 -0
- package/skills/axstack-anatomy/scripts/audit-order-convergence.test.mjs +55 -0
- package/skills/axstack-anatomy/scripts/audit-path-origin.test.mjs +26 -0
- package/skills/axstack-anatomy/scripts/audit-profile.test.mjs +41 -0
- package/skills/axstack-anatomy/scripts/audit-projection.test.mjs +36 -0
- package/skills/axstack-anatomy/scripts/audit-slide-clearance.test.mjs +58 -0
- package/skills/axstack-anatomy/scripts/audit-svg-attributes.test.mjs +46 -0
- package/skills/axstack-anatomy/scripts/audit-taper.test.mjs +29 -0
- package/skills/axstack-anatomy/scripts/capture-selector.test.mjs +131 -0
- package/skills/axstack-anatomy/scripts/capture.mjs +228 -0
- package/skills/axstack-anatomy/scripts/capture.test.mjs +42 -0
- package/skills/axstack-anatomy/scripts/chrome-port.mjs +36 -0
- package/skills/axstack-anatomy/scripts/chrome-startup.test.mjs +38 -0
- package/skills/axstack-anatomy/scripts/drive-actions.test.mjs +46 -0
- package/skills/axstack-anatomy/scripts/drive.mjs +302 -0
- package/skills/axstack-anatomy/scripts/drive.test.mjs +72 -0
- package/skills/axstack-anatomy/scripts/enter-key.test.mjs +38 -0
- package/skills/axstack-anatomy/scripts/fidelity-cut.test.mjs +54 -0
- package/skills/axstack-anatomy/scripts/fidelity-tube-coverage.test.mjs +40 -0
- package/skills/axstack-anatomy/scripts/inline-kit.mjs +26 -0
- package/skills/axstack-anatomy/scripts/line-ends.mjs +306 -0
- package/skills/axstack-anatomy/scripts/lines-arcs.test.mjs +50 -0
- package/skills/axstack-anatomy/scripts/lines-bezier.test.mjs +28 -0
- package/skills/axstack-anatomy/scripts/lines-round.test.mjs +56 -0
- package/skills/axstack-anatomy/scripts/lines-rounded-rect.test.mjs +32 -0
- package/skills/axstack-anatomy/scripts/lines.mjs +31 -0
- package/skills/axstack-anatomy/scripts/lines.test.mjs +38 -0
- package/skills/axstack-anatomy/scripts/navigation.test.mjs +55 -0
- package/skills/axstack-anatomy/scripts/orbit-sampling.test.mjs +50 -0
- package/skills/axstack-anatomy/scripts/react-dots-opacity.test.mjs +51 -0
- package/skills/axstack-anatomy/scripts/react-readout-first-write.test.mjs +37 -0
- package/skills/axstack-anatomy/scripts/react-solid-seamless.test.mjs +47 -0
- package/skills/axstack-anatomy/scripts/react-visibility-target.test.mjs +38 -0
- package/skills/axstack-anatomy/scripts/turn-bench.mjs +74 -0
- package/skills/axstack-anatomy/scripts/turn-check.mjs +641 -0
- package/skills/axstack-anatomy/scripts/turn-fidelity.mjs +413 -0
- package/skills/axstack-anatomy/scripts/turn-group-reference.test.mjs +40 -0
- package/skills/axstack-anatomy/scripts/turn-split-owner.test.mjs +62 -0
- package/skills/axstack-anatomy/theme.js +56 -0
- package/skills/axstack-explain/SKILL.md +28 -15
- package/skills/axstack-explain/references/delivery.md +22 -0
- package/skills/{axstack-diagram → axstack-explain}/references/fidelity.md +1 -7
- package/skills/axstack-explain/references/inline-pages.md +8 -8
- package/skills/axstack-explain/references/visual-qa.md +3 -5
- package/skills/axstack-explain/references/whiteboard-defense.md +59 -0
- package/skills/axstack-research/SKILL.md +18 -6
- package/src/archify-legacy.js +70 -0
- package/src/capabilities.js +1 -29
- package/src/installer.js +11 -31
- package/skills/axstack-diagram/SKILL.md +0 -28
- package/skills/axstack-diagram/references/archify.md +0 -76
- package/src/archify-pin.js +0 -5
- package/src/archify.js +0 -151
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
export type Pair = [number, number];
|
|
2
|
+
export type Tuning = readonly [number, number];
|
|
3
|
+
|
|
4
|
+
export interface Spring {
|
|
5
|
+
at: number;
|
|
6
|
+
rate: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface Member {
|
|
10
|
+
swell: Spring;
|
|
11
|
+
lean: Spring;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface Pose {
|
|
15
|
+
mid: number;
|
|
16
|
+
half: Pair;
|
|
17
|
+
lean: number;
|
|
18
|
+
press: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const HALF: Pair = [60, 16];
|
|
22
|
+
export const SWELL = 0.08;
|
|
23
|
+
export const SWELL_MOST = 6;
|
|
24
|
+
export const SWELL_FLOOR = -0.25;
|
|
25
|
+
export const RUBBER = 0.55;
|
|
26
|
+
const STRETCH = 0.35;
|
|
27
|
+
export const STRETCH_MOST = 0.08;
|
|
28
|
+
const THIN = 0.5;
|
|
29
|
+
const SOFT = 1;
|
|
30
|
+
export const GIVE = 14;
|
|
31
|
+
export const REACH = 0.15;
|
|
32
|
+
export const GIVE_MOST = 0.25;
|
|
33
|
+
const QUIET = 0.0005;
|
|
34
|
+
const SUB_RATE = 240;
|
|
35
|
+
export const FRAME = 1 / 60;
|
|
36
|
+
|
|
37
|
+
export const PRESS_SPRING: Tuning = [700, 32];
|
|
38
|
+
export const HOLD_SPRING: Tuning = [540, 40];
|
|
39
|
+
export const RELEASE_SPRING: Tuning = [320, 16];
|
|
40
|
+
|
|
41
|
+
const LONGEST = Math.max(HALF[0], HALF[1]);
|
|
42
|
+
export const SHARE = Math.min(SWELL, SWELL_MOST / LONGEST);
|
|
43
|
+
export const GIVEN = Math.min(GIVE, REACH * 2 * LONGEST);
|
|
44
|
+
export const ACROSS = (GIVEN * HALF[1]) / LONGEST;
|
|
45
|
+
|
|
46
|
+
export const zeta = ([stiff, drag]: Tuning) => drag / (2 * Math.sqrt(stiff));
|
|
47
|
+
|
|
48
|
+
function spring(held: Spring, want: number, dt: number, [stiff, drag]: Tuning, calm: boolean) {
|
|
49
|
+
const damping = calm ? 2 * Math.sqrt(stiff) : drag;
|
|
50
|
+
const steps = Math.max(Math.ceil(dt * SUB_RATE), 1);
|
|
51
|
+
const slice = dt / steps;
|
|
52
|
+
for (let step = 0; step < steps; step++) {
|
|
53
|
+
held.rate += (want - held.at) * stiff * slice - held.rate * damping * slice;
|
|
54
|
+
held.at += held.rate * slice;
|
|
55
|
+
}
|
|
56
|
+
if (Math.abs(want - held.at) < QUIET && Math.abs(held.rate) < QUIET) {
|
|
57
|
+
held.at = want;
|
|
58
|
+
held.rate = 0;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function rubberBand(distance: number, limit: number) {
|
|
63
|
+
return limit <= 0 ? 0 : limit * (1 - 1 / (1 + (RUBBER * distance) / limit));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const softened = (value: number) => Math.hypot(value, SOFT) - SOFT;
|
|
67
|
+
|
|
68
|
+
function stretched(lean: number, half: number, grow: number) {
|
|
69
|
+
const most = STRETCH_MOST * grow * half;
|
|
70
|
+
return most * Math.tanh((STRETCH * softened(lean)) / most);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const grownOf = (member: Member) => 1 + SHARE * Math.max(member.swell.at, SWELL_FLOOR);
|
|
74
|
+
|
|
75
|
+
export const memberAt = (swell = 0, lean = 0): Member => ({ swell: { at: swell, rate: 0 }, lean: { at: lean, rate: 0 } });
|
|
76
|
+
|
|
77
|
+
export function step(member: Member, held: boolean, pull: number, dt: number, calm = false) {
|
|
78
|
+
spring(member.swell, held ? 1 : 0, dt, held ? PRESS_SPRING : RELEASE_SPRING, calm);
|
|
79
|
+
const want = held && !calm ? Math.sign(pull) * rubberBand(Math.abs(pull), GIVEN) : 0;
|
|
80
|
+
spring(member.lean, want, dt, held ? HOLD_SPRING : RELEASE_SPRING, calm);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function poseOf(member: Member): Pose {
|
|
84
|
+
const grow = grownOf(member);
|
|
85
|
+
const lean = member.lean.at;
|
|
86
|
+
const stretch = stretched(lean, HALF[0], grow);
|
|
87
|
+
const ratio = 1 + stretch / (grow * HALF[0]);
|
|
88
|
+
return {
|
|
89
|
+
mid: lean - Math.sign(lean) * stretch,
|
|
90
|
+
half: [grow * HALF[0] * ratio, grow * HALF[1] * Math.pow(ratio, -THIN)],
|
|
91
|
+
lean,
|
|
92
|
+
press: Math.min(Math.max(member.swell.at, 0), 1.2),
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export const carried = (pose: Pose, x: number) => pose.mid + (pose.half[0] / HALF[0]) * x;
|
|
97
|
+
|
|
98
|
+
export const settled = (member: Member, held: boolean, pull: number) =>
|
|
99
|
+
member.swell.rate === 0 && member.lean.rate === 0 && member.swell.at === (held ? 1 : 0) && (held || member.lean.at === 0) && (held || pull === 0);
|
|
100
|
+
|
|
101
|
+
export const one = (value: number) => {
|
|
102
|
+
const text = (Math.round(value * 10) / 10).toFixed(1);
|
|
103
|
+
return text === "-0.0" ? "0.0" : text;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
export const two = (value: number) => (Math.round(value * 100) / 100).toFixed(2);
|
|
107
|
+
|
|
108
|
+
export const sizeText = (pose: Pose) => `${one(pose.half[0] * 2)} × ${one(pose.half[1] * 2)}`;
|
|
109
|
+
|
|
110
|
+
export function steady(pull: number) {
|
|
111
|
+
const member = memberAt();
|
|
112
|
+
for (let frame = 0; frame < 360; frame++) step(member, true, pull, FRAME);
|
|
113
|
+
return poseOf(member);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function pressRun() {
|
|
117
|
+
const member = memberAt();
|
|
118
|
+
let peak = 0;
|
|
119
|
+
let peakAt = 0;
|
|
120
|
+
for (let frame = 1; frame <= 120; frame++) {
|
|
121
|
+
step(member, true, 0, FRAME);
|
|
122
|
+
const tall = poseOf(member).half[1] * 2;
|
|
123
|
+
if (tall > peak) {
|
|
124
|
+
peak = tall;
|
|
125
|
+
peakAt = frame * FRAME;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return { peak, peakAt };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export const STILL_ENOUGH = 0.1;
|
|
132
|
+
|
|
133
|
+
function releaseRun(pull: number) {
|
|
134
|
+
const member = memberAt();
|
|
135
|
+
for (let frame = 0; frame < 360; frame++) step(member, true, pull, FRAME);
|
|
136
|
+
let swing = 0;
|
|
137
|
+
let swingAt = 0;
|
|
138
|
+
let dip = 0;
|
|
139
|
+
let still = 0;
|
|
140
|
+
for (let frame = 1; frame <= 300; frame++) {
|
|
141
|
+
step(member, false, 0, FRAME);
|
|
142
|
+
const lean = member.lean.at;
|
|
143
|
+
if (-Math.sign(pull) * lean > swing) {
|
|
144
|
+
swing = -Math.sign(pull) * lean;
|
|
145
|
+
swingAt = frame * FRAME;
|
|
146
|
+
}
|
|
147
|
+
dip = Math.max(dip, (1 - grownOf(member)) * 100);
|
|
148
|
+
const pose = poseOf(member);
|
|
149
|
+
const edges = [pose.mid - pose.half[0], pose.mid + pose.half[0], -pose.half[1], pose.half[1]];
|
|
150
|
+
const rest = [-HALF[0], HALF[0], -HALF[1], HALF[1]];
|
|
151
|
+
const off = Math.max(...edges.map((edge, index) => Math.abs(edge - rest[index]!)));
|
|
152
|
+
if (off > STILL_ENOUGH) still = (frame + 1) * FRAME;
|
|
153
|
+
}
|
|
154
|
+
return { swing, swingAt, dip, still };
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export const DRAG = 80;
|
|
158
|
+
export const PULL_MOST = 110;
|
|
159
|
+
export const REST: Pose = { mid: 0, half: [HALF[0], HALF[1]], lean: 0, press: 0 };
|
|
160
|
+
export const PRESSED = steady(0);
|
|
161
|
+
export const PULLED = steady(-DRAG);
|
|
162
|
+
export const PULLED_MOST = steady(-PULL_MOST);
|
|
163
|
+
export const PRESS_RUN = pressRun();
|
|
164
|
+
export const RELEASE_RUN = releaseRun(-DRAG);
|
|
165
|
+
export const DIP_MOST = -SWELL_FLOOR * SHARE * 100;
|
|
166
|
+
export const SIDE_GROWTH = SHARE * HALF[0];
|
|
167
|
+
|
|
168
|
+
export function readoutOf(pose: Pose) {
|
|
169
|
+
return `${sizeText(pose)} · lean ${one(Math.abs(pose.lean))} px`;
|
|
170
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
.ms {
|
|
2
|
+
--ms-glass-top: #262626;
|
|
3
|
+
--ms-glass-lit-top: #2e2e2e;
|
|
4
|
+
border-radius: 10px;
|
|
5
|
+
cursor: grab;
|
|
6
|
+
touch-action: pan-y;
|
|
7
|
+
-webkit-tap-highlight-color: transparent;
|
|
8
|
+
-webkit-user-select: none;
|
|
9
|
+
user-select: none;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.iso[data-theme="light"] .ms {
|
|
13
|
+
--ms-glass-top: #fefefd;
|
|
14
|
+
--ms-glass-lit-top: #fffffe;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.ms[data-held] {
|
|
18
|
+
cursor: grabbing;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.ms:focus-visible {
|
|
22
|
+
outline: 1px solid var(--anatomy-muted);
|
|
23
|
+
outline-offset: 6px;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.ms .iso-svg {
|
|
27
|
+
overflow: visible;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.ms-glass > .iso-top {
|
|
31
|
+
fill: var(--ms-glass-top);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.ms-glass[data-lit] > .iso-top {
|
|
35
|
+
fill: var(--ms-glass-lit-top);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.ms-glass[data-lit] > .iso-edge {
|
|
39
|
+
stroke: var(--anatomy-lit);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.ms-shine {
|
|
43
|
+
stroke-linecap: round;
|
|
44
|
+
opacity: 0.55;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.ms-shadow {
|
|
48
|
+
filter: blur(4px);
|
|
49
|
+
opacity: 0.8;
|
|
50
|
+
transform: translateY(1px);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.ms-coil {
|
|
54
|
+
stroke-linejoin: round;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.ms-needle {
|
|
58
|
+
fill: var(--anatomy-lit-top);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.ms-pull .iso-wire-end {
|
|
62
|
+
transition: opacity 160ms var(--anatomy-ease);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@media (prefers-reduced-motion: reduce) {
|
|
66
|
+
.ms * {
|
|
67
|
+
transition: none !important;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@media (max-width: 640px) {
|
|
72
|
+
.ms {
|
|
73
|
+
overflow: hidden;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.iso-plate .ms .iso-svg {
|
|
77
|
+
width: 118%;
|
|
78
|
+
margin: -4% -9% -3%;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { iso, type Flat, type Plan, type Point3, type Projection } from "../../kit/iso-kit";
|
|
2
|
+
|
|
3
|
+
export const WIDTH = 600;
|
|
4
|
+
export const HEIGHT = 340;
|
|
5
|
+
const PAD = 34;
|
|
6
|
+
export const AZIMUTH = 57;
|
|
7
|
+
|
|
8
|
+
export const BASE: Plan = { x: -134, y: -82, w: 298, d: 150, r: 9 };
|
|
9
|
+
export const BASE_H = 9;
|
|
10
|
+
export const FOOT_H = 5;
|
|
11
|
+
|
|
12
|
+
export const FRAME_X = 101;
|
|
13
|
+
export const FRAME_Y = 37;
|
|
14
|
+
export const BAR = 9;
|
|
15
|
+
export const BAR_H = 12;
|
|
16
|
+
|
|
17
|
+
export const ROD_Y = 18;
|
|
18
|
+
export const ROD_Z = 6;
|
|
19
|
+
export const ROD_HALF = 2;
|
|
20
|
+
export const COIL_R = 4.2;
|
|
21
|
+
export const COIL_TURNS = 6;
|
|
22
|
+
|
|
23
|
+
export const CARRIAGE: Plan = { x: -72, y: -26, w: 144, d: 52, r: 4 };
|
|
24
|
+
export const CARRIAGE_Z = 3;
|
|
25
|
+
export const CARRIAGE_H = 5;
|
|
26
|
+
export const CARRIAGE_TOP = CARRIAGE_Z + CARRIAGE_H;
|
|
27
|
+
export const BUSH_END = 80;
|
|
28
|
+
export const BUSH_W = 14;
|
|
29
|
+
export const BUSH_D = 12;
|
|
30
|
+
|
|
31
|
+
export const GLASS_Z = CARRIAGE_TOP;
|
|
32
|
+
export const GLASS_H = 10;
|
|
33
|
+
export const GLASS_TOP = GLASS_Z + GLASS_H;
|
|
34
|
+
|
|
35
|
+
export const PLUNGER_Z = 6;
|
|
36
|
+
export const DIAL: Flat = [131, 0];
|
|
37
|
+
export const DIAL_R = 15;
|
|
38
|
+
export const DIAL_Z = 3;
|
|
39
|
+
export const DIAL_H = 8;
|
|
40
|
+
export const DIAL_TOP = DIAL_Z + DIAL_H;
|
|
41
|
+
export const DIAL_SPAN = 20;
|
|
42
|
+
|
|
43
|
+
export const RAIL_Y = -66;
|
|
44
|
+
export const RAIL_D = 8;
|
|
45
|
+
export const RAIL_Z = 50;
|
|
46
|
+
export const RAIL_H = 8;
|
|
47
|
+
export const POST_L = -124;
|
|
48
|
+
export const POST_R = 66;
|
|
49
|
+
export const POST = 12;
|
|
50
|
+
|
|
51
|
+
export const PROBE_HOME = 45;
|
|
52
|
+
export const PROBE_MIN = -98;
|
|
53
|
+
export const PROBE_MAX = 48;
|
|
54
|
+
export const HOUSING_R = 5.5;
|
|
55
|
+
export const HOUSING_Z = 44;
|
|
56
|
+
export const HOUSING_H = 20;
|
|
57
|
+
export const PAD_R = 4.4;
|
|
58
|
+
export const PAD_H = 3;
|
|
59
|
+
export const HOVER = 12;
|
|
60
|
+
export const STEM = 28;
|
|
61
|
+
|
|
62
|
+
export const GRAB_MOST = 52;
|
|
63
|
+
export const FINGER_MOST = 62;
|
|
64
|
+
|
|
65
|
+
function fit(points: Point3[]): Projection {
|
|
66
|
+
const unit: Projection = { origin: [0, 0], scale: 1, azimuth: AZIMUTH };
|
|
67
|
+
const flat = points.map((point) => iso(point, unit));
|
|
68
|
+
const xs = flat.map(([x]) => x);
|
|
69
|
+
const ys = flat.map(([, y]) => y);
|
|
70
|
+
const left = Math.min(...xs);
|
|
71
|
+
const right = Math.max(...xs);
|
|
72
|
+
const up = Math.min(...ys);
|
|
73
|
+
const down = Math.max(...ys);
|
|
74
|
+
const scale = Math.min((WIDTH - PAD * 2) / (right - left), (HEIGHT - PAD * 2) / (down - up));
|
|
75
|
+
return { origin: [WIDTH / 2 - ((left + right) / 2) * scale, HEIGHT / 2 - ((up + down) / 2) * scale], scale, azimuth: AZIMUTH };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const corners = ({ x, y, w, d }: Plan, z0: number, z1: number): Point3[] => {
|
|
79
|
+
const out: Point3[] = [];
|
|
80
|
+
for (const px of [x, x + w]) for (const py of [y, y + d]) for (const z of [z0, z1]) out.push([px, py, z]);
|
|
81
|
+
return out;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
export const P = fit([
|
|
85
|
+
...corners(BASE, -BASE_H - FOOT_H, 0),
|
|
86
|
+
...corners({ x: POST_L, y: RAIL_Y - RAIL_D / 2, w: POST_R + POST - POST_L, d: RAIL_D, r: 0 }, RAIL_Z, RAIL_Z + RAIL_H + 6),
|
|
87
|
+
]);
|
|
88
|
+
|
|
89
|
+
export const at = (point: Point3) => iso(point, P);
|
|
90
|
+
|
|
91
|
+
const ORIGIN = at([0, 0, 0]);
|
|
92
|
+
const minus = (a: Flat, b: Flat): Flat => [a[0] - b[0], a[1] - b[1]];
|
|
93
|
+
export const EX = minus(at([1, 0, 0]), ORIGIN);
|
|
94
|
+
export const EZ = minus(at([0, 0, 1]), ORIGIN);
|
|
95
|
+
|
|
96
|
+
const fine = (value: number) => Math.round(value * 100) / 100;
|
|
97
|
+
|
|
98
|
+
export const shift = (x: number, z = 0) => `translate(${fine(EX[0] * x + EZ[0] * z)} ${fine(EX[1] * x + EZ[1] * z)})`;
|
|
99
|
+
|