import FreeCAD as App import FreeCADGui as Gui import Part # ============================================================ # CONFIG # ============================================================ TARGET_X = 75.0 TARGET_Y = 75.0 TARGET_Z = 50.0 LAYER_THICKNESS = 2.5 # mm (card/MDF range) DEBUG_STEP_VISUALS = True # ============================================================ # LOG # ============================================================ def log(msg): App.Console.PrintMessage(str(msg) + "\n") # ============================================================ # GET OBJECT # ============================================================ sel = Gui.Selection.getSelection() if len(sel) == 0: raise Exception("Select a single solid first") obj = sel[0] if not hasattr(obj, "Shape"): raise Exception("Selected object has no Shape") shape = obj.Shape.copy() log("Selected: " + obj.Name) # ============================================================ # SCALE TO FIT BBOX # ============================================================ bb = shape.BoundBox sx = TARGET_X / bb.XLength sy = TARGET_Y / bb.YLength sz = TARGET_Z / bb.ZLength scale = min(sx, sy, sz) log("Scale factor: " + str(scale)) m = App.Matrix() m.scale(scale, scale, scale) shape = shape.transformGeometry(m) bb = shape.BoundBox log("Scaled bbox:") log(str(bb.XLength) + " x " + str(bb.YLength) + " x " + str(bb.ZLength)) # ============================================================ # CREATE OUTPUT DOC # ============================================================ doc = App.newDocument("SLICES_OUTPUT") # optional: copy scaled model for reference ref = doc.addObject("Part::Feature", "ScaledModel") ref.Shape = shape # ============================================================ # SLICING LOOP # ============================================================ z = bb.ZMin index = 0 while z <= bb.ZMax: log("Slice " + str(index) + " at Z=" + str(z)) # large plane for intersection plane = Part.makePlane( bb.XLength * 3, bb.YLength * 3, App.Vector(bb.XMin - bb.XLength, bb.YMin - bb.YLength, z) ) section = shape.section(plane) # IMPORTANT: section can be compound if section.isNull() or len(section.Edges) == 0: log(" empty slice") z += LAYER_THICKNESS index += 1 continue # store slice slice_obj = doc.addObject("Part::Feature", f"Slice_{index:03d}") slice_obj.Shape = section # visually offset slices in X so you can inspect them if DEBUG_STEP_VISUALS: slice_obj.Placement.Base = App.Vector(index * 5, 0, 0) log(" edges: " + str(len(section.Edges))) z += LAYER_THICKNESS index += 1 # ============================================================ # FINALIZE # ============================================================ doc.recompute() Gui.ActiveDocument.ActiveView.fitAll() log("DONE - generated " + str(index) + " slices")