Geometry of mirror and rotor spacer
This commit is contained in:
parent
5b5ccee94e
commit
a684996475
|
@ -1,6 +1,7 @@
|
||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
import cadquery as Cq
|
import cadquery as Cq
|
||||||
from nhf.build import Model, TargetKind, target, assembly, submodel
|
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.touhou.yasaka_kanako.onbashira as MO
|
||||||
import nhf.utils
|
import nhf.utils
|
||||||
|
|
||||||
|
@ -8,36 +9,178 @@ import nhf.utils
|
||||||
class Mirror(Model):
|
class Mirror(Model):
|
||||||
"""
|
"""
|
||||||
Kanako's mirror, made of three levels.
|
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
|
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)
|
@target(name="core", kind=TargetKind.DXF)
|
||||||
def profile_core(self) -> Cq.Sketch:
|
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)
|
@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
|
Base of the casing with no holes carved out
|
||||||
"""
|
"""
|
||||||
dx = self.wall_thickness
|
|
||||||
return (
|
return (
|
||||||
Cq.Sketch()
|
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)
|
@target(name="casing-top", kind=TargetKind.DXF)
|
||||||
def profile_casing_top(self) -> Cq.Sketch:
|
def profile_casing_top(self) -> Cq.Sketch:
|
||||||
"""
|
rx = self.width/2 - self.outer_gap - self.inner_gap
|
||||||
Base of the casing with no holes carved out
|
ry = self.height/2 - self.outer_gap - self.inner_gap
|
||||||
"""
|
|
||||||
return (
|
return (
|
||||||
self.profile_casing()
|
self.profile_casing_bot()
|
||||||
.ellipse(self.width/2, self.height/2, mode="s")
|
.ellipse(rx, ry, mode="s")
|
||||||
|
)
|
||||||
|
def casing_top(self) -> Cq.Workplane:
|
||||||
|
return (
|
||||||
|
Cq.Workplane()
|
||||||
|
.placeSketch(self.profile_casing_top())
|
||||||
|
.extrude(self.casing_thickness)
|
||||||
)
|
)
|
||||||
|
|
||||||
@assembly()
|
@assembly()
|
||||||
def assembly(self) -> Cq.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
|
bearing_disk_thickness: float = 25.4 / 8
|
||||||
|
|
||||||
rotor_inner_radius: float = 40.0
|
rotor_inner_radius: float = 40.0
|
||||||
|
|
||||||
rotor_bind_bolt_diam: float = 8.0
|
rotor_bind_bolt_diam: float = 8.0
|
||||||
rotor_bind_radius: float = 85.0
|
rotor_bind_radius: float = 85.0
|
||||||
|
rotor_spacer_outer_diam: float = 15.0
|
||||||
stator_bind_radius: float = 140.0
|
stator_bind_radius: float = 140.0
|
||||||
|
|
||||||
material_side: Material = Material.WOOD_BIRCH
|
material_side: Material = Material.WOOD_BIRCH
|
||||||
|
@ -194,6 +194,74 @@ class Onbashira(Model):
|
||||||
"""
|
"""
|
||||||
pass
|
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(
|
def profile_side_panel(
|
||||||
self,
|
self,
|
||||||
length: float,
|
length: float,
|
||||||
|
@ -394,61 +462,6 @@ class Onbashira(Model):
|
||||||
result.tagAbsolute("holeStatorR", (ri * math.cos(th), ri * math.sin(th), -h/2), direction="-Z")
|
result.tagAbsolute("holeStatorR", (ri * math.cos(th), ri * math.sin(th), -h/2), direction="-Z")
|
||||||
return result
|
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:
|
def assembly_section(self, **kwargs) -> Cq.Assembly:
|
||||||
a = Cq.Assembly()
|
a = Cq.Assembly()
|
||||||
side = self.side_panel(**kwargs)
|
side = self.side_panel(**kwargs)
|
||||||
|
|
Loading…
Reference in New Issue