| = (int)$job['id']; ?> |
@@ -390,24 +379,29 @@ $jobs = $stmt->fetchAll(PDO::FETCH_ASSOC);
= $badge; ?> |
= $areaMm2; ?> |
= $areaCm2; ?> |
- = htmlspecialchars((string)$method, ENT_QUOTES, 'UTF-8'); ?> |
- = htmlspecialchars((string)$confidence, ENT_QUOTES, 'UTF-8'); ?> |
-
- 📄 Apri
+
+ 📄
+
+
+ 📐 DXF
+
+
+
@@ -540,6 +534,10 @@ $jobs = $stmt->fetchAll(PDO::FETCH_ASSOC);
Chiudi
+
+
@@ -607,9 +605,15 @@ $jobs = $stmt->fetchAll(PDO::FETCH_ASSOC);
let edgeSnapEnabled = false;
let edgeSnapPreviewPoint = null;
- const EDGE_SNAP_RADIUS = 45;
- const EDGE_DARK_THRESHOLD = 245;
- const EDGE_GRADIENT_THRESHOLD = 8;
+ const EDGE_SNAP_RADIUS = 50;
+ const EDGE_DARK_THRESHOLD = 200;
+
+ let edgeGray = null;
+ let edgeGrayW = 0;
+ let edgeGrayH = 0;
+ let snapRafPending = false;
+ let lastSnapMousePos = null;
+ let edgeCacheDirty = true;
let lastManualResult = null;
@@ -863,6 +867,8 @@ $jobs = $stmt->fetchAll(PDO::FETCH_ASSOC);
manualCurrentView = 'full';
manualRoiPageRect = null;
+ edgeCacheDirty = true;
+
const viewport = manualPdfPage.getViewport({
scale: manualBaseScale
});
@@ -880,6 +886,7 @@ $jobs = $stmt->fetchAll(PDO::FETCH_ASSOC);
canvasContext: manualPdfCtx,
viewport: viewport
}).promise.then(() => {
+ rebuildEdgeCache();
updateManualViewBadge();
redrawManualOverlay();
});
@@ -953,6 +960,7 @@ $jobs = $stmt->fetchAll(PDO::FETCH_ASSOC);
}
manualCurrentView = 'roi';
+ edgeCacheDirty = true;
const scale = manualBaseScale * MANUAL_ROI_ZOOM_FACTOR;
const viewport = manualPdfPage.getViewport({
@@ -983,6 +991,7 @@ $jobs = $stmt->fetchAll(PDO::FETCH_ASSOC);
viewport: viewport
}).promise.then(() => {
manualPdfCtx.restore();
+ rebuildEdgeCache();
updateManualViewBadge();
redrawManualOverlay();
}).catch(error => {
@@ -1067,6 +1076,7 @@ $jobs = $stmt->fetchAll(PDO::FETCH_ASSOC);
document.getElementById('saveManualAreaBtn').disabled = true;
document.getElementById('manualCoordsPreview').innerText = 'Nessun dato calcolato.';
+ document.getElementById('exportDxfBtn').disabled = true;
edgeSnapEnabled = false;
@@ -1171,8 +1181,18 @@ $jobs = $stmt->fetchAll(PDO::FETCH_ASSOC);
return;
}
if (edgeSnapEnabled && ['polygon', 'hole', 'edit'].includes(currentTool)) {
- edgeSnapPreviewPoint = snapToNearestEdge(pos, EDGE_SNAP_RADIUS);
- redrawManualOverlay();
+ lastSnapMousePos = pos;
+
+ if (!snapRafPending) {
+ snapRafPending = true;
+
+ requestAnimationFrame(() => {
+ snapRafPending = false;
+ edgeSnapPreviewPoint = snapToNearestEdge(lastSnapMousePos, EDGE_SNAP_RADIUS);
+ redrawManualOverlay();
+ });
+ }
+
return;
}
@@ -1318,96 +1338,119 @@ $jobs = $stmt->fetchAll(PDO::FETCH_ASSOC);
return pos;
}
+ function rebuildEdgeCache() {
+ edgeGray = null;
+
+ if (!manualPdfCanvas || !manualPdfCtx) {
+ return;
+ }
+
+ try {
+ const w = manualPdfCanvas.width;
+ const h = manualPdfCanvas.height;
+ const d = manualPdfCtx.getImageData(0, 0, w, h).data;
+
+ edgeGray = new Uint8Array(w * h);
+
+ for (let i = 0, p = 0; i < edgeGray.length; i++, p += 4) {
+ edgeGray[i] = (d[p] + d[p + 1] + d[p + 2]) / 3;
+ }
+
+ edgeGrayW = w;
+ edgeGrayH = h;
+ edgeCacheDirty = false;
+
+ console.log('Edge cache OK:', w + 'x' + h);
+ } catch (e) {
+ console.warn('Edge cache failed:', e);
+ edgeGray = null;
+ }
+ }
+
function snapToNearestEdge(pos, radius) {
- const canvasWidth = manualPdfCanvas.width;
- const canvasHeight = manualPdfCanvas.height;
+ if (edgeCacheDirty || !edgeGray || edgeGrayW !== manualPdfCanvas.width || edgeGrayH !== manualPdfCanvas.height) {
+ rebuildEdgeCache();
+ }
+
+ if (!edgeGray) {
+ return null;
+ }
+
+ const w = edgeGrayW;
+ const h = edgeGrayH;
const cx = Math.round(pos.x);
const cy = Math.round(pos.y);
- const x0 = Math.max(1, cx - radius);
- const y0 = Math.max(1, cy - radius);
- const x1 = Math.min(canvasWidth - 2, cx + radius);
- const y1 = Math.min(canvasHeight - 2, cy + radius);
-
- const w = x1 - x0 + 1;
- const h = y1 - y0 + 1;
-
- if (w <= 3 || h <= 3) {
- return null;
- }
-
- let imageData;
-
- try {
- imageData = manualPdfCtx.getImageData(x0, y0, w, h);
- } catch (e) {
- console.warn('Edge snap getImageData failed:', e);
- return null;
- }
-
- const data = imageData.data;
-
- function grayAt(localX, localY) {
- const index = (localY * w + localX) * 4;
- const r = data[index];
- const g = data[index + 1];
- const b = data[index + 2];
-
- return (r + g + b) / 3;
- }
+ const x0 = Math.max(0, cx - radius);
+ const y0 = Math.max(0, cy - radius);
+ const x1 = Math.min(w - 1, cx + radius);
+ const y1 = Math.min(h - 1, cy + radius);
let best = null;
- let bestScore = -Infinity;
+ let bestScore = Infinity;
+ const r2 = radius * radius;
- for (let yy = 1; yy < h - 1; yy++) {
- for (let xx = 1; xx < w - 1; xx++) {
- const globalX = x0 + xx;
- const globalY = y0 + yy;
+ for (let y = y0; y <= y1; y++) {
+ const rowOffset = y * w;
- const dx = globalX - pos.x;
- const dy = globalY - pos.y;
- const dist = Math.sqrt(dx * dx + dy * dy);
+ for (let x = x0; x <= x1; x++) {
+ const v = edgeGray[rowOffset + x];
- if (dist > radius) {
+ if (v > EDGE_DARK_THRESHOLD) {
continue;
}
- const center = grayAt(xx, yy);
+ const dx = x - pos.x;
+ const dy = y - pos.y;
+ const d2 = dx * dx + dy * dy;
- const gx = Math.abs(grayAt(xx + 1, yy) - grayAt(xx - 1, yy));
- const gy = Math.abs(grayAt(xx, yy + 1) - grayAt(xx, yy - 1));
- const gradient = gx + gy;
-
- const isDarkEnough = center < EDGE_DARK_THRESHOLD;
- const isRealEdge = gradient > EDGE_GRADIENT_THRESHOLD;
-
- if (!isDarkEnough && !isRealEdge) {
+ if (d2 > r2) {
continue;
}
- /*
- * Prefer:
- * - dark strokes
- * - real contrast edges
- * - points close to the cursor
- */
- const darknessScore = Math.max(0, 255 - center);
- const gradientScore = gradient * 3;
- const distancePenalty = dist * 4;
+ const score = Math.sqrt(d2) - (EDGE_DARK_THRESHOLD - v) * 0.03;
- const score = darknessScore + gradientScore - distancePenalty;
-
- if (score > bestScore) {
+ if (score < bestScore) {
bestScore = score;
best = {
- x: globalX,
- y: globalY
+ x: x,
+ y: y
};
}
}
}
+ if (!best) {
+ return null;
+ }
+
+ let sumX = 0;
+ let sumY = 0;
+ let sumW = 0;
+
+ for (let y = Math.max(0, best.y - 2); y <= Math.min(h - 1, best.y + 2); y++) {
+ for (let x = Math.max(0, best.x - 2); x <= Math.min(w - 1, best.x + 2); x++) {
+ const v = edgeGray[y * w + x];
+
+ if (v > EDGE_DARK_THRESHOLD) {
+ continue;
+ }
+
+ const weight = EDGE_DARK_THRESHOLD - v;
+ sumX += x * weight;
+ sumY += y * weight;
+ sumW += weight;
+ }
+ }
+
+ if (sumW > 0) {
+ return {
+ x: sumX / sumW,
+ y: sumY / sumW
+ };
+ }
+
return best;
}
@@ -1756,6 +1799,12 @@ $jobs = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (saveBtn) {
saveBtn.disabled = true;
}
+
+ const dxfBtn = document.getElementById('exportDxfBtn');
+
+ if (dxfBtn) {
+ dxfBtn.disabled = true;
+ }
}
function isSelectedPoint(type, holeIndex, pointIndex) {
@@ -2315,6 +2364,7 @@ $jobs = $stmt->fetchAll(PDO::FETCH_ASSOC);
};
document.getElementById('saveManualAreaBtn').disabled = false;
+ document.getElementById('exportDxfBtn').disabled = false;
setManualStatus(
`Area finale: ${finalAreaMm2.toFixed(3)} mm² = ${finalAreaCm2.toFixed(4)} cm². ` +
@@ -2335,8 +2385,17 @@ $jobs = $stmt->fetchAll(PDO::FETCH_ASSOC);
return;
}
+ let dxfContent = '';
+
+ try {
+ dxfContent = buildDxfString();
+ } catch (e) {
+ console.warn('DXF build failed:', e);
+ }
+
const payload = {
id: currentManualJobId,
+ dxf_content: dxfContent,
area_mm2: +lastManualResult.area_mm2.toFixed(6),
area_cm2: +lastManualResult.area_cm2.toFixed(6),
@@ -2417,6 +2476,69 @@ $jobs = $stmt->fetchAll(PDO::FETCH_ASSOC);
});
}
+ function toMmPoint(p) {
+ return {
+ x: p.x * mmPerPx,
+ y: (manualOverlayCanvas.height - p.y) * mmPerPx
+ };
+ }
+
+ function dxfPolyline(points, layer) {
+ let s = '0\nPOLYLINE\n8\n' + layer + '\n66\n1\n70\n1\n';
+
+ points.forEach(p => {
+ const m = toMmPoint(p);
+ s += '0\nVERTEX\n8\n' + layer +
+ '\n10\n' + m.x.toFixed(4) +
+ '\n20\n' + m.y.toFixed(4) +
+ '\n30\n0.0\n';
+ });
+
+ return s + '0\nSEQEND\n';
+ }
+
+ function buildDxfString() {
+ let dxf = '0\nSECTION\n2\nHEADER\n9\n$INSUNITS\n70\n4\n0\nENDSEC\n';
+ dxf += '0\nSECTION\n2\nENTITIES\n';
+ dxf += dxfPolyline(polygonPoints, 'PROFILO');
+
+ holes.forEach(hole => {
+ if (hole.length >= 3) {
+ dxf += dxfPolyline(hole, 'ESCLUSIONI');
+ }
+ });
+
+ dxf += '0\nENDSEC\n0\nEOF\n';
+ return dxf;
+ }
+
+ function exportDxf() {
+ if (!lastManualResult || !mmPerPx || polygonPoints.length < 3) {
+ Swal.fire({
+ icon: 'warning',
+ title: 'Prima calcola l\u2019area',
+ text: 'Il DXF viene generato dal profilo calibrato.'
+ });
+ return;
+ }
+
+ const dxf = buildDxfString();
+
+ const blob = new Blob([dxf], {
+ type: 'application/dxf'
+ });
+
+ const a = document.createElement('a');
+ a.href = URL.createObjectURL(blob);
+ a.download = 'profilo_job_' + currentManualJobId + '.dxf';
+ a.click();
+ URL.revokeObjectURL(a.href);
+ }
+
+ document.getElementById('exportDxfBtn').addEventListener('click', function() {
+ exportDxf();
+ });
+
function polygonAreaPx2(points) {
let area = 0;
@@ -2634,6 +2756,8 @@ $jobs = $stmt->fetchAll(PDO::FETCH_ASSOC);
btn.classList.add('btn-warning', 'active');
btn.innerText = '🧲 Magnete bordo ON';
+ rebuildEdgeCache();
+
setManualStatus(
'Magnete bordo attivo: quando disegni o sposti punti, il sistema prova ad agganciarli al bordo scuro più vicino.'
);
diff --git a/public/userarea/cad_area_save_manual_area.php b/public/userarea/cad_area_save_manual_area.php
index fb83783..8b81400 100644
--- a/public/userarea/cad_area_save_manual_area.php
+++ b/public/userarea/cad_area_save_manual_area.php
@@ -50,6 +50,7 @@ try {
$outerPolygon = $input['manual_polygon'] ?? null;
$holes = $input['manual_holes'] ?? [];
$roi = $input['roi'] ?? null;
+ $dxfContent = isset($input['dxf_content']) ? (string)$input['dxf_content'] : '';
if ($areaMm2 <= 0) {
jsonResponse([
@@ -106,6 +107,43 @@ try {
$manualHolesJson = json_encode($holes);
+ $dxfFilename = null;
+ $dxfUrl = null;
+
+ if ($dxfContent !== '') {
+
+ if (strlen($dxfContent) > 5 * 1024 * 1024) {
+ jsonResponse([
+ 'success' => false,
+ 'message' => 'DXF troppo grande.'
+ ]);
+ }
+
+ if (strpos($dxfContent, 'SECTION') === false || strpos($dxfContent, 'EOF') === false) {
+ jsonResponse([
+ 'success' => false,
+ 'message' => 'Contenuto DXF non valido.'
+ ]);
+ }
+
+ $dxfDir = __DIR__ . '/uploads/cad_area/dxf/';
+
+ if (!is_dir($dxfDir)) {
+ mkdir($dxfDir, 0755, true);
+ }
+
+ $dxfFilename = 'profilo_' . $id . '_' . date('Ymd_His') . '_' . bin2hex(random_bytes(4)) . '.dxf';
+
+ if (file_put_contents($dxfDir . $dxfFilename, $dxfContent) === false) {
+ jsonResponse([
+ 'success' => false,
+ 'message' => 'Impossibile salvare il file DXF sul server.'
+ ]);
+ }
+
+ $dxfUrl = 'uploads/cad_area/dxf/' . $dxfFilename;
+ }
+
$roiX = null;
$roiY = null;
$roiW = null;
@@ -152,6 +190,9 @@ try {
manual_holes_json = ?,
manual_status = 'completed',
+ dxf_filename = COALESCE(?, dxf_filename),
+ dxf_url = COALESCE(?, dxf_url),
+
scale_used = ?,
scale_detected = ?,
confidence = 'manual_validated',
@@ -188,6 +229,9 @@ try {
$manualPolygonJson,
$manualHolesJson,
+ $dxfFilename,
+ $dxfUrl,
+
$mmPerPx,
'manual',
@@ -227,6 +271,9 @@ try {
manual_holes_json = ?,
manual_status = 'completed',
+ dxf_filename = COALESCE(?, dxf_filename),
+ dxf_url = COALESCE(?, dxf_url),
+
scale_used = ?,
scale_detected = ?,
confidence = 'manual_validated',
@@ -264,6 +311,9 @@ try {
$manualPolygonJson,
$manualHolesJson,
+ $dxfFilename,
+ $dxfUrl,
+
$mmPerPx,
'manual',
@@ -285,7 +335,8 @@ try {
'area_mm2' => $areaMm2,
'area_cm2' => $areaCm2,
'outer_area_mm2' => $outerAreaMm2,
- 'holes_area_mm2' => $holesAreaMm2
+ 'holes_area_mm2' => $holesAreaMm2,
+ 'dxf_url' => $dxfUrl
]);
} catch (Throwable $e) {
error_log('CAD manual area save error: ' . $e->getMessage());
diff --git a/public/userarea/uploads/cad_area/dxf/profilo_26_20260706_084332_19608179.dxf b/public/userarea/uploads/cad_area/dxf/profilo_26_20260706_084332_19608179.dxf
new file mode 100644
index 0000000..28a1115
--- /dev/null
+++ b/public/userarea/uploads/cad_area/dxf/profilo_26_20260706_084332_19608179.dxf
@@ -0,0 +1,1148 @@
+0
+SECTION
+2
+HEADER
+9
+$INSUNITS
+70
+4
+0
+ENDSEC
+0
+SECTION
+2
+ENTITIES
+0
+POLYLINE
+8
+PROFILO
+66
+1
+70
+1
+0
+VERTEX
+8
+PROFILO
+10
+4.7362
+20
+7.7571
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+4.7666
+20
+1.5636
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+5.0247
+20
+1.1233
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+5.6015
+20
+0.9867
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+5.7837
+20
+1.2296
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+6.0266
+20
+1.7002
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+6.2391
+20
+2.0797
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+6.8463
+20
+2.4137
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+7.1347
+20
+2.0190
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+7.2865
+20
+1.5332
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+7.6357
+20
+1.1385
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+7.9393
+20
+1.0626
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+8.3643
+20
+1.1537
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+8.5313
+20
+1.5787
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+8.8501
+20
+2.0949
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+9.3055
+20
+2.3378
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+9.6091
+20
+1.9431
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+9.8975
+20
+1.4573
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+10.1556
+20
+1.1689
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+10.4440
+20
+1.0474
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+10.7932
+20
+1.1082
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+10.9601
+20
+1.4877
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+11.2182
+20
+1.8065
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+11.4156
+20
+2.1860
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+11.5825
+20
+2.2619
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+12.0076
+20
+2.2163
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+12.2505
+20
+1.8216
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+12.4934
+20
+1.3662
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+12.8880
+20
+1.1082
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+13.2372
+20
+1.1233
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+13.5408
+20
+1.3966
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+13.8899
+20
+1.6698
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+14.5882
+20
+2.0493
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+15.1954
+20
+2.1101
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+15.6508
+20
+2.0038
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+16.1366
+20
+1.7154
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+16.6679
+20
+1.5939
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.1537
+20
+1.4118
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.8216
+20
+1.1841
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+18.5958
+20
+1.1233
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+19.2637
+20
+1.0778
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+19.9317
+20
+1.0474
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+20.5996
+20
+1.1082
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+20.7514
+20
+1.3814
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+20.8425
+20
+1.7154
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+20.8121
+20
+2.1252
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+20.2656
+20
+2.3681
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+19.5066
+20
+2.6414
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+18.9450
+20
+2.9905
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+18.5806
+20
+3.3245
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+18.0493
+20
+3.6584
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.7002
+20
+3.9620
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.4573
+20
+4.3264
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+16.8501
+20
+4.9639
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+16.5009
+20
+5.2827
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+16.3340
+20
+5.7078
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+15.9241
+20
+6.1784
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+15.7419
+20
+6.7704
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+15.6053
+20
+7.1803
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+15.4231
+20
+7.6964
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+15.1347
+20
+8.2732
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+14.8767
+20
+8.9260
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+14.6489
+20
+9.3662
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+14.4061
+20
+9.6850
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+13.6471
+20
+9.9734
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+12.9184
+20
+9.8520
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+12.8273
+20
+9.5332
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+12.8273
+20
+8.9412
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+12.9184
+20
+8.4858
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+12.8880
+20
+8.1214
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+12.5844
+20
+7.7875
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+12.1746
+20
+7.7571
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+11.6584
+20
+7.8027
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+11.0512
+20
+7.7571
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+10.6110
+20
+7.7571
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+10.3529
+20
+7.8482
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+10.3529
+20
+8.3947
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+10.3378
+20
+8.8197
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+10.7780
+20
+8.9412
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+10.8083
+20
+9.2448
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+10.3681
+20
+9.5939
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+9.8823
+20
+10.0645
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+9.5787
+20
+10.2922
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+8.8501
+20
+10.2770
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+8.0455
+20
+10.2922
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+7.5901
+20
+10.3226
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+7.0588
+20
+9.8064
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+6.7856
+20
+9.4877
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+6.5427
+20
+9.1537
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+6.5427
+20
+8.8501
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+6.8008
+20
+8.8501
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+7.0588
+20
+8.8046
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+7.0436
+20
+8.5617
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+6.9981
+20
+8.1670
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+7.0133
+20
+7.7875
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+6.7856
+20
+7.7268
+30
+0.0
+0
+SEQEND
+0
+POLYLINE
+8
+ESCLUSIONI
+66
+1
+70
+1
+0
+VERTEX
+8
+ESCLUSIONI
+10
+7.8786
+20
+9.1841
+30
+0.0
+0
+VERTEX
+8
+ESCLUSIONI
+10
+7.8937
+20
+8.1063
+30
+0.0
+0
+VERTEX
+8
+ESCLUSIONI
+10
+8.0911
+20
+7.7116
+30
+0.0
+0
+VERTEX
+8
+ESCLUSIONI
+10
+8.5313
+20
+7.4990
+30
+0.0
+0
+VERTEX
+8
+ESCLUSIONI
+10
+9.0019
+20
+7.4839
+30
+0.0
+0
+VERTEX
+8
+ESCLUSIONI
+10
+9.2751
+20
+7.8027
+30
+0.0
+0
+VERTEX
+8
+ESCLUSIONI
+10
+9.5787
+20
+8.0304
+30
+0.0
+0
+VERTEX
+8
+ESCLUSIONI
+10
+9.6091
+20
+8.6527
+30
+0.0
+0
+VERTEX
+8
+ESCLUSIONI
+10
+9.5028
+20
+9.1689
+30
+0.0
+0
+VERTEX
+8
+ESCLUSIONI
+10
+9.2903
+20
+9.4118
+30
+0.0
+0
+VERTEX
+8
+ESCLUSIONI
+10
+8.8653
+20
+9.5332
+30
+0.0
+0
+VERTEX
+8
+ESCLUSIONI
+10
+8.5465
+20
+9.5787
+30
+0.0
+0
+VERTEX
+8
+ESCLUSIONI
+10
+8.2581
+20
+9.4725
+30
+0.0
+0
+VERTEX
+8
+ESCLUSIONI
+10
+7.8937
+20
+9.2903
+30
+0.0
+0
+VERTEX
+8
+ESCLUSIONI
+10
+7.8330
+20
+9.0778
+30
+0.0
+0
+SEQEND
+0
+ENDSEC
+0
+EOF
diff --git a/public/userarea/uploads/cad_area/dxf/profilo_26_20260706_084800_58bb8b04.dxf b/public/userarea/uploads/cad_area/dxf/profilo_26_20260706_084800_58bb8b04.dxf
new file mode 100644
index 0000000..9b97ddc
--- /dev/null
+++ b/public/userarea/uploads/cad_area/dxf/profilo_26_20260706_084800_58bb8b04.dxf
@@ -0,0 +1,158 @@
+0
+SECTION
+2
+HEADER
+9
+$INSUNITS
+70
+4
+0
+ENDSEC
+0
+SECTION
+2
+ENTITIES
+0
+POLYLINE
+8
+PROFILO
+66
+1
+70
+1
+0
+VERTEX
+8
+PROFILO
+10
+5.9087
+20
+9.0157
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+6.0608
+20
+2.8408
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+11.0190
+20
+2.8256
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+16.7528
+20
+3.2362
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.9239
+20
+4.4834
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.7262
+20
+6.6887
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.1939
+20
+8.1336
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+16.0076
+20
+10.2476
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+15.3688
+20
+10.9320
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+13.4373
+20
+11.0233
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+9.0722
+20
+11.4339
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+8.1597
+20
+11.2210
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+7.3992
+20
+10.7343
+30
+0.0
+0
+SEQEND
+0
+ENDSEC
+0
+EOF
diff --git a/public/userarea/uploads/cad_area/dxf/profilo_26_20260706_090611_5f78cd4d.dxf b/public/userarea/uploads/cad_area/dxf/profilo_26_20260706_090611_5f78cd4d.dxf
new file mode 100644
index 0000000..100b0b0
--- /dev/null
+++ b/public/userarea/uploads/cad_area/dxf/profilo_26_20260706_090611_5f78cd4d.dxf
@@ -0,0 +1,1078 @@
+0
+SECTION
+2
+HEADER
+9
+$INSUNITS
+70
+4
+0
+ENDSEC
+0
+SECTION
+2
+ENTITIES
+0
+POLYLINE
+8
+PROFILO
+66
+1
+70
+1
+0
+VERTEX
+8
+PROFILO
+10
+11.6949
+20
+67.7962
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+11.5794
+20
+65.6798
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+11.5798
+20
+61.6678
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+12.3134
+20
+60.9925
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+12.9390
+20
+61.6120
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+13.3359
+20
+62.2213
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+13.9572
+20
+61.9417
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+14.1417
+20
+61.5575
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+14.2533
+20
+61.3339
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+14.5903
+20
+61.0300
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+14.8045
+20
+60.9861
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+15.2908
+20
+61.1807
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+15.5914
+20
+61.7196
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+16.1589
+20
+62.2703
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+16.4315
+20
+62.1458
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+16.5604
+20
+61.9411
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+16.7939
+20
+61.4477
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+16.9714
+20
+61.1746
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.1396
+20
+61.0515
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.5758
+20
+60.9995
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.9785
+20
+61.2883
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+18.2727
+20
+61.8862
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+18.3287
+20
+61.9987
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+18.5986
+20
+62.2472
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+18.7616
+20
+62.2698
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+19.3167
+20
+61.6117
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+19.6895
+20
+61.0838
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+19.8990
+20
+60.9973
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+20.1782
+20
+61.0000
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+20.9216
+20
+61.6371
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+21.6374
+20
+62.0632
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+22.4525
+20
+62.0615
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+22.8363
+20
+61.8947
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+23.1636
+20
+61.6471
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+23.4826
+20
+61.5128
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+24.7825
+20
+61.1333
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+25.2212
+20
+61.0492
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+25.3823
+20
+61.0279
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+25.6524
+20
+60.9880
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+26.2956
+20
+60.9502
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+27.0638
+20
+60.9504
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+27.7164
+20
+61.0426
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+27.8636
+20
+61.1422
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+28.0249
+20
+61.4008
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+28.0589
+20
+61.5542
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+28.0638
+20
+61.6628
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+27.9524
+20
+61.9856
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+27.8151
+20
+62.1166
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+27.3354
+20
+62.3447
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+26.7916
+20
+62.5853
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+26.1956
+20
+62.8990
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+25.7031
+20
+63.2217
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+24.9311
+20
+63.8192
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+24.4097
+20
+64.3222
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+24.1231
+20
+64.6399
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+23.8039
+20
+65.0280
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+23.4634
+20
+65.5166
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+22.8199
+20
+66.7100
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+22.6395
+20
+67.1474
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+22.4578
+20
+67.6473
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+22.1785
+20
+68.2444
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+21.5905
+20
+69.2359
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+21.3407
+20
+69.8040
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+21.0977
+20
+69.9317
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+20.2843
+20
+69.9845
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+20.0530
+20
+69.9709
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+19.9266
+20
+69.7475
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+19.9266
+20
+69.0425
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+19.9266
+20
+68.6086
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+19.9049
+20
+68.1711
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+19.8885
+20
+68.1298
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+19.6311
+20
+67.8726
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+19.3489
+20
+67.7933
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+18.9826
+20
+67.8125
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+18.6763
+20
+67.7874
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.8285
+20
+67.7970
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.2120
+20
+67.7012
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.2286
+20
+68.0109
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.2199
+20
+68.5001
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.2353
+20
+68.7874
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.2572
+20
+68.8630
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.2572
+20
+68.8630
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.7232
+20
+68.9862
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.7984
+20
+69.1511
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.6954
+20
+69.3828
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+17.3599
+20
+69.7033
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+16.9212
+20
+70.1273
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+16.4280
+20
+70.3508
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+16.2166
+20
+70.4183
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+15.5650
+20
+70.4175
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+14.7000
+20
+70.4159
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+14.5305
+20
+70.3783
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+14.4226
+20
+70.2930
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+14.2785
+20
+70.1625
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+13.8949
+20
+69.7902
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+13.7301
+20
+69.6296
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+13.3786
+20
+69.1498
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+13.3870
+20
+69.0961
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+13.4283
+20
+69.0069
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+14.0280
+20
+68.7172
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+14.0280
+20
+68.7172
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+14.3514
+20
+68.2036
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+13.9626
+20
+68.0653
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+13.7818
+20
+67.8295
+30
+0.0
+0
+VERTEX
+8
+PROFILO
+10
+13.7133
+20
+67.8040
+30
+0.0
+0
+SEQEND
+0
+ENDSEC
+0
+EOF
|