Skip to content

Instantly share code, notes, and snippets.

@dakerfp
Last active March 28, 2022 19:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dakerfp/4328defcc0f756cee807bb6827e80ff2 to your computer and use it in GitHub Desktop.
Save dakerfp/4328defcc0f756cee807bb6827e80ff2 to your computer and use it in GitHub Desktop.
import Part
import FreeCAD
from FreeCAD import Base
TABLETOP_SLACK = 1 # in
LEG_WIDTH = 1.5 # in
TABLE_HEIGHT = 3 * 12 # 3ft
BEAM_WIDTH = 3/4 # in
BEAM_HEIGHT = 1.5 # in
doc = FreeCAD.newDocument()
def faceCloserTo(shape, to):
return min(shape.Faces, key=lambda f: to.distanceToPoint(f.CenterOfMass))
def vertexIsOnGround(v):
return v.Point.z == 0
def pointsShrinkToLength(a, b, length):
v = (b - a).normalize()
d = a.distanceToPoint(b)
shift = v * ((d - length) / 2)
return a + shift, b - shift
def createTabletop(h=TABLE_HEIGHT, width=3*12, depth=14, thickness=3/4, slack=TABLETOP_SLACK):
return Part.makeBox(width, depth, thickness, Base.Vector(0, 0, h))
def createLeg(name, x=0, y=0, h=TABLE_HEIGHT, w=LEG_WIDTH):
return Part.makeBox(w, w, h, Base.Vector(x, y))
def makeBoxFromPoints(p1, p2, p3, p4, height):
L1 = Part.LineSegment(p1, p2)
L2 = Part.LineSegment(p2, p3)
L3 = Part.LineSegment(p3, p4)
L4 = Part.LineSegment(p4, p1)
bottomWire = Part.Wire(Part.Shape([L1, L2, L3, L4]).Edges)
bottom = Part.Face(bottomWire)
up = Base.Vector(0, 0, height)
box = bottom.extrude(up)
return box
def createBeam(legA, legB, z=0):
f1 = faceCloserTo(legA, legB.CenterOfMass)
f2 = faceCloserTo(legB, legA.CenterOfMass)
pf1 = [v.Point for v in f1.Vertexes if vertexIsOnGround(v)]
pf2 = [v.Point for v in f2.Vertexes if vertexIsOnGround(v)]
p1, p2 = pointsShrinkToLength(pf1[0], pf1[1], BEAM_WIDTH)
p4, p3 = pointsShrinkToLength(pf2[0], pf2[1], BEAM_WIDTH)
beam = makeBoxFromPoints(p1, p2, p3, p4, BEAM_HEIGHT) # XXX
beam.translate(Base.Vector(0, 0, z))
return beam
def createShelf():
b1 = createBeam(leg1, leg2)
class shelf:
def __init__(self, beams):
self.beams = beams
class table(object):
def __init__(self, height=TABLE_HEIGHT, width=3*12, depth=14, leg_width=LEG_WIDTH, tabletop_slack=TABLETOP_SLACK, tabletop_thickness=3/4, beam_height=BEAM_HEIGHT, beam_width=BEAM_WIDTH):
self.tabletop = createTabletop(height, width=width, depth=depth, slack=tabletop_slack, thickness=tabletop_thickness)
xmin = tabletop_slack
xmax = self.tabletop.BoundBox.XMax - leg_width - tabletop_slack
ymin = tabletop_slack
ymax = self.tabletop.BoundBox.YMax - leg_width - tabletop_slack
self.leg1 = createLeg("leg1", xmin, ymin, height, leg_width)
self.leg2 = createLeg("leg2", xmin, ymax, height, leg_width)
self.leg3 = createLeg("leg3", xmax, ymax, height, leg_width)
self.leg4 = createLeg("leg4", xmax, ymin, height, leg_width)
self.shelf1 = self.makeShelf(4)
self.shelf2 = self.makeShelf(4 + 16)
self.shelf3 = self.makeShelf(height - beam_height)
def makeShelf(self, z):
return shelf([
createBeam(self.leg1, self.leg2, z),
createBeam(self.leg2, self.leg3, z),
createBeam(self.leg3, self.leg4, z),
createBeam(self.leg4, self.leg1, z),
])
def legs(self):
return [self.leg1, self.leg2, self.leg3, self.leg4]
def parts(self):
return [self.tabletop] + \
self.legs() + \
self.shelf1.beams + \
self.shelf2.beams + \
self.shelf3.beams
def show_table(t):
for p in t.parts():
Part.show(p)
# BOM
def show_bills_of_material(parts, initial_offset=Base.Vector(0, 0), offset=2):
parts = sorted(parts, key=lambda p: p.Volume)
for i, p in enumerate(parts):
bb = p.BoundBox
if i == 0:
p.translate(-bb.getPoint(4) + initial_offset)
else:
pbb = parts[i - 1].BoundBox
offsetVector = Base.Vector(0, offset)
p.translate(pbb.getPoint(7) -bb.getPoint(4) + offsetVector)
Part.show(p)
t = table()
show_table(t)
show_bills_of_material(t.parts(), initial_offset=Base.Vector(40, 0))
# workbench = table(width=6*12, depth=2*12, leg_width=3.5, tabletop_thickness=2.5)
# show_table(workbench)
# show_bills_of_material(workbench.parts(), initial_offset=Base.Vector(80, 0), offset=3)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment