"use client"; import { useMemo, useState } from "react"; import ToolShell from "@/components/toolkit/ToolShell"; import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; function num(v: string) { const n = parseFloat(v); return Number.isFinite(n) ? n : 0; } function fmtTime(seconds: number) { if (!Number.isFinite(seconds) || seconds <= 0) return "0 s"; const s = Math.round(seconds); const m = Math.floor(s / 60); const rem = s % 60; if (m < 60) return `${m}m ${rem}s`; const h = Math.floor(m / 60); const mm = m % 60; return `${h}h ${mm}m`; } export default function Page() { const [mode, setMode] = useState<"raster" | "vector">("raster"); const [passes, setPasses] = useState("1"); // raster const [width, setWidth] = useState("100"); // mm const [height, setHeight] = useState("100");// mm const [dpi, setDpi] = useState("300"); const [speedRaster, setSpeedRaster] = useState("800"); // mm/s const [overheadR, setOverheadR] = useState("1.10"); // factor // vector const [length, setLength] = useState("500"); // mm const [speedVector, setSpeedVector] = useState("50"); // mm/s const [overheadV, setOverheadV] = useState("1.05"); // factor const computed = useMemo(() => { const p = Math.max(1, Math.round(num(passes))); if (mode === "raster") { const w = num(width), h = num(height), D = num(dpi), v = num(speedRaster), k = Math.max(0.5, num(overheadR)); if (w <= 0 || h <= 0 || D <= 0 || v <= 0) return { t: 0, gapMm: 0, gapUm: 0, rows: 0 }; const gapMm = 25.4 / D; const gapUm = gapMm * 1000; const rows = h / gapMm; const t = rows * (w / v) * p * k; return { t, gapMm, gapUm, rows }; } else { const L = num(length), v = num(speedVector), k = Math.max(0.5, num(overheadV)); if (L <= 0 || v <= 0) return { t: 0, gapMm: 0, gapUm: 0, rows: 0 }; const t = (L / v) * Math.max(1, Math.round(num(passes))) * k; return { t, gapMm: 0, gapUm: 0, rows: 0 }; } }, [mode, passes, width, height, dpi, speedRaster, overheadR, length, speedVector, overheadV]); return ( Mode {mode === "raster" ? ( Raster Inputs ) : ( Vector Inputs )} Estimate
Estimated time
{fmtTime(computed.t)}
{mode === "raster" && ( <>
Scan gap
{computed.gapMm.toFixed(4)} mm
{computed.gapUm.toFixed(1)} µm
Line count
{computed.rows.toFixed(0)}
)}
{/* Footnote */}

Overhead factor* accounts for real-world slowdowns: acceleration/decelleration, jump moves, polygon delays, laser on/off timing, overscan, bidirectional settle time, and controller latency.{" "} Typical values: Vector cuts/marks{" "} 1.05–1.15 (simple paths, long runs closer to 1.05; tiny segments or lots of jumps closer to 1.15). Raster engraving{" "} 1.10–1.40 (lower DPI and long sweeps near 1.10; very high DPI or short scan width near 1.30–1.40). Galvo systems often have lower overhead at small sizes; gantry systems tend to have higher overhead at high DPI/short strokes.

); }