diff --git a/docker/php.ini b/docker/php.ini index 81297f7..cc0de64 100644 --- a/docker/php.ini +++ b/docker/php.ini @@ -1,3 +1,5 @@ -upload_max_filesize = 20M -post_max_size = 25M -memory_limit = 256M +upload_max_filesize = 300M +post_max_size = 310M +memory_limit = 512M +max_execution_time = 120 +max_input_time = 120 diff --git a/modules/printvault/api.php b/modules/printvault/api.php index 36f481d..70dc2e0 100644 --- a/modules/printvault/api.php +++ b/modules/printvault/api.php @@ -241,7 +241,7 @@ if ($action === 'models') { // ── GCODE PATHS ──────────────────────────────────────────────────────────────── if ($action === 'gcode_paths') { $id = (int)($_GET['id'] ?? 0); - $max = min((int)($_GET['max'] ?? 300000), 500000); + $max = (int)($_GET['max'] ?? 0) ?: PHP_INT_MAX; // no cap by default $s = $pdo->prepare("SELECT filename, file_type FROM pf_pv_models WHERE id=?"); $s->execute([$id]); $row = $s->fetch(); if (!$row) pvErr('Introuvable', 404); $ext = strtolower($row['file_type']); @@ -251,7 +251,7 @@ if ($action === 'gcode_paths') { $segments = []; $x=0.0; $y=0.0; $z=0.0; $e=0.0; $lastE=0.0; - $minZ=PHP_FLOAT_MAX; $maxZ=0.0; + $minZ=PHP_FLOAT_MAX; $maxZ=0.0; $count=0; $handle = fopen($path, 'r'); while (!feof($handle) && count($segments) < $max) { @@ -272,15 +272,19 @@ if ($action === 'gcode_paths') { if (preg_match('/E([-\d.]+)/i', $line, $m)) $ne = (float)$m[1]; $extruding = ($cmd === 'G1' && $ne > $lastE) ? 1 : 0; if ($nx !== $x || $ny !== $y || $nz !== $z) { - $segments[] = [$x, $y, $z, $nx, $ny, $nz, $extruding]; + // Compact flat array: x1,y1,z1,x2,y2,z2,ext (2 decimal precision) + $segments[] = round($x,2); $segments[] = round($y,2); $segments[] = round($z,2); + $segments[] = round($nx,2); $segments[] = round($ny,2); $segments[] = round($nz,2); + $segments[] = $extruding; $minZ = min($minZ, $nz); $maxZ = max($maxZ, $nz); + $count++; } $x=$nx; $y=$ny; $z=$nz; if ($ne !== $e) { $lastE = $e = $ne; } } fclose($handle); - pvOk(['segments' => $segments, 'min_z' => $minZ === PHP_FLOAT_MAX ? 0 : $minZ, 'max_z' => $maxZ, 'total' => count($segments)]); + pvOk(['flat' => $segments, 'min_z' => round($minZ === PHP_FLOAT_MAX ? 0 : $minZ, 2), 'max_z' => round($maxZ, 2), 'total' => $count]); } // ── FILE SERVE ───────────────────────────────────────────────────────────────── diff --git a/printvault-viewer.php b/printvault-viewer.php index 11221e9..c63db0a 100644 --- a/printvault-viewer.php +++ b/printvault-viewer.php @@ -307,53 +307,51 @@ function zToColor(z, minZ, maxZ) { document.getElementById('viewer-loading-text').textContent = 'Chargement des trajectoires…'; -fetch('/modules/printvault/api.php?action=gcode_paths&id=&max=300000', { +document.getElementById('viewer-loading-text').textContent = 'Parsing GCode…'; + +fetch('/modules/printvault/api.php?action=gcode_paths&id=', { credentials: 'same-origin', headers: {'X-Requested-With':'XMLHttpRequest','Accept':'application/json'} }) .then(r => r.json()) .then(j => { if (!j.ok) { document.getElementById('viewer-loading-text').textContent = j.error; return; } - const {segments, min_z, max_z} = j.data; + const {flat, min_z, max_z, total} = j.data; - // Separate extrusion and travel moves - const extPositions = []; - const extColors = []; - const travelPositions = []; + document.getElementById('viewer-loading-text').textContent = 'Construction du rendu…'; - segments.forEach(([x1,y1,z1, x2,y2,z2, ext]) => { + // flat = [x1,y1,z1,x2,y2,z2,ext, x1,y1,z1,...] stride 7 + const extPos=[], extCol=[], travPos=[]; + for (let i=0; i < flat.length; i+=7) { + const x1=flat[i],y1=flat[i+1],z1=flat[i+2]; + const x2=flat[i+3],y2=flat[i+4],z2=flat[i+5]; + const ext=flat[i+6]; if (ext) { const col = zToColor(z1, min_z, max_z); - extPositions.push(x1,z1,-y1, x2,z2,-y2); // swap Y/Z for Three.js - extColors.push(col.r,col.g,col.b, col.r,col.g,col.b); + extPos.push(x1,z1,-y1, x2,z2,-y2); + extCol.push(col.r,col.g,col.b, col.r,col.g,col.b); } else { - travelPositions.push(x1,z1,-y1, x2,z2,-y2); + travPos.push(x1,z1,-y1, x2,z2,-y2); } - }); + } const group = new THREE.Group(); - - if (extPositions.length) { + if (extPos.length) { const geo = new THREE.BufferGeometry(); - geo.setAttribute('position', new THREE.Float32BufferAttribute(extPositions, 3)); - geo.setAttribute('color', new THREE.Float32BufferAttribute(extColors, 3)); - const mat = new THREE.LineBasicMaterial({vertexColors: true, linewidth: 1}); - group.add(new THREE.LineSegments(geo, mat)); + geo.setAttribute('position', new THREE.Float32BufferAttribute(extPos, 3)); + geo.setAttribute('color', new THREE.Float32BufferAttribute(extCol, 3)); + group.add(new THREE.LineSegments(geo, new THREE.LineBasicMaterial({vertexColors:true}))); } - if (travelPositions.length) { + if (travPos.length) { const geo = new THREE.BufferGeometry(); - geo.setAttribute('position', new THREE.Float32BufferAttribute(travelPositions, 3)); - const mat = new THREE.LineBasicMaterial({color: 0x334155, linewidth: 1, transparent: true, opacity: 0.3}); - group.add(new THREE.LineSegments(geo, mat)); + geo.setAttribute('position', new THREE.Float32BufferAttribute(travPos, 3)); + group.add(new THREE.LineSegments(geo, new THREE.LineBasicMaterial({color:0x334155,transparent:true,opacity:0.25}))); } scene.add(group); fitCamera(group); document.getElementById('viewer-loading').style.display = 'none'; - - const total = segments.length; - const extCount = segments.filter(s=>s[6]).length; - document.getElementById('viewer-loading-text').textContent = `${total.toLocaleString()} segments (${extCount.toLocaleString()} extrusion)`; + document.getElementById('viewer-loading-text').textContent = `${total.toLocaleString()} segments`; }) .catch(err => { document.getElementById('viewer-loading-text').textContent = 'Erreur: '+err.message; });