mirror of
https://github.com/jhbruhn/respira.git
synced 2026-04-28 01:55:45 +00:00
Compare commits
6 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3e6a6688e3 | ||
| 0a80d77455 | |||
|
|
dc4fb0221c | ||
| 7431327c1c | |||
|
|
270a464742 | ||
|
|
8095f8543c |
4 changed files with 43 additions and 49 deletions
27
package-lock.json
generated
27
package-lock.json
generated
|
|
@ -15070,16 +15070,6 @@
|
|||
"murmur-32": "^0.1.0 || ^0.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/randombytes": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
|
||||
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
|
|
@ -16079,16 +16069,6 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/serialize-javascript": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
|
||||
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"randombytes": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/serve-static": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
|
||||
|
|
@ -17618,16 +17598,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/terser-webpack-plugin": {
|
||||
"version": "5.3.16",
|
||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz",
|
||||
"integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==",
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.4.0.tgz",
|
||||
"integrity": "sha512-Bn5vxm48flOIfkdl5CaD2+1CiUVbonWQ3KQPyP7/EuIl9Gbzq/gQFOzaMFUEgVjB1396tcK0SG8XcNJ/2kDH8g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@jridgewell/trace-mapping": "^0.3.25",
|
||||
"jest-worker": "^27.4.5",
|
||||
"schema-utils": "^4.3.0",
|
||||
"serialize-javascript": "^6.0.2",
|
||||
"terser": "^5.31.1"
|
||||
},
|
||||
"engines": {
|
||||
|
|
|
|||
|
|
@ -71,12 +71,12 @@ export function ProgressMonitor() {
|
|||
const isMaskTraceComplete =
|
||||
machineStatus === MachineStatus.MASK_TRACE_COMPLETE;
|
||||
|
||||
// Use PEN stitch count as fallback when machine reports 0 total stitches
|
||||
const totalStitches = patternInfo
|
||||
? patternInfo.totalStitches === 0 && displayPattern?.penStitches
|
||||
// Use our own PEN stitch count as the source of truth for total stitches.
|
||||
// The machine's patternInfo.totalStitches uses a different counting method than
|
||||
// currentStitch (e.g. excludes lock stitches), so it can't be used as the max.
|
||||
const totalStitches = displayPattern?.penStitches
|
||||
? displayPattern.penStitches.stitches.length
|
||||
: patternInfo.totalStitches
|
||||
: 0;
|
||||
: (patternInfo?.totalStitches ?? 0);
|
||||
|
||||
// Use adjustedStitchIndex (from step control) when available, otherwise machine-reported
|
||||
const currentStitch =
|
||||
|
|
@ -156,8 +156,10 @@ export function ProgressMonitor() {
|
|||
totalStitches={totalStitches}
|
||||
lastRolledBackError={lastRolledBackError}
|
||||
colorBlocks={colorBlocks}
|
||||
onAdjustPosition={adjustStitchPosition}
|
||||
onSetPosition={setStitchPosition}
|
||||
onAdjustPosition={(offset) =>
|
||||
adjustStitchPosition(offset, totalStitches)
|
||||
}
|
||||
onSetPosition={(index) => setStitchPosition(index, totalStitches)}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
|
|
|||
|
|
@ -65,8 +65,8 @@ interface MachineState {
|
|||
startSewing: () => Promise<void>;
|
||||
resumeSewing: () => Promise<void>;
|
||||
deletePattern: () => Promise<void>;
|
||||
setStitchPosition: (index: number) => Promise<void>;
|
||||
adjustStitchPosition: (offset: number) => Promise<void>;
|
||||
setStitchPosition: (index: number, maxStitches?: number) => Promise<void>;
|
||||
adjustStitchPosition: (offset: number, maxStitches?: number) => Promise<void>;
|
||||
|
||||
// Initialization
|
||||
initialize: () => void;
|
||||
|
|
@ -338,11 +338,11 @@ export const useMachineStore = create<MachineState>((set, get) => ({
|
|||
},
|
||||
|
||||
// Set stitch position to an absolute index
|
||||
setStitchPosition: async (index: number) => {
|
||||
setStitchPosition: async (index: number, maxStitches?: number) => {
|
||||
const { isConnected, service, patternInfo } = get();
|
||||
if (!isConnected) return;
|
||||
|
||||
const totalStitches = patternInfo?.totalStitches || 0;
|
||||
const totalStitches = maxStitches ?? patternInfo?.totalStitches ?? 0;
|
||||
const clamped = Math.max(0, Math.min(index, totalStitches));
|
||||
|
||||
try {
|
||||
|
|
@ -359,11 +359,11 @@ export const useMachineStore = create<MachineState>((set, get) => ({
|
|||
},
|
||||
|
||||
// Adjust stitch position by a relative offset
|
||||
adjustStitchPosition: async (offset: number) => {
|
||||
adjustStitchPosition: async (offset: number, maxStitches?: number) => {
|
||||
const { sewingProgress, adjustedStitchIndex } = get();
|
||||
const currentIndex =
|
||||
adjustedStitchIndex ?? sewingProgress?.currentStitch ?? 0;
|
||||
await get().setStitchPosition(currentIndex + offset);
|
||||
await get().setStitchPosition(currentIndex + offset, maxStitches);
|
||||
},
|
||||
|
||||
// Handle automatic stitch rollback for thread errors
|
||||
|
|
|
|||
|
|
@ -57,6 +57,12 @@ export interface ThreadColorInfo {
|
|||
// Type-safe Brother color data
|
||||
const brotherColors = brotherColorData as BrotherColor[];
|
||||
|
||||
// Maximum RGB Euclidean distance to accept a catalog number match.
|
||||
// PES catalog numbers from pystitch use a different numbering scheme than our
|
||||
// Brother color database, so a catalog hit can resolve to the wrong color.
|
||||
// A match is only trusted if the database entry's RGB is within this distance.
|
||||
const CATALOG_COLOR_MATCH_THRESHOLD = 50;
|
||||
|
||||
/**
|
||||
* Convert RGB values to hex color string
|
||||
*/
|
||||
|
|
@ -266,25 +272,32 @@ export function enhanceThreadWithBrotherColor(
|
|||
): ThreadColorInfo {
|
||||
const { matchByRGB = true } = options;
|
||||
|
||||
// First, try to match by catalog number
|
||||
if (thread.catalogNumber) {
|
||||
const brotherInfo = mapThreadCode(thread.catalogNumber);
|
||||
if (brotherInfo) {
|
||||
// Found a Brother color match by catalog number - use Brother data
|
||||
return brotherInfo;
|
||||
}
|
||||
}
|
||||
|
||||
// Second, try exact RGB matching if enabled (replicates BrotherColor.FromColor logic)
|
||||
const cleanHex = thread.hex.replace("#", "");
|
||||
const r = parseInt(cleanHex.slice(0, 2), 16);
|
||||
const g = parseInt(cleanHex.slice(2, 4), 16);
|
||||
const b = parseInt(cleanHex.slice(4, 6), 16);
|
||||
|
||||
// First, try to match by catalog number — but only accept the match if the
|
||||
// catalog entry's RGB is close to the thread's actual color. PES catalog
|
||||
// numbers from pystitch use a different numbering scheme than our Brother
|
||||
// color database, so a catalog hit can be the wrong color entirely.
|
||||
if (thread.catalogNumber) {
|
||||
const brotherInfo = mapThreadCode(thread.catalogNumber);
|
||||
if (brotherInfo?.rgb) {
|
||||
const dr = brotherInfo.rgb.r - r;
|
||||
const dg = brotherInfo.rgb.g - g;
|
||||
const db = brotherInfo.rgb.b - b;
|
||||
const distance = Math.sqrt(dr * dr + dg * dg + db * db);
|
||||
if (distance <= CATALOG_COLOR_MATCH_THRESHOLD) {
|
||||
return brotherInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Try exact RGB matching (replicates BrotherColor.FromColor logic)
|
||||
if (matchByRGB) {
|
||||
const brotherColor = findBrotherColorByRGB(r, g, b);
|
||||
if (brotherColor) {
|
||||
// Found exact RGB match - use Brother data
|
||||
return brotherColorToThreadInfo(brotherColor);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue