import cadquery as cq
# dimensions of the tank
thickness = 0.1
dt = 10 - 2*thickness # diameter of tank less thickness of the shell
rt = dt/2 # radius of tank
ht = 20 # total height of tank cylindrical section
hht = ht / 2 # half the tank height
hd = 3 - thickness # height of dome
# colors
green = cq.Color("Green")
red = cq.Color("Red")
def make_tank(reverse_aft_dome: bool = False) -> cq.Workplane:
# create the starting plane from which to work
wp = cq.Workplane("XZ")
# trace one half of the perimeter then rotate
# start at lower-left corner above aft dome
tank = wp.move(xDist=rt, yDist=-hht)
# create the vertical wall of the cylinder
tank = tank.line(xDist=0, yDist=ht)
# create the forward dome. this ends at the center
# line of the tank
tank = tank.ellipseArc(
x_radius=rt,
y_radius=hd,
angle1=0.,
angle2=90.,
sense=1, # clockwise (-1) or counter clockwise (1)
)
# create a vertical line at center of the tank
tank = tank.line(xDist=0, yDist=-(ht+2*hd))
# create the aft dome, starting from the center line
if reverse_aft_dome:
tank = tank.ellipseArc(
x_radius=rt,
y_radius=hd,
angle1=0,
angle2=90.,
sense=-1 # clockwise (-1) or counter clockwise (1)
)
else:
tank = tank.ellipseArc(
x_radius=rt,
y_radius=hd,
angle1=-90,
angle2=0.,
sense=1, # clockwise (-1) or counter clockwise (1)
)
# mark the 2D shape as complete
tank = tank.close()
# revolve the shape 360 degrees to create the 3D geometry
tank = tank.revolve(360)
# finally, apply a thin shell
tank = tank.shell(thickness=thickness)
# tag EVERYTHING
tank.edges(">Z").tag("topedge")
tank.faces(">Z").tag("topface")
tank.vertices(">Z").tag("topvert")
tank.edges("<Z").tag("bottomedge")
tank.faces("<Z").tag("bottomface")
tank.vertices("<Z").tag("bottomvert")
return tank
# create the forward tank with a reversed aft dome
fwd_tank = make_tank(reverse_aft_dome=True)
# create the aft tank with no reversed domes
aft_tank = make_tank()
# create the assembly to house both tanks
assy = cq.Assembly()
# create a center line to align along Z axis
center_line = cq.Workplane("XZ").vLine(0.1, forConstruction=True)
assy.add(center_line, name="CenterLine")
assy.constrain("CenterLine", "Fixed")
# add the forward tank
assy.add(fwd_tank, name='Forward_Tank', color=red)
# add the aft tank
assy.add(aft_tank, name='Aft_Tank', color=green)
# constrain the forward tank to be fixed
assy.constrain('Forward_Tank', "Fixed")
# constrain the aft tank to the center line
assy.constrain('Aft_Tank?topvert', 'CenterLine', 'PointOnLine')
assy.constrain('Aft_Tank?bottomvert', 'CenterLine', 'PointOnLine')
# constrain the two tanks to overlap at the
# forward_tank:aft_dome - aft_tank:forward_dome
# interface
assy.constrain('Forward_Tank?bottomvert', 'Aft_Tank?topface', 'PointInPlane')
assy.solve()
# visualize
display(assy)