mirror of
https://github.com/jhbruhn/respira.git
synced 2026-01-27 02:13:41 +00:00
- Removed all rotation/canvas debug console.log statements - Added calculateBoundsFromDecodedStitches() utility to eliminate code duplication - Used calculatePatternCenter() consistently across FileUpload and rotationUtils - Cleaner code with single source of truth for calculations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
83 lines
2 KiB
TypeScript
83 lines
2 KiB
TypeScript
/**
|
|
* Utility functions for PatternCanvas operations
|
|
*/
|
|
|
|
import type { DecodedPenData } from "../../formats/pen/types";
|
|
|
|
/**
|
|
* Calculate the geometric center of a pattern's bounds
|
|
*/
|
|
export function calculatePatternCenter(bounds: {
|
|
minX: number;
|
|
maxX: number;
|
|
minY: number;
|
|
maxY: number;
|
|
}): { x: number; y: number } {
|
|
return {
|
|
x: (bounds.minX + bounds.maxX) / 2,
|
|
y: (bounds.minY + bounds.maxY) / 2,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Convert PEN stitch format to PES stitch format
|
|
* PEN: {x, y, flags, isJump}
|
|
* PES: [x, y, cmd, colorIndex]
|
|
*/
|
|
export function convertPenStitchesToPesFormat(
|
|
penStitches: DecodedPenData,
|
|
): [number, number, number, number][] {
|
|
return penStitches.stitches.map((s, i) => {
|
|
const cmd = s.isJump ? 0x10 : 0; // MOVE flag if jump
|
|
const colorIndex =
|
|
penStitches.colorBlocks.find(
|
|
(b) => i >= b.startStitch && i <= b.endStitch,
|
|
)?.colorIndex ?? 0;
|
|
return [s.x, s.y, cmd, colorIndex];
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Calculate axis-aligned bounding box from decoded PEN stitches
|
|
*/
|
|
export function calculateBoundsFromDecodedStitches(decoded: DecodedPenData): {
|
|
minX: number;
|
|
maxX: number;
|
|
minY: number;
|
|
maxY: number;
|
|
} {
|
|
let minX = Infinity,
|
|
maxX = -Infinity;
|
|
let minY = Infinity,
|
|
maxY = -Infinity;
|
|
|
|
for (const stitch of decoded.stitches) {
|
|
if (stitch.x < minX) minX = stitch.x;
|
|
if (stitch.x > maxX) maxX = stitch.x;
|
|
if (stitch.y < minY) minY = stitch.y;
|
|
if (stitch.y > maxY) maxY = stitch.y;
|
|
}
|
|
|
|
return { minX, maxX, minY, maxY };
|
|
}
|
|
|
|
/**
|
|
* Calculate new stage position for zooming towards a specific point
|
|
* Used for both wheel zoom and button zoom operations
|
|
*/
|
|
export function calculateZoomToPoint(
|
|
oldScale: number,
|
|
newScale: number,
|
|
targetPoint: { x: number; y: number },
|
|
currentPos: { x: number; y: number },
|
|
): { x: number; y: number } {
|
|
const mousePointTo = {
|
|
x: (targetPoint.x - currentPos.x) / oldScale,
|
|
y: (targetPoint.y - currentPos.y) / oldScale,
|
|
};
|
|
|
|
return {
|
|
x: targetPoint.x - mousePointTo.x * newScale,
|
|
y: targetPoint.y - mousePointTo.y * newScale,
|
|
};
|
|
}
|