fix: Remove debug logs and refactor with utility functions

- 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>
This commit is contained in:
Jan-Henrik Bruhn 2025-12-25 21:49:46 +01:00
parent 271229c200
commit e92c9f9616
4 changed files with 47 additions and 83 deletions

View file

@ -17,6 +17,10 @@ import {
} from "../utils/rotationUtils"; } from "../utils/rotationUtils";
import { encodeStitchesToPen } from "../formats/pen/encoder"; import { encodeStitchesToPen } from "../formats/pen/encoder";
import { decodePenData } from "../formats/pen/decoder"; import { decodePenData } from "../formats/pen/decoder";
import {
calculatePatternCenter,
calculateBoundsFromDecodedStitches,
} from "./PatternCanvas/patternCanvasHelpers";
import { PatternInfoSkeleton } from "./SkeletonLoader"; import { PatternInfoSkeleton } from "./SkeletonLoader";
import { PatternInfo } from "./PatternInfo"; import { PatternInfo } from "./PatternInfo";
import { import {
@ -154,11 +158,6 @@ export function FileUpload() {
// Apply rotation if needed // Apply rotation if needed
if (patternRotation && patternRotation !== 0) { if (patternRotation && patternRotation !== 0) {
console.log(
"[FileUpload] Applying rotation before upload:",
patternRotation,
);
// Transform stitches // Transform stitches
const rotatedStitches = transformStitchesRotation( const rotatedStitches = transformStitchesRotation(
pesData.stitches, pesData.stitches,
@ -174,57 +173,25 @@ export function FileUpload() {
const decoded = decodePenData(penDataToUpload); const decoded = decodePenData(penDataToUpload);
// Calculate bounds from the DECODED stitches (the actual data that will be rendered) // Calculate bounds from the DECODED stitches (the actual data that will be rendered)
let decodedMinX = Infinity, const rotatedBounds = calculateBoundsFromDecodedStitches(decoded);
decodedMaxX = -Infinity;
let decodedMinY = Infinity,
decodedMaxY = -Infinity;
for (const stitch of decoded.stitches) {
if (stitch.x < decodedMinX) decodedMinX = stitch.x;
if (stitch.x > decodedMaxX) decodedMaxX = stitch.x;
if (stitch.y < decodedMinY) decodedMinY = stitch.y;
if (stitch.y > decodedMaxY) decodedMaxY = stitch.y;
}
const rotatedBounds = {
minX: decodedMinX,
maxX: decodedMaxX,
minY: decodedMinY,
maxY: decodedMaxY,
};
// Calculate the center of the rotated pattern // Calculate the center of the rotated pattern
const originalCenterX = (pesData.bounds.minX + pesData.bounds.maxX) / 2; const originalCenter = calculatePatternCenter(pesData.bounds);
const originalCenterY = (pesData.bounds.minY + pesData.bounds.maxY) / 2; const rotatedCenter = calculatePatternCenter(rotatedBounds);
const rotatedCenterX = (rotatedBounds.minX + rotatedBounds.maxX) / 2; const centerShiftX = rotatedCenter.x - originalCenter.x;
const rotatedCenterY = (rotatedBounds.minY + rotatedBounds.maxY) / 2; const centerShiftY = rotatedCenter.y - originalCenter.y;
const centerShiftX = rotatedCenterX - originalCenterX;
const centerShiftY = rotatedCenterY - originalCenterY;
console.log("[FileUpload] Pattern centers:", {
originalCenter: { x: originalCenterX, y: originalCenterY },
rotatedCenter: { x: rotatedCenterX, y: rotatedCenterY },
centerShift: { x: centerShiftX, y: centerShiftY },
});
// CRITICAL: Adjust position to compensate for the center shift! // CRITICAL: Adjust position to compensate for the center shift!
// In Konva, visual position = (x - offsetX, y - offsetY). // In Konva, visual position = (x - offsetX, y - offsetY).
// Original visual pos: (x - originalCenterX, y - originalCenterY) // Original visual pos: (x - originalCenter.x, y - originalCenter.y)
// New visual pos: (newX - rotatedCenterX, newY - rotatedCenterY) // New visual pos: (newX - rotatedCenter.x, newY - rotatedCenter.y)
// For same visual position: newX = x + (rotatedCenterX - originalCenterX) // For same visual position: newX = x + (rotatedCenter.x - originalCenter.x)
// So we need to add (rotatedCenter - originalCenter) to the position. // So we need to add (rotatedCenter - originalCenter) to the position.
const adjustedOffset = { const adjustedOffset = {
x: patternOffset.x + centerShiftX, x: patternOffset.x + centerShiftX,
y: patternOffset.y + centerShiftY, y: patternOffset.y + centerShiftY,
}; };
console.log(
"[FileUpload] Adjusting position to compensate for center shift:",
{
originalPosition: patternOffset,
adjustedPosition: adjustedOffset,
shift: { x: centerShiftX, y: centerShiftY },
},
);
// Create rotated PesPatternData for upload // Create rotated PesPatternData for upload
pesDataForUpload = { pesDataForUpload = {
...pesData, ...pesData,
@ -236,7 +203,6 @@ export function FileUpload() {
// Save uploaded pattern to store for preview BEFORE starting upload // Save uploaded pattern to store for preview BEFORE starting upload
// This allows the preview to show immediately when isUploading becomes true // This allows the preview to show immediately when isUploading becomes true
console.log("[FileUpload] Saving uploaded pattern for preview");
setUploadedPattern(pesDataForUpload, adjustedOffset); setUploadedPattern(pesDataForUpload, adjustedOffset);
// Upload the pattern with offset // Upload the pattern with offset
@ -287,29 +253,13 @@ export function FileUpload() {
// The patternOffset represents the pattern's CENTER position (due to offsetX/offsetY in canvas) // The patternOffset represents the pattern's CENTER position (due to offsetX/offsetY in canvas)
// So we need to calculate bounds relative to the center // So we need to calculate bounds relative to the center
const centerX = (bounds.minX + bounds.maxX) / 2; const center = calculatePatternCenter(bounds);
const centerY = (bounds.minY + bounds.maxY) / 2;
// Calculate actual bounds in world coordinates // Calculate actual bounds in world coordinates
const patternMinX = patternOffset.x - centerX + bounds.minX; const patternMinX = patternOffset.x - center.x + bounds.minX;
const patternMaxX = patternOffset.x - centerX + bounds.maxX; const patternMaxX = patternOffset.x - center.x + bounds.maxX;
const patternMinY = patternOffset.y - centerY + bounds.minY; const patternMinY = patternOffset.y - center.y + bounds.minY;
const patternMaxY = patternOffset.y - centerY + bounds.maxY; const patternMaxY = patternOffset.y - center.y + bounds.maxY;
console.log("[Bounds Check] Pattern center:", { centerX, centerY });
console.log("[Bounds Check] Offset (center position):", patternOffset);
console.log("[Bounds Check] Pattern bounds with offset:", {
minX: patternMinX,
maxX: patternMaxX,
minY: patternMinY,
maxY: patternMaxY,
});
console.log("[Bounds Check] Hoop bounds:", {
minX: -maxWidth / 2,
maxX: maxWidth / 2,
minY: -maxHeight / 2,
maxY: maxHeight / 2,
});
// Hoop bounds (centered at origin) // Hoop bounds (centered at origin)
const hoopMinX = -maxWidth / 2; const hoopMinX = -maxWidth / 2;

View file

@ -55,16 +55,6 @@ export function PatternLayer({
const groupName = isInteractive ? "pattern-group" : "uploaded-pattern-group"; const groupName = isInteractive ? "pattern-group" : "uploaded-pattern-group";
console.log(
`[PatternLayer] Rendering ${isInteractive ? "original" : "uploaded"} pattern:`,
{
position: offset,
rotation: isInteractive ? rotation : "n/a",
center,
bounds: pesData.bounds,
},
);
return ( return (
<> <>
<Group <Group

View file

@ -37,6 +37,30 @@ export function convertPenStitchesToPesFormat(
}); });
} }
/**
* 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 * Calculate new stage position for zooming towards a specific point
* Used for both wheel zoom and button zoom operations * Used for both wheel zoom and button zoom operations

View file

@ -1,3 +1,5 @@
import { calculatePatternCenter } from "../components/PatternCanvas/patternCanvasHelpers";
/** /**
* Rotate a single point around a center * Rotate a single point around a center
*/ */
@ -31,11 +33,10 @@ export function transformStitchesRotation(
): number[][] { ): number[][] {
if (angleDegrees === 0 || angleDegrees === 360) return stitches; if (angleDegrees === 0 || angleDegrees === 360) return stitches;
const centerX = (bounds.minX + bounds.maxX) / 2; const center = calculatePatternCenter(bounds);
const centerY = (bounds.minY + bounds.maxY) / 2;
return stitches.map(([x, y, cmd, colorIndex]) => { return stitches.map(([x, y, cmd, colorIndex]) => {
const rotated = rotatePoint(x, y, centerX, centerY, angleDegrees); const rotated = rotatePoint(x, y, center.x, center.y, angleDegrees);
return [Math.round(rotated.x), Math.round(rotated.y), cmd, colorIndex]; return [Math.round(rotated.x), Math.round(rotated.y), cmd, colorIndex];
}); });
} }
@ -49,8 +50,7 @@ export function calculateRotatedBounds(
): { minX: number; maxX: number; minY: number; maxY: number } { ): { minX: number; maxX: number; minY: number; maxY: number } {
if (angleDegrees === 0 || angleDegrees === 360) return bounds; if (angleDegrees === 0 || angleDegrees === 360) return bounds;
const centerX = (bounds.minX + bounds.maxX) / 2; const center = calculatePatternCenter(bounds);
const centerY = (bounds.minY + bounds.maxY) / 2;
// Rotate all four corners // Rotate all four corners
const corners = [ const corners = [
@ -61,7 +61,7 @@ export function calculateRotatedBounds(
]; ];
const rotatedCorners = corners.map(([x, y]) => const rotatedCorners = corners.map(([x, y]) =>
rotatePoint(x, y, centerX, centerY, angleDegrees), rotatePoint(x, y, center.x, center.y, angleDegrees),
); );
return { return {