Skip to content

Instantly share code, notes, and snippets.

@jdegenstein
Last active July 19, 2022 17:58
Show Gist options
  • Save jdegenstein/125f0f59a82121135b7812d0a313aacb to your computer and use it in GitHub Desktop.
Save jdegenstein/125f0f59a82121135b7812d0a313aacb to your computer and use it in GitHub Desktop.
CadQuery assembly of a Soma Cube Puzzle using constraints
import cadquery as cq
from random import randrange as rrr
from random import seed
#Soma set consists of 7 separate pieces
# 4 pieces can be x-y plane only, other 3 require x-y-z
#keep the same pseudo random colors later:
seed(5)#keep colors run-to-run
#(3,4,5,77,777,51221,512796321 are good seeds)
def arnco(u = 100, l = 10, cfloat=False):
if cfloat: #for two output types depending on need
return ((rrr(l,u)/255),(rrr(l,u)/255),(rrr(l,u)/255),1.0)
return {"alpha": 0.1,"color": (rrr(l,u),rrr(l,u),rrr(l,u))}
cb_w = 12 #cube size
chmf = 1 #chamfer
def scube():
return cq.Workplane().box(cb_w,cb_w,cb_w)
def convtToXYZpt(cenc): #convert cube position encoding to actual xyz points
arr = []
for id1,i in enumerate(cenc):
for id2,j in enumerate(i):
if j==1 and id1==0: #y=0
arr.append((id2*cb_w,0,0))
elif j==1 and id1==1: #y=1
arr.append((id2*cb_w,1*cb_w,0))
elif j==1 and id1==2: #z=1
arr.append((id2*cb_w,0,1*cb_w))
return arr
def mcube(cenc):
f1 = (
cq.Workplane()
.pushPoints(convtToXYZpt(cenc))
.eachpoint(lambda loc: scube().val().moved(loc), combine="a")
.edges()
.chamfer(chmf)
)
return f1
#cube position encoding
#x runs from L to R of each row
#row1 is y=0,z=0
#row2 is y=1,z=0
#row3 is y=0,z=1
#lower case L
c0 = [(1,1,0),
(1,0,0),
(0,0,0)]
#upper case L
c1 = [(1,1,1),
(1,0,0),
(0,0,0)]
#tee
c2 = [(1,1,1),
(0,1,0),
(0,0,0)]
#zee
c3 = [(1,1,0),
(0,1,1),
(0,0,0)]
#corner (xyz)
c4 = [(1,1,0),
(1,0,0),
(1,0,0)]
#RH (xyz)
c5 = [(1,1,0),
(1,0,0),
(0,1,0)]
#LH (xyz)
c6 = [(1,1,0),
(0,1,0),
(1,0,0)]
cubes = [c0,c1,c2,c3,c4,c5,c6]
#the following commented code will display all the pieces separately
# if "show_object" in locals():
# for idx,val in enumerate(cubes):
# show_object(mcube(cubes[idx])
# .translate((0,5*cb_w+idx*2.5*cb_w,0)),
# options=arnco()
# )
def XYPL():
return cq.Workplane().rect(75,75).extrude(-1)
def bigL():#big
rv = mcube(cubes[1]).rotate((0,0,0),(0,1,0),-90)
rv.faces(">Z[1]").tag("Z1").end()
rv.faces("<Z").tag("Z").end()
rv.faces(">Y").tag("Y").end()
rv.faces(">Y[1]").tag("Y1").end()
rv.faces(">X").tag("X").end()
return rv
def littleL():#littleL
rv = mcube(cubes[0])
rv.faces(">X").tag("X").end()
rv.faces("<X").tag("lX").end()
rv.faces(">X[1]").tag("X1").end()
rv.faces(">Y[1]").tag("Y1").end()
rv.faces(">Z").tag("Z").end()
return rv
def corner(): #corner
rv = mcube(cubes[4])
return rv
def LHS(): #LHS
rv = mcube(cubes[6])
return rv
def zee(): #zee
rv = mcube(cubes[3])
return rv
def tee(): #tee
rv = mcube(cubes[2])
return rv
def RHS(): #RHS
rv = mcube(cubes[5])
return rv
soma = (
cq.Assembly()
.add(XYPL(),name="XYPL", color=cq.Color(*arnco(cfloat=True)))
.add(bigL(),name="bigL", color=cq.Color(*arnco(cfloat=True)))
.add(littleL(),name="littleL", color=cq.Color(*arnco(cfloat=True)))
.add(LHS(),name="LHS", color=cq.Color(*arnco(cfloat=True)))
.add(zee(),name="zee", color=cq.Color(*arnco(cfloat=True)))
.add(tee(),name="tee", color=cq.Color(*arnco(cfloat=True)))
.add(corner(),name="corner", color=cq.Color(*arnco(cfloat=True)))
.add(RHS(),name="RHS", color=cq.Color(*arnco(cfloat=True)))
)
(
soma
.constrain("XYPL","Fixed")
.constrain("bigL?Z","XYPL@faces@>Z", "Axis")
.constrain("bigL?Z","FixedRotation",(0,0,0))
.constrain("bigL?Z","FixedPoint",(-cb_w,-cb_w/2,0))
.constrain("littleL@faces@>Y","XYPL@faces@>Z", "PointInPlane")
.constrain("littleL?X","bigL?Y1", "Axis")
.constrain("littleL?X1","bigL?Y", "Plane")
.constrain("littleL?Y1","bigL?Z1", "Plane")
.constrain("LHS@faces@<Z","XYPL@faces@>Z", "Axis")
#.constrain("LHS@faces@<Y","littleL@faces@<X", "Axis", param=0)
.constrain("LHS@faces@>Z[1]","tee@faces@>Y", "PointInPlane")
.constrain("LHS@faces@>Y[1]","zee@faces@>Z", "PointInPlane")
.constrain("LHS@faces@>Y","zee@faces@<Z", "Axis", param=0)
#.constrain("LHS@faces@>Y","littleL@faces@>X", "Axis", param=0)
.constrain("LHS@faces@>X","tee@faces@>X[1]", "PointInPlane")
.constrain("zee@faces@>Y[1]","littleL@faces@<Y", "Axis")
.constrain("zee@faces@>Y[1]","littleL@faces@<Y", "PointInPlane")
.constrain("zee@faces@>X[1]","littleL@faces@>Z", "Axis")
.constrain("zee@faces@>X[1]","littleL@faces@>Z", "PointInPlane")
.constrain("zee@faces@<Z","bigL@faces@>Y[1]", "PointInPlane")
.constrain("tee@faces@>Y[1]","littleL@faces@<Y", "Axis")
.constrain("tee@faces@>Y[1]","littleL@faces@<Y", "PointInPlane")
.constrain("tee@faces@>X[1]","littleL@faces@>Z", "PointInPlane")
.constrain("tee@faces@<Z","zee@faces@>Z", "Axis")
.constrain("tee@faces@<Z","zee@faces@>Z", "PointInPlane")
.constrain("corner@faces@<Z","XYPL@faces@>Z", "PointInPlane")
.constrain("corner@faces@<X","bigL@faces@<Y", "Axis", param=0)
.constrain("corner@faces@<Y","LHS@faces@<X", "Axis", param=0)
.constrain("corner@faces@>X[1]","zee@faces@<Z", "PointInPlane")
.constrain("corner@faces@>Y","bigL@faces@>X", "PointInPlane")
.constrain("RHS@faces@<Z","bigL@faces@>Z", "Axis", param=0)
#.constrain("RHS@faces@<Y","bigL@faces@<Y", "Axis", param=0)
.constrain("RHS@faces@<X","tee@faces@>X", "Axis", param=0)
.constrain("RHS@faces@>Z[1]","corner@faces@>Z", "PointInPlane")
.constrain("RHS@faces@>X[1]","zee@faces@<X[1]", "PointInPlane")
.constrain("RHS@faces@>Y[1]","zee@faces@<Z", "PointInPlane")
)
soma.solve()
show_object(soma,options=arnco())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment