Somebody once made a "Lego.py". I found this in my files, but I can't find the original post. It's very slow.
Code: Select all
import FreeCAD,Part,math
class Lego:
'''return a lego brick'''
def __init__(self,obj, unitsX=4, unitsY=2,unitsZ=1,modifier=0):
obj.addProperty("App::PropertyInteger","unitsX","Lego","Size in knobs in X direction.").unitsX = unitsX
obj.addProperty("App::PropertyInteger","unitsY","Lego","Size in knobs in Y direction.").unitsY = unitsY
obj.addProperty("App::PropertyInteger","unitsZ","Lego","Size in knobs in Z direction.").unitsZ = unitsZ
obj.addProperty("App::PropertyInteger","modifier","Lego","Variant No ").modifier = modifier
obj.Proxy = self
def onChanged(self, fp, prop):
"Do something when a property has changed"
pass
def execute(self, fp):
fp.Shape=Lego.buildshape(fp.unitsX, fp.unitsY, fp.unitsZ,fp.modifier)
@staticmethod
def buildshape(unitsX, unitsY,unitsZ,modifier):
gap=0.1
gaps=2*gap
unitSize = 8
height=9.6
knobHeight=1.8
knobRadius=4.8/2
wall=1.5
upWall=5.5 #// guessed
supportthickness=0.6 # 0.15x4 or 0.20x3
maxsupportlayerthickness=0.15
supportdistance=4 # 4x4=16mm^2, printer option
cylRadius = (unitSize*math.sqrt(2)-2*knobRadius)/2 #0000003,2568542494923801952067548968388
cylWall = round(3.25685,5)
l=unitSize*unitsX-gaps
w= unitSize*unitsY-gaps
c1=Part.makeBox(l, w, height,FreeCAD.Vector(-l/2.0,-w/2.0,0))
c2=Part.makeBox(l-gaps-2*wall, w-gaps-2*wall, height,FreeCAD.Vector(-(l-gaps-2*wall)/2.0,-(w-gaps-2*wall)/2.0,-1*upWall))
d1=c1.cut(c2)
shape1=d1 # box
knobs=Part.Shape()
# shape1=Part.Shape()#makeBox(1,1,1)
knob=Part.makeCylinder(knobRadius,knobHeight+upWall/2,FreeCAD.Vector(0,0,height-upWall/2.0))
for x in range(unitsX):
for y in range(unitsY):
newknob=knob.copy()
newknob.translate((x*unitSize, y*unitSize, 0))
if knobs.isNull():
knobs=newknob
else:
knobs=knobs.fuse(newknob)
knobs.translate(((1-unitsX)*unitSize/2, (1-unitsY)*unitSize/2, 0))
if (unitsX > 1 and unitsY > 1)or(modifier==-1):
cyl=Part.makeCylinder(cylRadius,height-upWall/2 ).cut(Part.makeCylinder(cylRadius-cylWall,height))
cyl.translate((0,0,upWall/8))
cyls=Part.Shape()
for x in range(unitsX-1):
for y in range(unitsY-1):
newcyl=cyl.copy()
newcyl.translate((x*unitSize, y*unitSize, 0))
if cyls.isNull():
cyls=newcyl
else:
cyls=cyls.fuse(newcyl)
cyls.translate(((2-unitsX)*unitSize/2, (2-unitsY)*unitSize/2, 0))
if modifier==2: #
newknobs=knobs.copy() #
newknobs.translate((0,0,height*unitsZ-height)) #
shape1=shape1.fuse(newknobs) #
# return shape1 #
for x in my_range(1,unitsX,2):
zmodifier=0
if modifier<=0:
zmodifier=0
else:
zmodifier=1
carrycy =Part.makeCylinder(unitSize/2,height*unitsZ-height ) # height+ # *(1-zmodifier)
carrycy.translate((unitSize*unitsX/2-x*unitSize,-unitSize/2-wall,height))
wallnearwallbase=Part.makeBox(l, w, height,FreeCAD.Vector(-l/2.0,-w/2.0+unitSize*unitsY,0)) #-wall*(1-zmodifier)
wallnearwall=Part.makeBox(l-gaps-2*wall, w-gaps-2*wall, height,FreeCAD.Vector(-(l-gaps-2*wall)/2.0,-(w-gaps-2*wall)/2.0+unitSize*unitsY,-1*upWall))
shape1=shape1.fuse(carrycy) # carry cylynder
wallnearwallbase=wallnearwallbase.cut(wallnearwall)#knobs=knobs.cut(wallnearwall)
wallnearwallbase.translate((0,-unitSize*unitsY,height*unitsZ-height))
if zmodifier==0:
shape1=shape1.cut(wallnearwallbase)#knobs=knobs.cut(wallnearwall)
else:
shape1=shape1.fuse(wallnearwallbase)#knobs=knobs.cut(wallnearwall)
# else:
c1_=Part.makeBox(l, wall, height*unitsZ,FreeCAD.Vector(-l/2.0,-w/2.0-wall*2,0))
c2_=Part.makeBox(l, wall, height,FreeCAD.Vector(-l/2.0,-w/2.0-wall,0))
shape1=shape1.fuse(c2_) # side panel base
shape1=shape1.fuse(c1_) # side panel
#.fuse(c1_)
shape1=shape1.fuse(knobs)#
shape1=shape1.fuse(cyls)#.removeSplitter() #
# shape=shape.fuse(shape1)
# shape=knobs.fuse(d1).removeSplitter()
else:
shape1=knobs.fuse(d1).removeSplitter()
#Part.show(d1.common(cyls))
for x in my_range(1,unitsX*unitSize,supportdistance): #
origvector=FreeCAD.Vector(-l/2.0+x,-w/2.0-1,-2*supportthickness)
support=Part.makeBox(supportthickness,w+2,height-upWall-maxsupportlayerthickness+2*supportthickness,origvector)
support1=Part.makeBox(supportthickness/2,w+2,height-upWall+2*supportthickness,origvector)
xoffset=0
yoffset=0
for ttranslation in range(1,9): # [1,2,3,4,5,6,7,8]
if ttranslation==1:
xoffset=0
yoffset=1
elif ttranslation==2:
xoffset=1
yoffset=0
elif ttranslation==3:
xoffset=1
yoffset=1
elif ttranslation==4:
xoffset=-1
yoffset=1
elif ttranslation==5:
xoffset=-1
yoffset=-1
elif ttranslation==6:
xoffset=-1
yoffset=0
elif ttranslation==7:
xoffset=0
yoffset=-1
elif ttranslation==8:
xoffset=1
yoffset=-1
# elif ttranslation==2:
# xoffset=1
# elif ttranslation==2:
# xoffset=1
zOffset = 0.0001
support.translate((+xoffset,+yoffset,zOffset)) ########################## here
support1.translate((+xoffset,+yoffset,zOffset)) #
support=support.cut(shape1)
support1=support1.cut(shape1)
support.translate((-xoffset,-yoffset,zOffset)) #
support1.translate((-xoffset,-yoffset,zOffset)) #
shape1=shape1.fuse(support)
shape1=shape1.fuse(support1)
return shape1
def my_range(start, end, step):
while start <= end:
yield start
start += step
def makeLego(x,y,z,modifier,doc=None):
doc = doc or FreeCAD.ActiveDocument
obj=doc.addObject("Part::FeaturePython","Lego")
Lego(obj)
obj.unitsX=x
obj.unitsY=y
obj.unitsZ=z
obj.modifier=modifier
obj.ViewObject.Proxy=0 # just set it to something different from None (this assignment is needed to run an internal notification)
return obj
if __name__ == '__main__':
#nonparametric
#Part.show(Lego.buildshape(4,2))
#parametric
# modifier -1 - mono rail
# modifier 0 - -1 wall
# modifier 1 - full mono wall, upper solid
makeLego(8,2,6,2)
# makeLego(8,2)
# makeLego(16,2)