mirror of
https://github.com/jhbruhn/respira.git
synced 2026-01-27 10:23:41 +00:00
Merge pull request #13 from jhbruhn/fix/combine-color-end-cut-flags
fix: Combine COLOR_END and CUT flags on same stitch for color changes
This commit is contained in:
commit
254b09271e
2 changed files with 39 additions and 60 deletions
|
|
@ -298,21 +298,15 @@ describe('encodeStitchesToPen', () => {
|
|||
idx++;
|
||||
}
|
||||
|
||||
// 4. Cut command
|
||||
const cutStitch = decoded[idx];
|
||||
expect(cutStitch.x).toBe(10);
|
||||
expect(cutStitch.y).toBe(0);
|
||||
expect(cutStitch.isCut).toBe(true);
|
||||
// 4. COLOR_END + CUT command (combined on same stitch)
|
||||
const colorEndCutStitch = decoded[idx];
|
||||
expect(colorEndCutStitch.x).toBe(10);
|
||||
expect(colorEndCutStitch.y).toBe(0);
|
||||
expect(colorEndCutStitch.isCut).toBe(true);
|
||||
expect(colorEndCutStitch.isColorEnd).toBe(true);
|
||||
idx++;
|
||||
|
||||
// 5. COLOR_END marker (no jump needed since same position)
|
||||
const colorEndStitch = decoded[idx];
|
||||
expect(colorEndStitch.x).toBe(10);
|
||||
expect(colorEndStitch.y).toBe(0);
|
||||
expect(colorEndStitch.isColorEnd).toBe(true);
|
||||
idx++;
|
||||
|
||||
// 6. 8 starting lock stitches for new color
|
||||
// 5. 8 starting lock stitches for new color
|
||||
for (let i = 0; i < 8; i++) {
|
||||
const lockStitch = decoded[idx];
|
||||
expect(lockStitch.x).to.be.closeTo(10, LOCK_STITCH_JUMP_SIZE);
|
||||
|
|
@ -320,7 +314,7 @@ describe('encodeStitchesToPen', () => {
|
|||
idx++;
|
||||
}
|
||||
|
||||
// 7. First stitch of new color
|
||||
// 6. First stitch of new color
|
||||
expect(decoded[idx].x).toBe(10);
|
||||
expect(decoded[idx].y).toBe(0);
|
||||
idx++;
|
||||
|
|
@ -353,9 +347,11 @@ describe('encodeStitchesToPen', () => {
|
|||
idx++;
|
||||
}
|
||||
|
||||
// 2. Cut command at (10, 0)
|
||||
expect(decoded[idx].isCut).toBe(true);
|
||||
// 2. COLOR_END + CUT command at (10, 0) - combined on same stitch
|
||||
expect(decoded[idx].x).toBe(10);
|
||||
expect(decoded[idx].y).toBe(0);
|
||||
expect(decoded[idx].isCut).toBe(true);
|
||||
expect(decoded[idx].isColorEnd).toBe(true);
|
||||
idx++;
|
||||
|
||||
// 3. Jump to new position (30, 10)
|
||||
|
|
@ -364,20 +360,14 @@ describe('encodeStitchesToPen', () => {
|
|||
expect(decoded[idx].isFeed).toBe(true);
|
||||
idx++;
|
||||
|
||||
// 4. COLOR_END marker at (30, 10)
|
||||
expect(decoded[idx].x).toBe(30);
|
||||
expect(decoded[idx].y).toBe(10);
|
||||
expect(decoded[idx].isColorEnd).toBe(true);
|
||||
idx++;
|
||||
|
||||
// 5. 8 starting lock stitches at (30, 10)
|
||||
// 4. 8 starting lock stitches at (30, 10)
|
||||
for (let i = 0; i < 8; i++) {
|
||||
expect(decoded[idx].x).to.be.closeTo(30, LOCK_STITCH_JUMP_SIZE);
|
||||
expect(decoded[idx].y).to.be.closeTo(10, LOCK_STITCH_JUMP_SIZE);
|
||||
idx++;
|
||||
}
|
||||
|
||||
// 6. Continue with new color stitches
|
||||
// 5. Continue with new color stitches
|
||||
expect(decoded[idx].x).toBe(30);
|
||||
expect(decoded[idx].y).toBe(10);
|
||||
});
|
||||
|
|
@ -421,10 +411,11 @@ describe('encodeStitchesToPen', () => {
|
|||
idx++;
|
||||
}
|
||||
|
||||
// 4. Cut command at (10, 0)
|
||||
// 4. COLOR_END + CUT command at (10, 0) - combined on same stitch
|
||||
expect(decoded[idx].x).toBe(10);
|
||||
expect(decoded[idx].y).toBe(0);
|
||||
expect(decoded[idx].isCut).toBe(true);
|
||||
expect(decoded[idx].isColorEnd).toBe(true);
|
||||
idx++;
|
||||
|
||||
// 5. Jump to new location (50, 20) - extracted from the MOVE stitch
|
||||
|
|
@ -433,26 +424,20 @@ describe('encodeStitchesToPen', () => {
|
|||
expect(decoded[idx].isFeed).toBe(true);
|
||||
idx++;
|
||||
|
||||
// 6. COLOR_END marker at (50, 20)
|
||||
expect(decoded[idx].x).toBe(50);
|
||||
expect(decoded[idx].y).toBe(20);
|
||||
expect(decoded[idx].isColorEnd).toBe(true);
|
||||
idx++;
|
||||
|
||||
// 7. 8 starting lock stitches at (50, 20)
|
||||
// 6. 8 starting lock stitches at (50, 20)
|
||||
for (let i = 0; i < 8; i++) {
|
||||
expect(decoded[idx].x).to.be.closeTo(50, LOCK_STITCH_JUMP_SIZE);
|
||||
expect(decoded[idx].y).to.be.closeTo(20, LOCK_STITCH_JUMP_SIZE);
|
||||
idx++;
|
||||
}
|
||||
|
||||
// 8. First actual stitch of new color at (50, 20)
|
||||
// 7. First actual stitch of new color at (50, 20)
|
||||
expect(decoded[idx].x).toBe(50);
|
||||
expect(decoded[idx].y).toBe(20);
|
||||
expect(decoded[idx].isFeed).toBe(false);
|
||||
idx++;
|
||||
|
||||
// 9. Last stitch with DATA_END
|
||||
// 8. Last stitch with DATA_END
|
||||
expect(decoded[idx].x).toBe(60);
|
||||
expect(decoded[idx].y).toBe(20);
|
||||
expect(decoded[idx].isDataEnd).toBe(true);
|
||||
|
|
@ -666,7 +651,7 @@ describe('encodeStitchesToPen', () => {
|
|||
|
||||
const result = encodeStitchesToPen(stitches);
|
||||
const decoded = decodeAllPenStitches(result.penBytes);
|
||||
console.log(decoded);
|
||||
|
||||
// Expected sequence:
|
||||
// 0. Feed move to proper location (should always happen here)
|
||||
// 1. 8 starting lock stitches at (10, 20)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ const PEN_DATA_END = 0x05; // Last stitch of entire pattern
|
|||
const FEED_LENGTH = 50; // Long jump threshold requiring lock stitches and cut
|
||||
const TARGET_LENGTH = 8.0; // Target accumulated length for lock stitch direction
|
||||
const MAX_POINTS = 5; // Maximum points to accumulate for lock stitch direction
|
||||
export const LOCK_STITCH_JUMP_SIZE = 4.0;
|
||||
export const LOCK_STITCH_JUMP_SIZE = 2.0;
|
||||
const LOCK_STITCH_SCALE = LOCK_STITCH_JUMP_SIZE / 8.0; // Scale the magnitude-8 vector down to 4
|
||||
|
||||
export interface StitchData {
|
||||
|
|
@ -286,7 +286,7 @@ export function encodeStitchesToPen(stitches: number[][]): PenEncodingResult {
|
|||
penStitches.push(...generateLockStitches(absX, absY, startDir.dirX, startDir.dirY));
|
||||
}
|
||||
|
||||
// Handle color change: finishing lock, cut, jump, COLOR_END, starting lock
|
||||
// Handle color change: finishing lock, COLOR_END+CUT, jump, starting lock
|
||||
if (isColorChange) {
|
||||
const nextStitchCmd = nextStitch[2];
|
||||
const nextStitchX = Math.round(nextStitch[0]);
|
||||
|
|
@ -299,17 +299,26 @@ export function encodeStitchesToPen(stitches: number[][]): PenEncodingResult {
|
|||
const finishDir = calculateLockDirection(stitches, i, true);
|
||||
penStitches.push(...generateLockStitches(absX, absY, finishDir.dirX, finishDir.dirY));
|
||||
|
||||
// Step 2: Add cut command at current position
|
||||
const cutXEncoded = (absX << 3) & 0xffff;
|
||||
const cutYEncoded = ((absY << 3) & 0xffff) | PEN_CUT_DATA;
|
||||
// Step 2: Add COLOR_END + CUT command at CURRENT position (same stitch!)
|
||||
// This is where the machine pauses and waits for the user to change thread color
|
||||
// IMPORTANT: COLOR_END and CUT must be on the SAME stitch, not separate stitches
|
||||
let colorEndCutXEncoded = (absX << 3) & 0xffff;
|
||||
let colorEndCutYEncoded = (absY << 3) & 0xffff;
|
||||
|
||||
// Add COLOR_END flag to X coordinate and CUT flag to Y coordinate
|
||||
colorEndCutXEncoded = (colorEndCutXEncoded & 0xfff8) | PEN_COLOR_END;
|
||||
colorEndCutYEncoded |= PEN_CUT_DATA;
|
||||
|
||||
penStitches.push(
|
||||
cutXEncoded & 0xff,
|
||||
(cutXEncoded >> 8) & 0xff,
|
||||
cutYEncoded & 0xff,
|
||||
(cutYEncoded >> 8) & 0xff
|
||||
colorEndCutXEncoded & 0xff,
|
||||
(colorEndCutXEncoded >> 8) & 0xff,
|
||||
colorEndCutYEncoded & 0xff,
|
||||
(colorEndCutYEncoded >> 8) & 0xff
|
||||
);
|
||||
|
||||
// Machine pauses here for color change
|
||||
// After user changes color, the following stitches execute with the new color
|
||||
|
||||
// Step 3: If next stitch is a JUMP, encode it and skip it in the loop
|
||||
// Otherwise, add a jump ourselves if positions differ
|
||||
const jumpToX = nextStitchX;
|
||||
|
|
@ -334,22 +343,7 @@ export function encodeStitchesToPen(stitches: number[][]): PenEncodingResult {
|
|||
);
|
||||
}
|
||||
|
||||
// Step 4: Add COLOR_END marker at NEW position
|
||||
// This is where the machine pauses and waits for the user to change thread color
|
||||
let colorEndXEncoded = (jumpToX << 3) & 0xffff;
|
||||
const colorEndYEncoded = (jumpToY << 3) & 0xffff;
|
||||
|
||||
// Add COLOR_END flag to X coordinate
|
||||
colorEndXEncoded = (colorEndXEncoded & 0xfff8) | PEN_COLOR_END;
|
||||
|
||||
penStitches.push(
|
||||
colorEndXEncoded & 0xff,
|
||||
(colorEndXEncoded >> 8) & 0xff,
|
||||
colorEndYEncoded & 0xff,
|
||||
(colorEndYEncoded >> 8) & 0xff
|
||||
);
|
||||
|
||||
// Step 5: Add starting lock stitches at the new position
|
||||
// Step 4: Add starting lock stitches at the new position
|
||||
// Loop A: Jump/Entry Vector - Look FORWARD at upcoming stitches in new color
|
||||
// This hides the knot under the stitches we're about to make
|
||||
const nextStitchIdx = nextIsJump ? i + 2 : i + 1;
|
||||
|
|
|
|||
Loading…
Reference in a new issue