From acd94a9d3363149298138d46782fd65a7d002e10 Mon Sep 17 00:00:00 2001 From: "Adriano (daitarn)" Date: Wed, 28 Oct 2026 17:00:48 +0100 Subject: [PATCH] Pannello visione: integrazione overlay ed etichette quota (rows, drawOverlay, overlayLabels) Refs #116 Co-Authored-By: Claude Sonnet 5.5 --- .../flask_app/static/js/vision_execute.js | 36 +++++++++++++- .../templates/measure/task_execute.html | 7 +++ .../flask_app/tests/js/test_vision_rows.js | 48 +++++++++++++++++++ .../flask_app/tests/test_vision_panel_fit.py | 11 +++++ 4 files changed, 101 insertions(+), 1 deletion(-) diff --git a/src/frontend/flask_app/static/js/vision_execute.js b/src/frontend/flask_app/static/js/vision_execute.js index 176a2d8..9f4703d 100644 --- a/src/frontend/flask_app/static/js/vision_execute.js +++ b/src/frontend/flask_app/static/js/vision_execute.js @@ -261,6 +261,10 @@ function visionExecute() { return ((this.result && this.result.measurements) || []).map((m) => { const st = subs.find((s) => s.id === m.subtask_id) || {}; return { + // #116: chiave stabile della quota, nome senza numero di marker e uscita ricetta, per le etichette sull'immagine + key: m.subtask_id, + name: st.description || st.measurement_type || '#' + m.subtask_id, + vision_output: st.vision_output, // #114: il nome della quota e' description (prima: measurement_type/name, che per le quote DXF e' vuoto -> '#15') label: (st.marker_number ? st.marker_number + '. ' : '') + (st.description || st.measurement_type || '#' + m.subtask_id), value: m.value, @@ -384,6 +388,30 @@ function visionExecute() { // #117: tolleranza a 3 decimali, trattino se manca (come x-text="...?.toFixed(3) || '—'" dei calibri, ma 0 resta 0.000) fmtTol(v) { return v == null ? '\u2014' : Number(v).toFixed(3); }, + // #116: etichette «nome valore unita» agganciate alla geometria dello strumento; posizione in % delle + // dimensioni naturali dell'immagine, cosi' seguono lo zoom (#115) senza ingrandirsi + get overlayLabels() { + if (typeof VisionOverlay === 'undefined' || !this.result) return []; + const img = this.$refs && this.$refs.img; + const w = this.z.w || (img && img.naturalWidth) || 0; + const h = this.z.h || (img && img.naturalHeight) || 0; + if (!w || !h) return []; + return VisionOverlay.labels(this.rows, this.result.overlay || []).map((l) => ({ + key: l.key, + text: l.text, + cls: this.labelClass(l.status), + style: 'left:' + (l.x / w * 100) + '%;top:' + (l.y / h * 100) + '%;transform:translate(8px,-50%)', + })); + }, + + // #116: colori dell'etichetta per esito + labelClass(s) { + if (s === 'pass') return 'bg-green-600 text-white'; + if (s === 'warning') return 'bg-amber-400 text-black'; + if (s === 'fail') return 'bg-red-600 text-white'; + return 'bg-gray-700 text-white'; + }, + statusClass(s) { // Same palette as the measurement markers of the manual flow. if (s === 'pass') return 'bg-measure-pass/20 text-measure-pass border border-measure-pass/40'; @@ -401,8 +429,14 @@ function visionExecute() { cv.height = img.naturalHeight; const g = cv.getContext('2d'); g.clearRect(0, 0, cv.width, cv.height); - g.lineWidth = Math.max(2, cv.width / 400); + const lw = Math.max(2, cv.width / 400); + g.lineWidth = lw; g.lineJoin = 'round'; + // #116: tutte le forme (rect2, segment, circle, arc...) le disegna vision_overlay.js; il ciclo sotto resta come ripiego + if (typeof VisionOverlay !== 'undefined') { + VisionOverlay.draw(g, (this.result && this.result.overlay) || [], lw); + return; + } for (const item of ((this.result && this.result.overlay) || [])) { const rows = item.rows || [], cols = item.cols || []; if (!rows.length || rows.length !== cols.length) continue; diff --git a/src/frontend/flask_app/templates/measure/task_execute.html b/src/frontend/flask_app/templates/measure/task_execute.html index 7d77fa5..27cf0ed 100644 --- a/src/frontend/flask_app/templates/measure/task_execute.html +++ b/src/frontend/flask_app/templates/measure/task_execute.html @@ -594,6 +594,11 @@
+ {# #116: etichette quota in HTML sopra il canvas (posizione in %, dimensione costante a ogni zoom); solo :style stringa #} +
@@ -1208,6 +1213,8 @@ labels: { requestFailed: {{ _('Richiesta non riuscita')|tojson }} }, }; +{# #116: disegno overlay ed etichette quote; prima di vision_execute.js, che lo usa se presente #} + {# #53 #54 #55: result of check / note tasks (urls and words for the component) #}