iso.js
1.5 kB · javascript · 47 lines
1// PROJECTION23const RATIO = 0.8660254037844386;45export function project(x, y, z) {6 return [(x - y) * RATIO, (x + y) * 0.5 - z];7}89function fit(faces, frame) {10 let [lx, ly, hx, hy] = [Number.MAX_VALUE, Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE];11 for (const face of faces) {12 for (const p of face.quad) {13 if (p[0] < lx) lx = p[0];14 if (p[1] < ly) ly = p[1];15 if (p[0] > hx) hx = p[0];16 if (p[1] > hy) hy = p[1];17 }18 }19 const sx = Math.max(hx - lx, 1e-9);20 const sy = Math.max(hy - ly, 1e-9);21 const scale = Math.min(frame.w / sx, frame.h / sy);22 const ox = frame.x + (frame.w - sx * scale) / 2;23 const oy = frame.y + (frame.h - sy * scale) / 2;24 return (p) => [ox + (p[0] - lx) * scale, oy + (p[1] - ly) * scale];25}2627// DRAWING2829export function draw(pen, frame, quads, shade, edge) {30 const faces = [];31 for (const { normal, verts } of quads) {32 if (normal.x + normal.y + normal.z <= 0) continue;33 const tone = normal.z > 0 ? 0 : normal.y > 0 ? 1 : 2;34 let depth = 0;35 for (const v of verts) depth += Math.fround(Math.fround(v.x + v.y) + v.z);36 faces.push({ quad: verts.map((v) => project(v.x, v.y, v.z)), tone, depth: depth / 4 });37 }38 if (faces.length === 0) return;39 faces.sort((a, b) => a.depth - b.depth);40 const place = fit(faces, frame);41 const thick = Math.max(Math.min(frame.w, frame.h) / 400, 0.6);42 for (const { quad, tone } of faces) {43 const pts = quad.map(place);44 pen.polygon(pts, shade[tone]);45 if (edge) pen.polyline([...pts, pts[0]], thick, edge);46 }47}