Wizard DXF: anteprima del disegno appena caricato, con L × H mm #101
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Richiesta Adriano 25/10: quando si carica un dxf sulla ricetta mostrare l'anteprima. Fatto quando: scelto il .dxf nel wizard «Crea ricetta da DXF» compare il disegno (letto dal worker con read_xld_dxf) e le misure L × H.
ESITO: richiesta
COSA: anteprima del disegno appena si sceglie il .dxf nel wizard «Crea ricetta da DXF» (editor task, tipo dxf_compare), con dimensioni L × H in mm, prima di creare la ricetta.
Richiesta di Adriano 25/10/2026: «quando carichi un dxf sulla ricetta fai vedere anteprima».
Scelta di Opus: il DXF si legge sul vision worker con lo stesso lettore del confronto (
visionsuite.io.dxf.read_xld_dxf, usato insrc/vision/costruttori.py:227), così l'anteprima mostra esattamente la geometria che CompareDxf userà. Niente parser DXF in JavaScript.CONTRATTO (identico per piano A e piano B)
POST /dxf/preview(src/vision_worker/main.py), multipart campodxf.POST /api/vision/dxf-preview(src/backend/api/routers/vision.py),require_maker, Formdxf: UploadFile; inoltra al worker e restituisce la stessa risposta.POST /maker/api/vision/dxf-preview(blueprints/maker.py),@login_required+@role_required("Maker"), campo filedxf; inoltra al backend.{"contorni": [[[x, y], ...], ...], "bbox": {"xmin": f, "ymin": f, "xmax": f, "ymax": f}, "larghezza_mm": f, "altezza_mm": f, "entita": int, "punti": int}
Coordinate in mm del DXF, asse y verso il basso (come immagine e SVG): y = -y_dxf. Arrotondate a 3 decimali. Totale punti ≤ 20000 (decimazione uniforme per contorno se si supera, mantenendo primo e ultimo punto).
entita= numero di contorni,punti= punti restituiti.api_dxf_compare_recipe(maker.py:674).PIANO A — worker + backend (ramo lavoro/daitarn-tmf-101a)
/dxf/preview. Scrive i byte in un file temporaneo,read_xld_dxf(path, sampling_distance=0.05, scale=1.0, flip_y=False), poi y = -y; i contorni li converte in liste [x, y] (verificare i nomi degli attributi di XldCont: righe/colonne o x/y; leggerevisionsuite/io/dxf.pynel venvC:/Users/Adriano/lavoro/TieMeasureFlow-dxfcal/build/venv313). La parte sincrona va inrun_in_threadpool/executor come_decode_and_build_dxf(main.py:229).dxf_preview(dxf_bytes)sul modello didxf_compare_recipe(riga ~201), riusando il POST multipart generico al worker (riga ~154).POST /dxf-preview(prefisso del router = /api/vision).PYTHONPATH=. C:/Users/Adriano/lavoro/TieMeasureFlow-dxfcal-backend/.venv/Scripts/python.exe -m pytest src/backend/tests/<file> -q -p no:cacheprovider. Test del worker: conC:/Users/Adriano/lavoro/TieMeasureFlow-dxfcal/build/venv313/Scripts/python.exe(ha visionsuite), cartella test esistente del worker (cercarla:src/vision_worker/testsotests/).NON TOCCARE (A): src/frontend/**, costruttori.py (solo lettura), CompareDxf.
PIANO B — Flask + pagina (ramo lavoro/daitarn-tmf-101b)
/api/vision/dxf-previewsul modello diapi_dxf_compare_recipe(riga 674): 400 «Serve il file DXF» se manca.dxfPreview: null,dxfPreviewBusy: false,dxfPreviewError: ''.onDxf(ev)(riga 90) oltre a oggi chiamaloadDxfPreview()→ POST multipart con CSRF comerun()(riga ~133-141). Con file tolto: tutto azzerato. Una risposta arrivata dopo un cambio di file si scarta (contatore).Funzione
dxfPreviewPaths()→ array di stringhepointsper<polyline>;dxfPreviewViewBox()→ bbox con margine 5% (minimo 0.5 mm).preserveAspectRatio="xMidYMid meet", sfondo var(--bg-primary), bordo),<polyline fill="none" vector-effect="non-scaling-stroke" stroke-width="1.5">col colore primario; sotto: «L × H mm · N entità» con virgola decimale (2 decimali). Durante il caricamento «Lettura DXF…»; errore in rosso col detail. Testi con_(), voci intranslations/en/LC_MESSAGES/messages.po(non committare .mo).src/frontend/flask_app/tests/conmock_api_client; comandoC:/Users/Adriano/lavoro/TieMeasureFlow-dxfcal-frontend/.venv/Scripts/python.exe -m pytest tests -q -p no:cacheproviderdasrc/frontend/flask_app. Base: 9 fallimenti preesistenti (+4 di lingua/.mo nei worktree), nessuno nuovo.NON TOCCARE (B): src/backend/, src/vision_worker/, templates/statistics/** (ci lavora #100).
PROVA (Opus): merge A+B su lavoro/daitarn-tmf-dxfcal, riavvio TMF, headless Edge su editor del task 8: scelta di
C:/Users/Adriano/Desktop/Sider foto e DXF/DXF profilo/12.3X5.1MEVISS235JR_profilo.dxf→ SVG con contorni e circa «12,30 × 5,10 mm»; file non DXF → errore leggibile.Soluzione
ESITO: fatto
FILE: src/vision_worker/main.py — POST /dxf/preview (_dxf_preview: read_xld_dxf sampling 0.05 mm, y=-y, bbox su punti completi, decimazione ≤20000); src/backend/services/vision_service.py dxf_preview; src/backend/api/routers/vision.py POST /api/vision/dxf-preview (Maker, limite max_upload_size_mb → 422); src/frontend/flask_app/blueprints/maker.py proxy /maker/api/vision/dxf-preview; static/js/dxf_recipe_wizard.js loadDxfPreview/dxfPreviewD/dxfPreviewViewBox/dxfPreviewSummary; templates/maker/task_editor.html SVG con un solo e x-bind:view-box.camel (x-for dentro svg non va con Alpine; :viewBox viene abbassato dal parser).
TEST: backend test_vision_dxf_preview.py (5), worker test_dxf_compare.py -k preview (5), frontend TestDxfPreviewProxy (4) + tests/js/test_dxf_preview.js.
COMMIT:
ebaafbe,bdb1e8c, e582df7; merge fino a4791c34su lavoro/daitarn-tmf-dxfcal (pushato).PROVA: TMF daitarn riavviato, headless Edge task 8 ricetta 3: MEVIS chiuso → path d 488 car., viewBox 3.68 -21.997 13.53 6.33, «12,30 × 5,10 mm · 1 entità»; PR165 profilo → «15,38 × 5,20 mm · 12 entità»; DXF completo Sider (R12 rotto) → errore rosso «DXF illeggibile: ValueError: Invalid handle 0.»