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