Indeed a nice challenge. I only tested on a much simpler Part, but this script should work and hold all your constraints. Select the part and run it.
Note: You likely need to rotate your part. The foam mats in my script have their opening always in z direction. So if this is wrong for your part just rotate it.
Code: Select all
import Part
#get the shape to slice
shape = Gui.Selection.getSelection()[0].Shape
#parameters
thickness = 2; #thickness of foam
slices = 11; #number of slices
#needed boiler plate: Bounding box and side faces
bbox = shape.BoundBox;
extbox = Part.makeBox(bbox.XLength*1.2, bbox.YLength*1.2, bbox.ZLength*1.2)
extbox.translate(bbox.Center - extbox.CenterOfMass);
rightFace = extbox.Faces[2]
leftFace = extbox.Faces[3]
for x in range(0, slices):
#build the foam slice we want to use
foam = Part.makeBox(thickness, bbox.YLength*1.2, bbox.ZLength*1.2);
foam.translate(App.Vector(bbox.XMin + bbox.XLength/slices*x, bbox.Center.y - foam.CenterOfMass.y, bbox.Center.z - foam.CenterOfMass.z));
bface = foam.Faces[0];
#get the part sections that needs to be handled by that slice
section = foam.common(shape);
#we need to handle each solid seperate
for solid in section.Solids:
#get the needed largest needed outline by projecting all faces
projections = [];
for face in solid.Faces:
edges = bface.project([face]);
face = Part.Face(Part.Wire(edges.Edges));
projections.append(face);
projection = projections[0].multiFuse(projections);
projection = projection.removeSplitter();
outline = projection.Faces[0].OuterWire;
#find the left- and rightmost points in the outline and ensure that we have verices there
def splitEdges ( outline, dist ):
if dist[2][0][3] == 'Edge':
e = outline.Edges[dist[2][0][4]];
edges = outline.Edges;
del edges[dist[2][0][4]]
split = e.split(dist[2][0][5]);
edges += split.Edges;
vertex = split.Vertexes[1];
return (Part.Wire(edges), vertex);
return (outline, outline.Vertexes[dist[2][0][4]])
res = splitEdges(outline, rightFace.distToShape(outline));
v1 = res[1];
res = splitEdges(res[0], leftFace.distToShape(res[0]));
v2 = res[1];
outline = res[0];
#build extension lines to ensure we cut out the whole foam
e = [];
e.append( Part.Edge(Part.Line(v1.Point, v1.Point + App.Vector(0,0,bbox.ZLength))) );
e.append( Part.Edge(Part.Line(v1.Point + App.Vector(0,0,bbox.ZLength), v2.Point + App.Vector(0,0,bbox.ZLength))) );
e.append( Part.Edge(Part.Line(v2.Point + App.Vector(0,0,bbox.ZLength), v2.Point)) );
#find a set of outline edges between the vertices: it doesnt matter which path of the two possibles
def getNextEdge(edges, vertex):
for edge in edges:
if (edge.Vertexes[0].Point - vertex.Point).Length < 1e-4:
edges.remove(edge);
return (edge, edge.Vertexes[1]);
if (edge.Vertexes[1].Point - vertex.Point).Length < 1e-4:
edges.remove(edge);
return (edge, edge.Vertexes[0]);
edges = outline.Edges;
res = getNextEdge(edges, v2);
e.append(res[0]);
while edge and ((res[1].Point - v1.Point).Length > 1e-4):
res = getNextEdge(edges, res[1]);
e.append(res[0]);
#we are not sure we have build the real outer wire, we could have followed the wrong edge... brute forece again!
face = Part.Face(outline).fuse(Part.Face(Part.Wire(e)));
#build the cut shape and finaly cut the foam
hole = face.extrude(App.Vector(thickness, 0 ,0));
foam = foam.cut(hole).removeSplitter();
Part.show(foam)

- s.png (52.97 KiB) Viewed 3234 times

- s2.png (8.71 KiB) Viewed 3234 times

- s3.png (57.27 KiB) Viewed 3234 times