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
You can’t perform that action at this time.