// Printer models, and simple line drawings of their shapes, drawn for // Printhive. The drawings suggest a model's form — open frame, enclosed, large // format — rather than depict any product exactly. (function () { const svg = (inner, width = 150) => `${inner}`; // One spool in a drawing, filled with what's loaded there: a colour for a // spool, dashed for an empty slot, plain when nothing is known. const HEX = /^#[0-9a-f]{6}$/i; const colourOf = (slot) => (slot && HEX.test(slot.colour || '') ? slot.colour : null); const spool = (cx, cy, r, slot, active) => { if (slot && slot.empty) return ``; const fill = colourOf(slot); const ring = active ? ' stroke-width="3.4"' : ''; return fill ? `` : ``; }; const toolhead = (x, y) => ` `; // Where each shape's spools sit, where its toolhead takes filament in, and // where an external spool is drawn when it's the one in use. const amsLiteAt = (x) => [[x - 9, 40, 7], [x + 9, 40, 7], [x - 9, 58, 7], [x + 9, 58, 7]]; const amsTopAt = (x, width) => [0, 1, 2, 3].map((i) => [x + width / 8 + (i * width) / 4, 23, 5]); const layouts = { // A1: a bed on a base, an upright gantry, an AMS lite alongside. open: { spools: amsLiteAt(126), head: [50, 49], external: [104, 12, 6], body: () => ` `, stand: (x = 126) => ``, }, // A1 mini: a single column holding the gantry out over the bed. openMini: { spools: amsLiteAt(122), head: [58, 47], external: [29, 18, 6], body: () => ` `, stand: () => ``, }, // A2L: the A1's form, stretched to a larger bed. openLarge: { spools: amsLiteAt(132), head: [52, 47], external: [112, 10, 6], body: () => ` `, stand: () => ``, }, // P1P: a bare cube frame. frame: { width: 140, spools: [], head: [56, 53], external: [124, 18, 6], body: () => ` `, }, // P1S, P2S, X1C, X1E, X2D: an enclosed box with an AMS on top. box: { width: 126, spools: amsTopAt(30, 66), head: [56, 52], external: [112, 60, 6], body: () => ` `, }, // H2S, H2D, H2C: a wide enclosed box with an AMS on top. large: { spools: amsTopAt(28, 94), head: [58, 52], secondHead: [78, 52], external: [142, 60, 6], body: () => ` `, }, // Anything else: a plain box with a nozzle. generic: { width: 140, spools: [], head: [63, 50], external: [122, 22, 6], body: () => ` `, }, }; // The filament's path from a spool into the toolhead: a tube curving over // the frame, outlined so a dark filament still shows on a dark page. const feed = (from, head, colour, moving) => { const [sx, sy] = from; const tx = head[0] + 7; const ty = head[1]; const lift = Math.max(2, Math.min(sy, ty) - 30); const d = `M${sx} ${sy} C${sx} ${lift}, ${tx} ${lift}, ${tx} ${ty}`; return ` ${moving ? `` : ''} `; }; // `slots`: the first AMS unit's four slots, as { empty, colour }. // `use`: which is feeding — { slot } for one of those, { external, colour } // for the external spool — and `moving` while it's printing. function draw(shapeName, slots = [], use = null, moving = false) { const L = layouts[shapeName] || layouts.generic; let parts = L.body(); let feedPart = ''; if (use && use.external && L.external) { const [x, y, r] = L.external; parts += spool(x, y, r, { colour: use.colour }, true); feedPart = feed([x, y], L.head, colourOf(use) || 'currentColor', moving); } else if (use && use.slot != null && L.spools[use.slot]) { const [x, y] = L.spools[use.slot]; const colour = colourOf(slots[use.slot]); if (colour) feedPart = feed([x, y], L.head, colour, moving); } if (L.stand) parts += L.stand(); parts += L.spools.map(([x, y, r], i) => spool(x, y, r, slots[i], use && use.slot === i)).join(''); // The tube is drawn behind the toolhead, so it disappears into it. parts += feedPart + toolhead(...L.head); if (L.secondHead) parts += toolhead(...L.secondHead); return svg(parts, L.width); } // ams is only a suggestion — a P1S might have an AMS, an AMS 2 Pro or an AMS HT. const models = [ { id: 'A1 mini', shape: 'openMini', ams: 'ams_lite' }, { id: 'A1', shape: 'open', ams: 'ams_lite' }, { id: 'A2L', shape: 'openLarge', ams: 'ams_lite' }, { id: 'P1P', shape: 'frame', ams: 'ams' }, { id: 'P1S', shape: 'box', ams: 'ams' }, { id: 'P2S', shape: 'box', ams: 'ams_2_pro' }, { id: 'X1C', shape: 'box', ams: 'ams' }, { id: 'X1E', shape: 'box', ams: 'ams' }, { id: 'X2D', shape: 'box', ams: 'ams_2_pro' }, { id: 'H2S', shape: 'large', ams: 'ams_2_pro' }, { id: 'H2D', shape: 'large', ams: 'ams_2_pro' }, { id: 'H2C', shape: 'large', ams: 'ams_2_pro' }, { id: 'Other', shape: 'generic', ams: 'none' }, ]; const amsTypes = [ { id: 'none', label: 'No AMS (external spool)' }, { id: 'ams_lite', label: 'AMS lite (full or empty only)' }, { id: 'ams', label: 'AMS' }, { id: 'ams_2_pro', label: 'AMS 2 Pro' }, { id: 'ams_ht', label: 'AMS HT' }, ]; const find = (id) => models.find((m) => m.id === id) || null; window.PRINTER_MODELS = { models, amsTypes, find, art: (id, slots = [], use = null, moving = false) => draw((find(id) || {}).shape, slots, use, moving), }; }());