96 lines
2.2 KiB
TypeScript
96 lines
2.2 KiB
TypeScript
|
|
import { contourToSvgPath } from './contour';
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 卡片切割路径
|
|||
|
|
*/
|
|||
|
|
export interface CardPath {
|
|||
|
|
pageIndex: number;
|
|||
|
|
cardIndex: number;
|
|||
|
|
points: [number, number][];
|
|||
|
|
centerX: number;
|
|||
|
|
centerY: number;
|
|||
|
|
pathD: string;
|
|||
|
|
startPoint: [number, number];
|
|||
|
|
endPoint: [number, number];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 生成空走路径(抬刀移动路径)
|
|||
|
|
* @param cardPaths 卡片切割路径
|
|||
|
|
* @param a4Height A4 纸高度(用于坐标转换)
|
|||
|
|
*/
|
|||
|
|
export function generateTravelPaths(
|
|||
|
|
cardPaths: CardPath[],
|
|||
|
|
a4Height: number
|
|||
|
|
): [number, number][][] {
|
|||
|
|
const travelPaths: [number, number][][] = [];
|
|||
|
|
|
|||
|
|
// 起点:左上角 (0, a4Height) - 注意 SVG 坐标 Y 向下,plotter 坐标 Y 向上
|
|||
|
|
const startPoint: [number, number] = [0, a4Height];
|
|||
|
|
|
|||
|
|
if (cardPaths.length === 0) {
|
|||
|
|
return travelPaths;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 从起点到第一张卡的起点
|
|||
|
|
travelPaths.push([startPoint, cardPaths[0].startPoint]);
|
|||
|
|
|
|||
|
|
// 卡片之间的移动
|
|||
|
|
for (let i = 0; i < cardPaths.length - 1; i++) {
|
|||
|
|
const currentEnd = cardPaths[i].endPoint;
|
|||
|
|
const nextStart = cardPaths[i + 1].startPoint;
|
|||
|
|
travelPaths.push([currentEnd, nextStart]);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 从最后一张卡返回起点
|
|||
|
|
travelPaths.push([cardPaths[cardPaths.length - 1].endPoint, startPoint]);
|
|||
|
|
|
|||
|
|
return travelPaths;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 将旅行路径转换为 SVG path 命令
|
|||
|
|
*/
|
|||
|
|
export function travelPathsToSvg(travelPaths: [number, number][][]): string {
|
|||
|
|
return travelPaths.map(path => contourToSvgPath(path, false)).join(' ');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* 计算所有卡片轮廓的总边界框
|
|||
|
|
*/
|
|||
|
|
export function calculateTotalBounds(cardPaths: CardPath[]): {
|
|||
|
|
minX: number;
|
|||
|
|
minY: number;
|
|||
|
|
maxX: number;
|
|||
|
|
maxY: number;
|
|||
|
|
width: number;
|
|||
|
|
height: number;
|
|||
|
|
} {
|
|||
|
|
if (cardPaths.length === 0) {
|
|||
|
|
return { minX: 0, minY: 0, maxX: 0, maxY: 0, width: 0, height: 0 };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let minX = Infinity;
|
|||
|
|
let minY = Infinity;
|
|||
|
|
let maxX = -Infinity;
|
|||
|
|
let maxY = -Infinity;
|
|||
|
|
|
|||
|
|
for (const cardPath of cardPaths) {
|
|||
|
|
for (const [x, y] of cardPath.points) {
|
|||
|
|
minX = Math.min(minX, x);
|
|||
|
|
minY = Math.min(minY, y);
|
|||
|
|
maxX = Math.max(maxX, x);
|
|||
|
|
maxY = Math.max(maxY, y);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
minX,
|
|||
|
|
minY,
|
|||
|
|
maxX,
|
|||
|
|
maxY,
|
|||
|
|
width: maxX - minX,
|
|||
|
|
height: maxY - minY
|
|||
|
|
};
|
|||
|
|
}
|