import { normalize } from "./normalize"; /** * 生成 HPGL 代码,支持指定起点和终点 * @param pts 路径点数组 * @param width 页面宽度(mm) * @param height 页面高度(mm) * @param px2mm 像素到毫米的转换系数 * @param startPoint 起点坐标(mm),默认为左上角 [0, height] * @param endPoint 终点坐标(mm),默认为左上角 [0, height] */ export function pts2plotter( pts: [number, number][][], width: number, height: number, px2mm = 0.1, startPoint?: [number, number], endPoint?: [number, number] ) { const start = startPoint ?? [0, height]; const end = endPoint ?? [0, height]; let str = init(width * px2mm, height * px2mm); // 按 X 轴然后 Y 轴排序路径 const sorted = pts.slice(); sorted.sort(function (a, b) { const [ax, ay] = topleft(a); const [bx, by] = topleft(b); if (ax !== bx) return ax - bx; return ay - by; }); // 从起点到第一个路径 if (sorted.length > 0) { const firstPath = sorted[0]; str += ` U${plu(start[0] * px2mm)},${plu((height - start[1]) * px2mm)}`; str += ` D${plu(firstPath[0][0] * px2mm)},${plu((height - firstPath[0][1]) * px2mm)}`; // 切割第一个路径 for (let i = 1; i < firstPath.length; i++) { const pt = firstPath[i]; str += ` D${plu(pt[0] * px2mm)},${plu((height - pt[1]) * px2mm)}`; } // 路径之间移动 for (let i = 1; i < sorted.length; i++) { const prevPath = sorted[i - 1]; const currPath = sorted[i]; // 抬刀移动到下一个路径起点 str += ` U${plu(currPath[0][0] * px2mm)},${plu((height - currPath[0][1]) * px2mm)}`; // 下刀切割 str += ` D${plu(currPath[0][0] * px2mm)},${plu((height - currPath[0][1]) * px2mm)}`; for (let j = 1; j < currPath.length; j++) { const pt = currPath[j]; str += ` D${plu(pt[0] * px2mm)},${plu((height - pt[1]) * px2mm)}`; } } } // 返回终点 str += ` U${plu(end[0] * px2mm)},${plu((height - end[1]) * px2mm)}`; str += endCommand(); return str; } // 兼容旧版本(不使用新参数) export function pts2plotterLegacy( pts: [number, number][][], width: number, height: number, px2mm = 0.1 ) { return pts2plotter(pts, width, height, px2mm); } function topleft(pts: [number, number][]) { let minx = NaN; let miny = NaN; for (const pt of pts) { if (isNaN(minx) || minx > pt[0]) minx = pt[0]; if (isNaN(miny) || miny > pt[1]) miny = pt[1]; } return [minx, miny] as [number, number]; } function init(w: number, h: number) { return ` IN TB26,${plu(w)},${plu(h)} CT1`; } function endCommand() { return ' @ @'; } function plu(n: number) { return Math.round(n / 0.025); }