Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Parametric Aluminum Extrusion Module
import math
from FreeCAD import Base
#Main class for general extrusion related methods
class ExtrusionProfile():
def __init__(self, profile):
self.profile = profile
def makeExtrusion(self, p1, p2, rotateAngle=0):
"""Generates an extrusion which connects between two points,
points represent the center of the face of each end
profile is a filled face, and p1,p2 are Vectors representing points in 3D space
rotateAngle specifies the amount to rotate about the extrusion axis after orienting the face"""
dir = p2.sub(p1)
normal = Base.Vector(0,0,1) # current assumed normal of profile face (restricted to the XY plane)
cross = dir.cross(normal)
angle = math.degrees(dir.getAngle(normal))
profile = self.profile.copy()
if cross.x != 0 or cross.y !=0 or cross.z != 0:
profile.rotate(p1, cross, -angle)
extrusion = profile.extrude(dir)
extrusion.rotate(p1, dir, rotateAngle)
return extrusion
# A simple profile that mimics the extrusion type used in default MendelMax
class BasicExtrusionProfile(ExtrusionProfile):
def __init__(self, size=20.0, edgeThickness=2.0, diagonalThickness=1.5, slotWidth=6.0, centerBore=4.2, centerWidth=8.0):
s2 = size / 2.0
sw2 = slotWidth / 2.0
cw2 = centerWidth / 2.0
dt2 = math.sqrt(2.0) * diagonalThickness / 2.0
# define 1/8 of the points, this works similarly to Midpoint circle algorithm taking advantage of all the symmetry in the extrusion face to avoid hardcoding many point values
points = [
Base.Vector(cw2, cw2 - dt2),
Base.Vector(s2 - edgeThickness, s2 - (edgeThickness + dt2)),
Base.Vector(s2 - edgeThickness, sw2),
Base.Vector(s2, sw2)
# symmetry across "y = x"
mirror = [Base.Vector(p.y, p.x) for p in reversed(points)]
points.append(Base.Vector(size/2.0, size/2.0)) # corner point
points.extend([Base.Vector(-p.x, p.y) for p in reversed(points)]) # X axis symmetry
points.extend([Base.Vector(p.x, -p.y) for p in reversed(points)]) # Y axis symmetry
# convert list of vertices to a face
face = Part.makeFilledFace(Part.makePolygon(points).Edges)
# cut out the circle
c = Part.makeCircle(centerBore / 2.0)
c = Part.makeFilledFace(c.Edges)
face = face.cut(c)
self.profile = face
# Solid square bar(for use in boolean cut operations)
class SolidSquareExtrusionProfile(ExtrusionProfile):
def __init__(self, size=20.0):
s2 = size / 2.0
poly = Part.makePolygon([
self.profile = Part.makeFilledFace(poly.Edges)
class MendelMax():
ExtrusionProfiles = {
"2020": { # similar dimensions to a commonly used vendor. Don't su mi!
'size': 20.0,
'edgeThickness': 2.0,
'diagonalThickness': 1.5,
'slotWidth': 6.0,
'centerBore': 4.2,
'centerWidth': 8.0,
def __init__(self, extrusion_profile="2020", extrusion_x_length=300.0, extrusion_y_length=340.0 , extrusion_diagonal_length=420.0):
self.extrusion_profile = BasicExtrusionProfile(MendelMax.ExtrusionProfiles[extrusion_profile])
self.extrusion_x_length = extrusion_x_length
self.extrusion_y_length = extrusion_y_length
self.extrusion_diagonal_length = extrusion_diagonal_length
#generated dimensions
self.extrusion_x_top_length = extrusion_x_length + 120.0
#Extrusion lengths aren't exactly the same as the lengths of the triangle geometry that defines the frame angle
#self.triangle_diagonal_length = self.extrusion_diagonal_length +
def makeInPlaceExtrusions(self):
profile = BasicExtrusionProfile()
x = profile.makeExtrusion(Base.Vector(0,0,0), Base.Vector(0,0,30))
#cutterProfile = SolidSquareExtrusionProfile(10)
#y = cutterProfile.makeExtrusion(Base.Vector(-30, 0, 10),Base.Vector(30, 0, 10) )
#x = x.cut(y) # not sure why this line doesn't work. FreeCAD bug?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment