139 lines
3.7 KiB
Python
139 lines
3.7 KiB
Python
# @author Arnaud Morin <arnaud.gfpv@mailops.fr>
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
#
|
|
|
|
import cadquery as cq
|
|
from math import sqrt
|
|
|
|
def camera_mount():
|
|
|
|
cam = (cq.Workplane("XZ")
|
|
.box(17, 17, 10, centered=(True, True, False))
|
|
.faces(">Y")
|
|
.workplane()
|
|
.rect(17, 17)
|
|
.workplane(offset=8)
|
|
.rect(14, 14)
|
|
.loft(combine=True))
|
|
|
|
# Round the loft's four corners.
|
|
corners = cq.selectors.BoxSelector((-10, 1, -10), (10, 8, 10))
|
|
cam = cam.edges(corners).fillet(6.0)
|
|
|
|
# Lens hole
|
|
cam = cam.faces(">Y").workplane().hole(13.5)
|
|
|
|
# Camera pocket
|
|
cam = cam.faces("<Y").workplane().rect(14, 14).cutBlind(-9)
|
|
|
|
# Position camera correctly
|
|
cam = (cam.rotate((0, 0, 0), (1, 0, 0), 45)
|
|
.translate((0, 9, 17)))
|
|
|
|
# Base plate
|
|
base = (cq.Workplane("XY")
|
|
.box(55,55,1, centered=(True,True,False)))
|
|
|
|
# Skirt (jupe)
|
|
bottom_pts = [
|
|
(12, -22), (12, -7.5), (12, 0), (12, 7.5),
|
|
(12, 17), (6, 17), (0, 17), (-6, 17),
|
|
(-12, 17), (-12, 7.5), (-12, 0), (-12, -7.5),
|
|
(-12, -22), (-6, -22), (0, -22), (6, -22),
|
|
]
|
|
bottom = cq.Wire.makePolygon(
|
|
[cq.Vector(x, y, 0.0) for x, y in bottom_pts], close=True)
|
|
|
|
top_pts = [
|
|
(8.5, 8.5), (8.5, 4.25), (8.5, 0), (8.5, -4.25),
|
|
(8.5, -8.5), (4.25, -8.5), (0, -8.5), (-4.25, -8.5),
|
|
(-8.5, -8.5), (-8.5, -4.25), (-8.5, 0), (-8.5, 4.25),
|
|
(-8.5, 8.5), (-4.25, 8.5), (0, 8.5), (4.25, 8.5),
|
|
]
|
|
top = (cq.Wire.makePolygon(
|
|
[cq.Vector(x, -5.0, z) for x, z in top_pts], close=True)
|
|
.rotate((0, 0, 0), (1, 0, 0), 45)
|
|
.translate((0, 9, 17)))
|
|
|
|
skirt = cq.Workplane("XY").add(cq.Solid.makeLoft([bottom, top], True))
|
|
p = base.union(skirt)
|
|
|
|
# Filet between the union using a box to select the edges.
|
|
box = cq.selectors.BoxSelector((-13, -23, 0), (13, 18, 3), boundingbox=True)
|
|
p = p.faces("+Z").edges(box).fillet(9)
|
|
|
|
# Skirt pocket for camera
|
|
normal_45 = cq.Vector(0, 1 / sqrt(2), 1 / sqrt(2))
|
|
p = (p.faces(cq.DirectionSelector(normal_45))
|
|
.workplane(centerOption="CenterOfBoundBox")
|
|
.rect(14, 14)
|
|
.cutThruAll())
|
|
|
|
# Filet below base, on three sides of the pocket's exit hole.
|
|
box = cq.selectors.BoxSelector((-14, -16, 0), (14, 10, 1))
|
|
p = p.faces("-Z").edges(box).fillet(4.5)
|
|
|
|
# Camera support
|
|
p = p.union(cam)
|
|
|
|
# Cut extra plate
|
|
quadrant = [
|
|
(21, 0),
|
|
(15, 7),
|
|
(20, 23.7),
|
|
(14, 23.7),
|
|
(7.5, 20.5),
|
|
(0, 20.5),
|
|
(0, 40),
|
|
(40, 40),
|
|
(40, 0),
|
|
]
|
|
|
|
cut = (
|
|
cq.Workplane("XY")
|
|
.polyline(quadrant)
|
|
.close()
|
|
.extrude(10)
|
|
)
|
|
cut = cut.union(cut.mirror("XZ"))
|
|
cut = cut.union(cut.mirror("YZ"))
|
|
cut = cut.edges("|Z").fillet(3)
|
|
|
|
p = p.cut(cut)
|
|
|
|
# Add holes for 25.5x25.5 FC.
|
|
bolts = (cq.Workplane("XY")
|
|
.pushPoints([(18.03, 0), (-18.03, 0), (0, -18.03), (0, 18.03)])
|
|
.circle(2.2 / 2.0)
|
|
.extrude(10, both=True))
|
|
p = p.cut(bolts)
|
|
|
|
# Add holes for standoff
|
|
x, y = (14, 20)
|
|
bolts = (cq.Workplane("XY")
|
|
.pushPoints([(sx * x, sy * y) for sx in (-1.0, 1.0) for sy in (-1.0, 1.0)])
|
|
.circle(2.2 / 2.0)
|
|
.extrude(10, both=True))
|
|
p = p.cut(bolts)
|
|
|
|
return p
|
|
|
|
|
|
result = camera_mount()
|
|
|
|
assert result.solids().size() == 1, "camera_mount is not one solid"
|
|
|
|
if "show_object" not in globals(): # running outside CQ-editor
|
|
def show_object(*args, **kwargs):
|
|
pass
|
|
|
|
show_object(result)
|
|
|
|
if __name__ == "__main__":
|
|
TPU_DENSITY = 1.21e-3 # g/mm3
|
|
|
|
solid = result.val()
|
|
|
|
print("camera_mount %.2f g in TPU"
|
|
% (solid.Volume() * TPU_DENSITY))
|