{"id":3354,"date":"2026-01-16T00:22:52","date_gmt":"2026-01-16T00:22:52","guid":{"rendered":"https:\/\/www2.yeltrowshopllc.com\/?page_id=3354"},"modified":"2026-01-16T00:47:08","modified_gmt":"2026-01-16T00:47:08","slug":"gridfinity-case-calculator","status":"publish","type":"page","link":"https:\/\/www2.yeltrowshopllc.com\/index.php\/gridfinity-case-calculator\/","title":{"rendered":"Gridfinity Case Calculator"},"content":{"rendered":"\n<div style=\"max-width: 520px; padding: 1em; border: 1px solid #ccc;\">\n  <h3>Volume Calculator with SVG Plot<\/h3>\n\n  <label>\n    Height:\n    <input type=\"number\" id=\"height\" step=\"any\" oninput=\"updateAll()\">\n  <\/label><br><br>\n\n  <label>\n    Width:\n    <input type=\"number\" id=\"width\" step=\"any\" oninput=\"updateAll()\">\n  <\/label><br><br>\n\n  <label>\n    Depth:\n    <input type=\"number\" id=\"depth\" step=\"any\" oninput=\"updateAll()\">\n  <\/label><br><br>\n\n  <strong>Volume:<\/strong>\n  <span id=\"volume\">0.00<\/span>\n\n  <br><br>\n\n  <!-- SVG output replaces the canvas -->\n  <svg id=\"cubeSvg\" width=\"420\" height=\"300\" viewBox=\"0 0 420 300\"\n       style=\"border:1px solid #ddd; display:block;\"><\/svg>\n\n  <br>\n  <button type=\"button\" onclick=\"downloadSVG()\">Download SVG<\/button>\n<\/div>\n\n<script>\nfunction updateAll() {\n  calculateVolume();\n  drawCubeSVG();\n}\n\nfunction calculateVolume() {\n  const hEl = document.getElementById(\"height\");\n  const wEl = document.getElementById(\"width\");\n  const dEl = document.getElementById(\"depth\");\n\n  const h = parseFloat(hEl.value) || 0;\n  const w = parseFloat(wEl.value) || 0;\n  const d = parseFloat(dEl.value) || 0;\n\n  document.getElementById(\"volume\").textContent = (h * w * d).toFixed(2);\n}\n\nfunction svgEl(tag, attrs = {}) {\n  const el = document.createElementNS(\"http:\/\/www.w3.org\/2000\/svg\", tag);\n  for (const [k, v] of Object.entries(attrs)) el.setAttribute(k, String(v));\n  return el;\n}\n\nfunction drawCubeSVG() {\n  const hEl = document.getElementById(\"height\");\n  const wEl = document.getElementById(\"width\");\n  const dEl = document.getElementById(\"depth\");\n\n  const h = parseFloat(hEl.value) || 1;\n  const w = parseFloat(wEl.value) || 1;\n  const d = parseFloat(dEl.value) || 1;\n\n  const svg = document.getElementById(\"cubeSvg\");\n\n  \/\/ Clear SVG\n  while (svg.firstChild) svg.removeChild(svg.firstChild);\n\n  \/\/ Fit cube in SVG\n  const maxDim = Math.max(h, w, d);\n  const scale = 120 \/ maxDim;\n\n  const H = h * scale;\n  const W = w * scale;\n  const D = d * scale;\n\n  \/\/ Perspective correction (cabinet projection)\n  const depthScale = 0.5;\n  const dx = D * depthScale;\n  const dy = D * depthScale;\n\n  \/\/ Anchor point\n  const x = 120;\n  const y = 230;\n\n  function svgEl(tag, attrs = {}) {\n    const el = document.createElementNS(\"http:\/\/www.w3.org\/2000\/svg\", tag);\n    for (const [k, v] of Object.entries(attrs)) el.setAttribute(k, String(v));\n    return el;\n  }\n\n  \/\/ Helper: midpoint between 2 points\n  function mid(p1, p2) {\n    return { x: (p1.x + p2.x) \/ 2, y: (p1.y + p2.y) \/ 2 };\n  }\n\n  \/\/ Helper: add dashed line\n  function dashedLine(p1, p2) {\n    return svgEl(\"line\", {\n      x1: p1.x, y1: p1.y,\n      x2: p2.x, y2: p2.y,\n      stroke: \"#000\",\n      \"stroke-width\": \"1\",\n      \"stroke-dasharray\": \"4 4\",\n      \"stroke-linecap\": \"round\"\n    });\n  }\n\n  \/\/ Define key points\n  const A = { x: x,         y: y - H };      \/\/ front top-left\n  const B = { x: x + W,     y: y - H };      \/\/ front top-right\n  const C = { x: x + W,     y: y };          \/\/ front bottom-right\n  const Df= { x: x,         y: y };          \/\/ front bottom-left\n\n  const At = { x: x + dx,       y: y - H - dy }; \/\/ back top-left (top face)\n  const Bt = { x: x + W + dx,   y: y - H - dy }; \/\/ back top-right\n  const Ct = { x: x + W + dx,   y: y - dy };     \/\/ back bottom-right\n  const Dt = { x: x + dx,       y: y - dy };     \/\/ back bottom-left\n\n  \/\/ Faces (optional shading)\n  const top = svgEl(\"polygon\", {\n    points: [A, At, Bt, B].map(p => `${p.x},${p.y}`).join(\" \"),\n    fill: \"#f3f3f3\",\n    stroke: \"#000\",\n    \"stroke-width\": \"1\"\n  });\n\n  const side = svgEl(\"polygon\", {\n    points: [B, Bt, Ct, C].map(p => `${p.x},${p.y}`).join(\" \"),\n    fill: \"#e6e6e6\",\n    stroke: \"#000\",\n    \"stroke-width\": \"1\"\n  });\n\n  const front = svgEl(\"rect\", {\n    x: x,\n    y: y - H,\n    width: W,\n    height: H,\n    fill: \"#ffffff\",\n    stroke: \"#000\",\n    \"stroke-width\": \"1\"\n  });\n\n  \/\/ Add faces (order matters for overlap)\n  svg.appendChild(top);\n  svg.appendChild(side);\n  svg.appendChild(front);\n\n  \/\/ ---- Add dashed quadrant lines on each face ----\n\n  \/\/ FRONT face quadrant lines\n  const frontMidTop    = { x: x + W \/ 2, y: y - H };\n  const frontMidBottom = { x: x + W \/ 2, y: y };\n  const frontMidLeft   = { x: x,         y: y - H \/ 2 };\n  const frontMidRight  = { x: x + W,     y: y - H \/ 2 };\n\n  svg.appendChild(dashedLine(frontMidTop, frontMidBottom)); \/\/ vertical\n  svg.appendChild(dashedLine(frontMidLeft, frontMidRight)); \/\/ horizontal\n\n  \/\/ TOP face quadrant lines (connect midpoints of opposite edges)\n  const topMidFront = mid(A, B);\n  const topMidBack  = mid(At, Bt);\n  const topMidLeft  = mid(A, At);\n  const topMidRight = mid(B, Bt);\n\n  svg.appendChild(dashedLine(topMidFront, topMidBack));\n  svg.appendChild(dashedLine(topMidLeft, topMidRight));\n\n  \/\/ SIDE face quadrant lines\n  const sideMidFront = mid(B, C);\n  const sideMidBack  = mid(Bt, Ct);\n  const sideMidTop   = mid(B, Bt);\n  const sideMidBot   = mid(C, Ct);\n\n  svg.appendChild(dashedLine(sideMidFront, sideMidBack));\n  svg.appendChild(dashedLine(sideMidTop, sideMidBot));\n\n  \/\/ ---- Labels ----\n  const labelStyle = { \"font-size\": \"12\", \"font-family\": \"Arial, sans-serif\", fill: \"#000\" };\n\n  svg.appendChild(svgEl(\"text\", { x: x + W \/ 2 - 30, y: y + 20, ...labelStyle }))\n    .textContent = `Width: ${w}`;\n\n  svg.appendChild(svgEl(\"text\", { x: x - 90, y: y - H \/ 2, ...labelStyle }))\n    .textContent = `Height: ${h}`;\n\n  svg.appendChild(svgEl(\"text\", { x: x + W + dx + 10, y: y - dy \/ 2, ...labelStyle }))\n    .textContent = `Depth: ${d}`;\n}\n\n\nfunction downloadSVG() {\n  const svg = document.getElementById(\"cubeSvg\");\n  const serializer = new XMLSerializer();\n  let source = serializer.serializeToString(svg);\n\n  \/\/ Ensure XML header (nice for standalone files)\n  if (!source.match(\/^<\\?xml\/)) {\n    source = '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n' + source;\n  }\n\n  const blob = new Blob([source], { type: \"image\/svg+xml;charset=utf-8\" });\n  const url = URL.createObjectURL(blob);\n\n  const a = document.createElement(\"a\");\n  a.href = url;\n  a.download = \"volume-cube.svg\";\n  document.body.appendChild(a);\n  a.click();\n  document.body.removeChild(a);\n\n  URL.revokeObjectURL(url);\n}\n\ndocument.addEventListener(\"DOMContentLoaded\", updateAll);\n<\/script>\n\n","protected":false},"excerpt":{"rendered":"<p>Volume Calculator with SVG Plot Height: Width: Depth: Volume: 0.00 Download SVG<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":[],"_links":{"self":[{"href":"https:\/\/www2.yeltrowshopllc.com\/index.php\/wp-json\/wp\/v2\/pages\/3354"}],"collection":[{"href":"https:\/\/www2.yeltrowshopllc.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www2.yeltrowshopllc.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www2.yeltrowshopllc.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www2.yeltrowshopllc.com\/index.php\/wp-json\/wp\/v2\/comments?post=3354"}],"version-history":[{"count":6,"href":"https:\/\/www2.yeltrowshopllc.com\/index.php\/wp-json\/wp\/v2\/pages\/3354\/revisions"}],"predecessor-version":[{"id":3363,"href":"https:\/\/www2.yeltrowshopllc.com\/index.php\/wp-json\/wp\/v2\/pages\/3354\/revisions\/3363"}],"wp:attachment":[{"href":"https:\/\/www2.yeltrowshopllc.com\/index.php\/wp-json\/wp\/v2\/media?parent=3354"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}