Geometry of mirror and rotor spacer
This commit is contained in:
parent
5b5ccee94e
commit
a684996475
|
@ -1,6 +1,7 @@
|
|||
from dataclasses import dataclass, field
|
||||
import cadquery as Cq
|
||||
from nhf.build import Model, TargetKind, target, assembly, submodel
|
||||
from nhf.materials import Role, Material
|
||||
import nhf.touhou.yasaka_kanako.onbashira as MO
|
||||
import nhf.utils
|
||||
|
||||
|
@ -8,36 +9,178 @@ import nhf.utils
|
|||
class Mirror(Model):
|
||||
"""
|
||||
Kanako's mirror, made of three levels.
|
||||
|
||||
The mirror suface is sandwiched between two layers of wood. As such, its
|
||||
dimensions have to sit in between that of the aperature on the surface, and
|
||||
the outer walls. The width/height here refers to the outer edge's width and height
|
||||
"""
|
||||
width: float = 50.0
|
||||
height: float = 70.0
|
||||
height: float = 60.0
|
||||
|
||||
wall_thickness: float = 10.0
|
||||
inner_gap: float = 3.0
|
||||
outer_gap: float = 3.0
|
||||
|
||||
core_thickness: float = 25.4 / 8
|
||||
casing_thickness: float = 25.4 / 16
|
||||
|
||||
flange_r0: float = 5.0
|
||||
flange_r1: float = 15.0
|
||||
flange_y1: float = 12.0
|
||||
flange_y2: float = 25.0
|
||||
flange_hole_r: float = 8.0
|
||||
wing_x1: float = 12.0
|
||||
wing_x2: float = 20.0
|
||||
wing_r1: float = 6.0
|
||||
wing_r2: float = 12.0
|
||||
tail_r0: float = 5.0
|
||||
tail_r1: float = 10.0
|
||||
tail_y1: float = 12.0
|
||||
tail_y2: float = 25.0
|
||||
|
||||
# Necklace hole
|
||||
hole_diam: float = 5.0
|
||||
|
||||
material_mirror: Material = Material.ACRYLIC_TRANSPARENT
|
||||
material_casing: Material = Material.WOOD_BIRCH
|
||||
|
||||
@target(name="core", kind=TargetKind.DXF)
|
||||
def profile_core(self) -> Cq.Sketch:
|
||||
return Cq.Sketch().ellipse(self.width/2, self.height/2)
|
||||
rx = self.width/2 - self.outer_gap
|
||||
ry = self.height/2 - self.outer_gap
|
||||
return Cq.Sketch().ellipse(rx, ry)
|
||||
|
||||
def core(self) -> Cq.Workplane:
|
||||
return (
|
||||
Cq.Workplane()
|
||||
.placeSketch(self.profile_core())
|
||||
.extrude(self.core_thickness)
|
||||
)
|
||||
|
||||
@target(name="casing-bot", kind=TargetKind.DXF)
|
||||
def profile_casing(self) -> Cq.Sketch:
|
||||
def profile_casing_bot(self) -> Cq.Sketch:
|
||||
"""
|
||||
Base of the casing with no holes carved out
|
||||
"""
|
||||
dx = self.wall_thickness
|
||||
return (
|
||||
Cq.Sketch()
|
||||
.ellipse(self.width/2+dx, self.height/2+dx)
|
||||
.ellipse(self.width/2, self.height/2)
|
||||
)
|
||||
def casing_bot(self) -> Cq.Workplane:
|
||||
return (
|
||||
Cq.Workplane()
|
||||
.placeSketch(self.profile_casing_bot())
|
||||
.extrude(self.casing_thickness)
|
||||
)
|
||||
def profile_wing(self, sign: float=1) -> Cq.Sketch:
|
||||
xt = self.width / 2 - self.outer_gap
|
||||
return (
|
||||
Cq.Sketch()
|
||||
.polygon([
|
||||
(sign*xt, self.wing_r1),
|
||||
(sign*(xt+self.wing_x1), self.wing_r1),
|
||||
(sign*(xt+self.wing_x1), self.wing_r2),
|
||||
(sign*(xt+self.wing_x2), self.wing_r2),
|
||||
(sign*(xt+self.wing_x2), -self.wing_r2),
|
||||
(sign*(xt+self.wing_x1), -self.wing_r2),
|
||||
(sign*(xt+self.wing_x1), -self.wing_r1),
|
||||
(sign*xt, -self.wing_r1),
|
||||
])
|
||||
)
|
||||
@target(name="casing-mid", kind=TargetKind.DXF)
|
||||
def profile_casing_mid(self) -> Cq.Sketch:
|
||||
yt = self.height / 2 - self.outer_gap
|
||||
rx = self.width/2 - self.outer_gap
|
||||
ry = self.height/2 - self.outer_gap
|
||||
yh = (self.flange_y1 + self.flange_y2) / 2
|
||||
flange = (
|
||||
Cq.Sketch()
|
||||
.polygon([
|
||||
(self.flange_r0, yt),
|
||||
(self.flange_r0, yt + self.flange_y1),
|
||||
(self.flange_r1, yt + self.flange_y1),
|
||||
(self.flange_r1, yt + self.flange_y2),
|
||||
(-self.flange_r1, yt + self.flange_y2),
|
||||
(-self.flange_r1, yt + self.flange_y1),
|
||||
(-self.flange_r0, yt + self.flange_y1),
|
||||
(-self.flange_r0, yt),
|
||||
])
|
||||
.push([
|
||||
(self.flange_hole_r, yt+yh),
|
||||
(-self.flange_hole_r, yt+yh),
|
||||
])
|
||||
.circle(self.hole_diam/2, mode="s")
|
||||
)
|
||||
tail = (
|
||||
Cq.Sketch()
|
||||
.polygon([
|
||||
(+self.tail_r0, -yt),
|
||||
(+self.tail_r0, -yt - self.tail_y1),
|
||||
(+self.tail_r1, -yt - self.tail_y1),
|
||||
(+self.tail_r1, -yt - self.tail_y2),
|
||||
(-self.tail_r1, -yt - self.tail_y2),
|
||||
(-self.tail_r1, -yt - self.tail_y1),
|
||||
(-self.tail_r0, -yt - self.tail_y1),
|
||||
(-self.tail_r0, -yt),
|
||||
])
|
||||
)
|
||||
return (
|
||||
self.profile_casing_bot()
|
||||
.ellipse(rx, ry, mode="s")
|
||||
.boolean(flange, mode="a")
|
||||
.boolean(tail, mode="a")
|
||||
.boolean(self.profile_wing(-1), mode="a")
|
||||
.boolean(self.profile_wing(1), mode="a")
|
||||
)
|
||||
def casing_mid(self) -> Cq.Workplane:
|
||||
return (
|
||||
Cq.Workplane()
|
||||
.placeSketch(self.profile_casing_mid())
|
||||
.extrude(self.core_thickness)
|
||||
)
|
||||
@target(name="casing-top", kind=TargetKind.DXF)
|
||||
def profile_casing_top(self) -> Cq.Sketch:
|
||||
"""
|
||||
Base of the casing with no holes carved out
|
||||
"""
|
||||
rx = self.width/2 - self.outer_gap - self.inner_gap
|
||||
ry = self.height/2 - self.outer_gap - self.inner_gap
|
||||
return (
|
||||
self.profile_casing()
|
||||
.ellipse(self.width/2, self.height/2, mode="s")
|
||||
self.profile_casing_bot()
|
||||
.ellipse(rx, ry, mode="s")
|
||||
)
|
||||
def casing_top(self) -> Cq.Workplane:
|
||||
return (
|
||||
Cq.Workplane()
|
||||
.placeSketch(self.profile_casing_top())
|
||||
.extrude(self.casing_thickness)
|
||||
)
|
||||
|
||||
@assembly()
|
||||
def assembly(self) -> Cq.Assembly:
|
||||
pass
|
||||
return (
|
||||
Cq.Assembly()
|
||||
.addS(
|
||||
self.core(),
|
||||
name="core",
|
||||
material=self.material_mirror,
|
||||
role=Role.DECORATION,
|
||||
loc=Cq.Location(0, 0, self.casing_thickness)
|
||||
)
|
||||
.addS(
|
||||
self.casing_bot(),
|
||||
name="casing_bot",
|
||||
material=self.material_casing,
|
||||
role=Role.CASING,
|
||||
)
|
||||
.addS(
|
||||
self.casing_mid(),
|
||||
name="casing_mid",
|
||||
material=self.material_casing,
|
||||
role=Role.CASING,
|
||||
loc=Cq.Location(0, 0, self.casing_thickness)
|
||||
)
|
||||
.addS(
|
||||
self.casing_top(),
|
||||
name="casing_top",
|
||||
material=self.material_casing,
|
||||
role=Role.CASING,
|
||||
loc=Cq.Location(0, 0, self.core_thickness + self.casing_thickness)
|
||||
)
|
||||
)
|
||||
|
|
|
@ -54,9 +54,9 @@ class Onbashira(Model):
|
|||
bearing_disk_thickness: float = 25.4 / 8
|
||||
|
||||
rotor_inner_radius: float = 40.0
|
||||
|
||||
rotor_bind_bolt_diam: float = 8.0
|
||||
rotor_bind_radius: float = 85.0
|
||||
rotor_spacer_outer_diam: float = 15.0
|
||||
stator_bind_radius: float = 140.0
|
||||
|
||||
material_side: Material = Material.WOOD_BIRCH
|
||||
|
@ -194,6 +194,74 @@ class Onbashira(Model):
|
|||
"""
|
||||
pass
|
||||
|
||||
def bearing_ball(self) -> Cq.Solid:
|
||||
return Cq.Solid.makeSphere(radius=self.bearing_ball_diam/2, angleDegrees1=-90)
|
||||
|
||||
@target(name="rotor-spacer")
|
||||
def rotor_spacer(self) -> Cq.Solid:
|
||||
outer = Cq.Solid.makeCylinder(
|
||||
radius=self.rotor_spacer_outer_diam/2,
|
||||
height=self.bearing_disk_gap,
|
||||
)
|
||||
inner = Cq.Solid.makeCylinder(
|
||||
radius=self.rotor_bind_bolt_diam/2,
|
||||
height=self.bearing_disk_gap
|
||||
)
|
||||
return outer - inner
|
||||
|
||||
def assembly_rotor(self) -> Cq.Assembly:
|
||||
z_lower = -self.bearing_disk_gap/2 - self.bearing_disk_thickness
|
||||
a = (
|
||||
Cq.Assembly()
|
||||
.addS(
|
||||
self.bearing_stator(),
|
||||
name="stator1",
|
||||
material=self.material_bearing,
|
||||
role=Role.STATOR,
|
||||
loc=Cq.Location(0, 0, self.bearing_disk_gap/2)
|
||||
)
|
||||
.addS(
|
||||
self.bearing_rotor(),
|
||||
name="rotor1",
|
||||
material=self.material_bearing,
|
||||
role=Role.ROTOR,
|
||||
loc=Cq.Location(0, 0, self.bearing_disk_gap/2)
|
||||
)
|
||||
.addS(
|
||||
self.bearing_stator(),
|
||||
name="stator2",
|
||||
material=self.material_bearing,
|
||||
role=Role.STATOR,
|
||||
loc=Cq.Location(0, 0, z_lower)
|
||||
)
|
||||
.addS(
|
||||
self.bearing_rotor(),
|
||||
name="rotor2",
|
||||
material=self.material_bearing,
|
||||
role=Role.ROTOR,
|
||||
loc=Cq.Location(0, 0, z_lower)
|
||||
)
|
||||
.addS(
|
||||
self.bearing_gasket(),
|
||||
name="gasket",
|
||||
material=self.material_bearing,
|
||||
role=Role.ROTOR,
|
||||
loc=Cq.Location(0, 0, -self.bearing_disk_thickness/2)
|
||||
)
|
||||
)
|
||||
for i in range(self.n_bearing_balls):
|
||||
ball = self.bearing_ball()
|
||||
loc = Cq.Location.rot2d(i * 360/self.n_bearing_balls) * Cq.Location(self.bearing_track_radius, 0, 0)
|
||||
a = a.addS(
|
||||
ball,
|
||||
name=f"bearing_ball{i}",
|
||||
material=self.material_bearing_ball,
|
||||
role=Role.BEARING,
|
||||
loc=loc,
|
||||
)
|
||||
return a
|
||||
|
||||
|
||||
def profile_side_panel(
|
||||
self,
|
||||
length: float,
|
||||
|
@ -394,61 +462,6 @@ class Onbashira(Model):
|
|||
result.tagAbsolute("holeStatorR", (ri * math.cos(th), ri * math.sin(th), -h/2), direction="-Z")
|
||||
return result
|
||||
|
||||
def bearing_ball(self) -> Cq.Solid:
|
||||
return Cq.Solid.makeSphere(radius=self.bearing_ball_diam/2, angleDegrees1=-90)
|
||||
|
||||
def assembly_rotor(self) -> Cq.Assembly:
|
||||
z_lower = -self.bearing_disk_gap/2 - self.bearing_disk_thickness
|
||||
a = (
|
||||
Cq.Assembly()
|
||||
.addS(
|
||||
self.bearing_stator(),
|
||||
name="stator1",
|
||||
material=self.material_bearing,
|
||||
role=Role.STATOR,
|
||||
loc=Cq.Location(0, 0, self.bearing_disk_gap/2)
|
||||
)
|
||||
.addS(
|
||||
self.bearing_rotor(),
|
||||
name="rotor1",
|
||||
material=self.material_bearing,
|
||||
role=Role.ROTOR,
|
||||
loc=Cq.Location(0, 0, self.bearing_disk_gap/2)
|
||||
)
|
||||
.addS(
|
||||
self.bearing_stator(),
|
||||
name="stator2",
|
||||
material=self.material_bearing,
|
||||
role=Role.STATOR,
|
||||
loc=Cq.Location(0, 0, z_lower)
|
||||
)
|
||||
.addS(
|
||||
self.bearing_rotor(),
|
||||
name="rotor2",
|
||||
material=self.material_bearing,
|
||||
role=Role.ROTOR,
|
||||
loc=Cq.Location(0, 0, z_lower)
|
||||
)
|
||||
.addS(
|
||||
self.bearing_gasket(),
|
||||
name="gasket",
|
||||
material=self.material_bearing,
|
||||
role=Role.ROTOR,
|
||||
loc=Cq.Location(0, 0, -self.bearing_disk_thickness/2)
|
||||
)
|
||||
)
|
||||
for i in range(self.n_bearing_balls):
|
||||
ball = self.bearing_ball()
|
||||
loc = Cq.Location.rot2d(i * 360/self.n_bearing_balls) * Cq.Location(self.bearing_track_radius, 0, 0)
|
||||
a = a.addS(
|
||||
ball,
|
||||
name=f"bearing_ball{i}",
|
||||
material=self.material_bearing_ball,
|
||||
role=Role.BEARING,
|
||||
loc=loc,
|
||||
)
|
||||
return a
|
||||
|
||||
def assembly_section(self, **kwargs) -> Cq.Assembly:
|
||||
a = Cq.Assembly()
|
||||
side = self.side_panel(**kwargs)
|
||||
|
|
Loading…
Reference in New Issue