Error al mover el archivo.'; exit; } $cmd = "node /var/www/html/runPrusa.js " . escapeshellarg($stlPath); exec($cmd, $output, $return_var); if ($return_var !== 0 || empty($output)) { echo '
Error al generar G-code:
' . implode("
", $output) . '
'; exit; } $result = json_decode($output[0], true); if (!$result) { echo '
No se pudo leer la información del G-code.
'; exit; } // Capturamos el nombre del STL final (por si hubo conversión) $nombreArchivoFinal = $result['finalStl'] ?? basename($stlPath); // Datos del archivo $margen = 0.10; $filamento_mm = $result['filamentUsedMm'] ?? 0; $filamento_cm3 = $result['filamentUsedCm3'] ?? 0; $tiempo_estimado = $result['estimatedTime'] ?? "0h 0m 0s"; $filamento_mm_seg = $filamento_mm * (1 + $margen); $filamento_cm3_seg = $filamento_cm3 * (1 + $margen); $tiempo_seg = ajustarTiempo($tiempo_estimado, $margen); $impresoraSeleccionada = $_POST['marca'] ?? 'markforged'; $materialSeleccionado = $_POST['material'] ?? 'pla'; include 'calculo_precio.php'; $cotizacion = calcularCotizacionImpresion( $filamento_cm3_seg, convertirTiempoAHoras($tiempo_seg), $materialSeleccionado, $impresoraSeleccionada ); // --- MOSTRAR RESULTADOS --- echo '

COTIZACIÓN ESTIMADA

Impresora:
' . htmlspecialchars(ucfirst($impresoraSeleccionada)) . '
Material:
' . htmlspecialchars(ucfirst($materialSeleccionado)) . '
Concepto Importe
Costo del Material $' . number_format($cotizacion['costo_material'], 2) . '
Costo del Tiempo $' . number_format($cotizacion['costo_tiempo'], 2) . '
Subtotal de Producción $' . number_format($cotizacion['subtotal_produccion'], 2) . '
Consumible de Impresión $' . number_format($cotizacion['consumible_impresion'], 2) . '
Concepto Importe
Costo de Operación $' . number_format($cotizacion['costo_operacion'], 2) . '
Subtotal de Operación $' . number_format($cotizacion['subtotal_operacion'], 2) . '
Costo Final $' . number_format($cotizacion['costo_final_impresion'], 2) . '
Indirectos $' . number_format($cotizacion['indirectos'], 2) . '

Precio Final Estimado:

$' . number_format($cotizacion['precio_final'], 2) . ' MXN

  Descargar G-code

'; // ========= 2. BLOQUE DE ACORDEONES ========= echo '

  • Filamento usado: ' . number_format($filamento_mm, 2) . ' mm
  • Volumen usado: ' . number_format($filamento_cm3, 2) . ' cm³
  • Tiempo estimado: ' . htmlspecialchars($tiempo_estimado) . '
  • Filamento (seguridad): ' . number_format($filamento_mm_seg, 2) . ' mm
  • Volumen (seguridad): ' . number_format($filamento_cm3_seg, 2) . ' cm³
  • Tiempo (seguridad): ' . htmlspecialchars($tiempo_seg) . '
'; // --- FIN DEL BLOQUE REEMPLAZADO --- // === VISUALIZADOR 3D === echo '

VISUALIZADOR

Controles del Visor 3D

'; // === DIV OCULTO $stlUrl = 'uploads/' . htmlspecialchars($nombreArchivoFinal); echo ''; } else { echo '
No se recibió un archivo STL válido.
'; } } else { echo '
Método no permitido.
'; } // --- FUNCIONES AUXILIARES --- function ajustarTiempo($tiempo_str, $porcentaje) { preg_match_all("/(\\d+)([hms])/", $tiempo_str, $matches, PREG_SET_ORDER); $segundos = 0; foreach ($matches as $match) { $valor = (int)$match[1]; switch ($match[2]) { case "h": $segundos += $valor * 3600; break; case "m": $segundos += $valor * 60; break; case "s": $segundos += $valor; break; } } $segundos_ajustados = round($segundos * (1 + $porcentaje)); $horas = intdiv($segundos_ajustados, 3600); $minutos = intdiv($segundos_ajustados % 3600, 60); $segundos_final = $segundos_ajustados % 60; return "{$horas}h {$minutos}m {$segundos_final}s"; } function convertirTiempoAHoras($tiempo_str) { preg_match_all("/(\\d+)([hms])/", $tiempo_str, $matches, PREG_SET_ORDER); $horas = 0; foreach ($matches as $match) { $valor = (int)$match[1]; switch ($match[2]) { case "h": $horas += $valor; break; case "m": $horas += $valor / 60; break; case "s": $horas += $valor / 3600; break; } } return $horas; } ?>