slicer_utils.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import subprocess
  2. import os
  3. import re
  4. import logging
  5. import shutil
  6. from config import SLICER_PATH, SLICER_CONFIG
  7. logger = logging.getLogger(__name__)
  8. def slice_model(file_path: str):
  9. """
  10. Runs PrusaSlicer CLI to extract the EXACT 3D volume of the STL/OBJ file using --info.
  11. Returns a dict with estimated print_time (str) and filament_used (g).
  12. """
  13. if not shutil.which(SLICER_PATH):
  14. logger.error(f"Slicer not found at {SLICER_PATH}")
  15. return None
  16. cmd = [
  17. SLICER_PATH,
  18. "--info",
  19. file_path
  20. ]
  21. try:
  22. # Run info extraction (very fast, no full G-code generation)
  23. process = subprocess.run(cmd, capture_output=True, text=True, check=True)
  24. content = process.stdout
  25. # Regex to find volume in mm3
  26. # Format: volume = 87552.437500
  27. volume_match = re.search(r"volume\s*=\s*([\d\.]+)", content)
  28. if not volume_match:
  29. logger.error("Volume could not be parsed from PrusaSlicer output.")
  30. return None
  31. volume_mm3 = float(volume_match.group(1))
  32. volume_cm3 = volume_mm3 / 1000.0
  33. # Estimate weight assuming average density of PLA/PETG (~1.25 g/cm3)
  34. filament_g = round(volume_cm3 * 1.25, 2)
  35. # Estimate printing time assuming average volumetric flow rate of ~10 mm3/s
  36. # (This is a very realistic average for standard 0.4mm nozzle including travel/supports)
  37. time_seconds = int(volume_mm3 / 10.0)
  38. hours = time_seconds // 3600
  39. minutes = (time_seconds % 3600) // 60
  40. if hours > 0:
  41. time_str = f"{hours}h {minutes}m"
  42. else:
  43. time_str = f"{minutes}m"
  44. return {
  45. "filament_g": filament_g,
  46. "print_time_str": time_str,
  47. "success": True
  48. }
  49. except subprocess.CalledProcessError as e:
  50. logger.error(f"Slicing info error: {e.stderr}")
  51. return None
  52. except Exception as e:
  53. logger.error(f"General error in slice_model: {e}")
  54. return None