diff --git a/src/components/DatumPanel.vue b/src/components/DatumPanel.vue index 0778e47..809408e 100644 --- a/src/components/DatumPanel.vue +++ b/src/components/DatumPanel.vue @@ -96,6 +96,7 @@ function axisBadge(datum: Datum): string | null { if (datum.type === "rectangle" && datum.isAxisReference) return "axis" if (datum.type === "line" && datum.axisRole === "x") return "+x" if (datum.type === "line" && datum.axisRole === "y") return "+y" + if (datum.type === "ellipse" && datum.isPrimary) return "primary" return null } @@ -407,6 +408,35 @@ function axisBadge(datum: Datum): string | null { +
+ + +
diff --git a/src/lib/solver.ts b/src/lib/solver.ts index 999d1c5..2fa88bb 100644 --- a/src/lib/solver.ts +++ b/src/lib/solver.ts @@ -268,7 +268,10 @@ type Primary = function pickPrimary(datums: Datum[]): Primary { if (datums.length === 0) throw new Error("No datums provided.") - // User-flagged world-axis reference wins regardless of type priority. + // User-flagged primary wins regardless of type priority. Rect's + // `isAxisReference` and line's `axisRole` carry axis semantics on top + // of "primary"; ellipse's `isPrimary` is a pure primary flag (ellipses + // don't define axis directions on their own). for (const d of datums) { if (d.type === "rectangle" && d.isAxisReference) { return { kind: "rect", datum: d } @@ -276,6 +279,9 @@ function pickPrimary(datums: Datum[]): Primary { if (d.type === "line" && d.axisRole) { return { kind: "line", datum: d } } + if (d.type === "ellipse" && d.isPrimary) { + return { kind: "ellipse", datum: d } + } } const typeRank = (d: Datum): number => diff --git a/src/stores/app.ts b/src/stores/app.ts index 790fea7..9037130 100644 --- a/src/stores/app.ts +++ b/src/stores/app.ts @@ -103,14 +103,15 @@ export const useAppStore = defineStore("app", () => { } } - /** Set (or clear) the world-axis role on a datum, enforcing that at + /** Set (or clear) the gauge-primary role on a datum, enforcing that at * most one datum holds the role at a time. - * `role`: "rect" → rectangle.isAxisReference = true - * "x"/"y" → line.axisRole = "x"|"y" - * null → clear the role on `id` (no-op if it wasn't set). */ + * `role`: "rect" → rectangle.isAxisReference = true + * "x"/"y" → line.axisRole = "x"|"y" + * "ellipse" → ellipse.isPrimary = true + * null → clear the role on `id` (no-op if it wasn't set). */ function setAxisRole( id: string, - role: "rect" | "x" | "y" | null, + role: "rect" | "x" | "y" | "ellipse" | null, ) { // Clear any existing flag on other datums. for (let i = 0; i < datums.value.length; i++) { @@ -120,6 +121,8 @@ export const useAppStore = defineStore("app", () => { datums.value[i] = { ...d, isAxisReference: false } } else if (d.type === "line" && d.axisRole) { datums.value[i] = { ...d, axisRole: null } + } else if (d.type === "ellipse" && d.isPrimary) { + datums.value[i] = { ...d, isPrimary: false } } } const idx = datums.value.findIndex((d) => d.id === id) @@ -131,6 +134,8 @@ export const useAppStore = defineStore("app", () => { datums.value[idx] = { ...target, isAxisReference: false } } else if (target.type === "line") { datums.value[idx] = { ...target, axisRole: null } + } else { + datums.value[idx] = { ...target, isPrimary: false } } return } @@ -138,6 +143,8 @@ export const useAppStore = defineStore("app", () => { datums.value[idx] = { ...target, isAxisReference: true } } else if ((role === "x" || role === "y") && target.type === "line") { datums.value[idx] = { ...target, axisRole: role } + } else if (role === "ellipse" && target.type === "ellipse") { + datums.value[idx] = { ...target, isPrimary: true } } } diff --git a/src/types/index.ts b/src/types/index.ts index 2473a78..883b86d 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -49,6 +49,10 @@ export interface EllipseDatum { diameterMm: number confidence: 1 | 2 | 3 | 4 | 5 label: string + /** When true, this ellipse is the gauge primary — overrides the + * type-rank auto-pick. Mutually exclusive with `RectDatum.isAxisReference` + * and `LineDatum.axisRole`; setting any of those clears the others. */ + isPrimary?: boolean } export type Datum = RectDatum | LineDatum | EllipseDatum