cosplay: Touhou/Shiki Eiki #7

Open
aniva wants to merge 11 commits from touhou/shiki-eiki into main
1 changed files with 69 additions and 32 deletions
Showing only changes of commit dbf374fe20 - Show all commits

View File

@ -10,9 +10,9 @@ class Crown(Model):
facets: int = 5 facets: int = 5
# Lower circumference # Lower circumference
base_circ: float = 570.0 base_circ: float = 538.0
# Upper circumference # Upper circumference
tilt_circ: float = 670.0 tilt_circ: float = 640.0
height: float = 120.0 height: float = 120.0
margin: float = 10.0 margin: float = 10.0
@ -25,6 +25,7 @@ class Crown(Model):
super().__init__(name="crown") super().__init__(name="crown")
assert self.tilt_circ > self.base_circ assert self.tilt_circ > self.base_circ
assert self.facet_width_upper / 2 > self.height / 2, "Top angle must be > 90 degrees"
@property @property
def facet_width_lower(self): def facet_width_lower(self):
@ -33,8 +34,7 @@ class Crown(Model):
def facet_width_upper(self): def facet_width_upper(self):
return self.tilt_circ / self.facets return self.tilt_circ / self.facets
@target(name="side", kind=TargetKind.DXF) def profile_base(self) -> Cq.Sketch:
def profile_side(self) -> Cq.Sketch:
# Generate the pentagonal shape # Generate the pentagonal shape
dx_l = self.facet_width_lower dx_l = self.facet_width_lower
@ -51,6 +51,35 @@ class Crown(Model):
]) ])
) )
@target(name="side", kind=TargetKind.DXF)
def profile_side(self) -> Cq.Sketch:
dy = self.facet_width_upper * 0.1
x_side = self.facet_width_upper
y_tip = self.height - self.margin
eye = (
Cq.Sketch()
.segment(
(0, y_tip),
(dy, y_tip - dy),
)
.segment(
(0, y_tip),
(-dy, y_tip - dy),
)
.bezier([
(dy, y_tip - dy),
(0, y_tip - dy/2),
(0, y_tip - dy/2),
(-dy, y_tip - dy),
])
.assemble()
)
return (
self.profile_base()
.boolean(eye, mode='s')
)
@target(name="dot", kind=TargetKind.DXF) @target(name="dot", kind=TargetKind.DXF)
def profile_dot(self) -> Cq.Sketch: def profile_dot(self) -> Cq.Sketch:
return ( return (
@ -72,7 +101,7 @@ class Crown(Model):
) )
window_p1 = Cq.Location.from2d( window_p1 = Cq.Location.from2d(
dx_u/2 - self.margin - window_length * 0.4, dx_u/2 - self.margin - window_length * 0.4,
dy/2 + self.margin, dy/2 + self.margin/2,
math.degrees(math.atan2(dy/2, -dx_u/2)), math.degrees(math.atan2(dy/2, -dx_u/2)),
) )
window_p2 = Cq.Location.from2d( window_p2 = Cq.Location.from2d(
@ -156,20 +185,44 @@ class Crown(Model):
needle_y_top = dy - self.margin needle_y_top = dy - self.margin
needle_y_mid = dy * 0.7 needle_y_mid = dy * 0.7
needle_dx = scale_base_x * 2 needle_dx = scale_base_x * 2
y_shoulder = needle_y_mid - z * 2
needle = ( needle = (
Cq.Sketch()
.segment(
(0, needle_y_mid),
(z, y_shoulder),
)
.segment(
(z, y_shoulder),
(z, scale_base_y),
)
.segment(
(z, scale_base_y),
(-z, scale_base_y),
)
.segment(
(-z, y_shoulder),
(-z, scale_base_y),
)
.segment(
(-z, y_shoulder),
(0, needle_y_mid),
)
.assemble()
)
z2 = z * 2
y1 = needle_y_mid + z2
needle_head = (
Cq.Sketch() Cq.Sketch()
.segment( .segment(
(z, needle_y_mid), (z, needle_y_mid),
(z, scale_base_y), (z, y1),
) )
.segment( .segment(
(z, scale_base_y),
(-z, scale_base_y),
)
.segment(
(-z, scale_base_y),
(-z, needle_y_mid), (-z, needle_y_mid),
(-z, y1),
) )
# Outer edge
.bezier([ .bezier([
(0, needle_y_top), (0, needle_y_top),
(0, (needle_y_top + needle_y_mid)/2), (0, (needle_y_top + needle_y_mid)/2),
@ -182,40 +235,24 @@ class Crown(Model):
(-needle_dx, (needle_y_top + needle_y_mid)/2), (-needle_dx, (needle_y_top + needle_y_mid)/2),
(-z, needle_y_mid), (-z, needle_y_mid),
]) ])
.assemble() # Inner edge
)
z2 = z * 2
needle_inner = (
Cq.Sketch()
.segment(
(z2, needle_y_mid - z2),
(-z2, needle_y_mid - z2)
)
.segment(
(z2, needle_y_mid - z2),
(z2, needle_y_mid + z2),
)
.segment(
(-z2, needle_y_mid - z2),
(-z2, needle_y_mid + z2),
)
.bezier([ .bezier([
(0, needle_y_top - z2), (0, needle_y_top - z2),
(0, (needle_y_top + needle_y_mid)/2), (0, (needle_y_top + needle_y_mid)/2),
(needle_dx-z2*2, (needle_y_top + needle_y_mid)/2), (needle_dx-z2*2, (needle_y_top + needle_y_mid)/2),
(z2, needle_y_mid + z2), (z, y1),
]) ])
.bezier([ .bezier([
(0, needle_y_top - z2), (0, needle_y_top - z2),
(0, (needle_y_top + needle_y_mid)/2), (0, (needle_y_top + needle_y_mid)/2),
(-needle_dx+z2*2, (needle_y_top + needle_y_mid)/2), (-needle_dx+z2*2, (needle_y_top + needle_y_mid)/2),
(-z2, needle_y_mid + z2), (-z, y1),
]) ])
.assemble() .assemble()
) )
return ( return (
self.profile_side() self.profile_base()
.boolean(window.moved(window_p1), mode='s') .boolean(window.moved(window_p1), mode='s')
.boolean(window.moved(window_p1.flip_x()), mode='s') .boolean(window.moved(window_p1.flip_x()), mode='s')
.boolean(window.moved(window_p2), mode='s') .boolean(window.moved(window_p2), mode='s')
@ -224,7 +261,7 @@ class Crown(Model):
.boolean(scale_pan.moved(loc_scale_pan2), mode='s') .boolean(scale_pan.moved(loc_scale_pan2), mode='s')
.boolean(scale_body, mode='s') .boolean(scale_body, mode='s')
.boolean(needle, mode='s') .boolean(needle, mode='s')
.boolean(needle_inner, mode='a') .boolean(needle_head, mode='s')
.clean() .clean()
) )