cosplay: Touhou/Shiki Eiki #7
|
@ -61,6 +61,7 @@ class Crown(Model):
|
||||||
|
|
||||||
assert self.front_wing_angle < 180 / self.facets
|
assert self.front_wing_angle < 180 / self.facets
|
||||||
assert self.front_wing_dh + self.front_wing_height < self.height
|
assert self.front_wing_dh + self.front_wing_height < self.height
|
||||||
|
assert self.slot_phi < 2 * math.pi / self.facets
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def facet_width_lower(self):
|
def facet_width_lower(self):
|
||||||
|
@ -88,21 +89,79 @@ class Crown(Model):
|
||||||
def radius_upper_front(self):
|
def radius_upper_front(self):
|
||||||
return self.radius_lower_front + (self.radius_upper - self.radius_lower)
|
return self.radius_lower_front + (self.radius_upper - self.radius_lower)
|
||||||
|
|
||||||
def profile_base(self) -> Cq.Sketch:
|
@property
|
||||||
# Generate the pentagonal shape
|
def slot_r0(self):
|
||||||
|
return self.radius_lower + self.thickness / 2
|
||||||
|
@property
|
||||||
|
def slot_r1(self):
|
||||||
|
return self.radius_upper + self.thickness / 2
|
||||||
|
|
||||||
|
@property
|
||||||
|
def slot_h0(self) -> float:
|
||||||
|
"""
|
||||||
|
Phantom height formed by similar triangle, i.e. h0 in
|
||||||
|
|
||||||
|
(h0 + h) / r2 = h0 / r1
|
||||||
|
"""
|
||||||
|
rat = self.slot_r0 / (self.slot_r1 - self.slot_r0)
|
||||||
|
return self.height * rat
|
||||||
|
@property
|
||||||
|
def slot_theta(self) -> float:
|
||||||
|
"""
|
||||||
|
Cone tilt, related to other quantities by
|
||||||
|
h0 = r1 * cot theta
|
||||||
|
"""
|
||||||
|
h = self.height
|
||||||
|
return math.atan(self.slot_r0 / (self.height + self.slot_h0))
|
||||||
|
@property
|
||||||
|
def slot_phi(self) -> float:
|
||||||
|
"""
|
||||||
|
When a slice of the crown is expanded (via Gauss's Theorema Egregium),
|
||||||
|
it does not form a full circle. phi is the angle of one of the slices.
|
||||||
|
|
||||||
|
Note that on the cone itself, the angular slice is `2 pi / n` which `n`
|
||||||
|
is the number of sides.
|
||||||
|
"""
|
||||||
|
arc = self.slot_r0 * math.pi * 2 / self.facets
|
||||||
|
rho = self.slot_h0 / math.cos(self.slot_theta)
|
||||||
|
return arc / rho
|
||||||
|
|
||||||
|
|
||||||
|
def profile_base(self) -> Cq.Sketch:
|
||||||
|
# Generate a conical pentagonal shape
|
||||||
|
|
||||||
|
y0 = self.slot_h0 / math.cos(self.slot_theta)
|
||||||
|
yh = (self.height/2 + self.slot_h0) / math.cos(self.slot_theta)
|
||||||
|
yq = (self.height*3/4 + self.slot_h0) / math.cos(self.slot_theta)
|
||||||
|
y1 = (self.height + self.slot_h0) / math.cos(self.slot_theta)
|
||||||
|
phi2 = self.slot_phi / 2
|
||||||
|
|
||||||
dx_l = self.facet_width_lower
|
|
||||||
dx_u = self.facet_width_upper
|
|
||||||
dy = self.height
|
|
||||||
return (
|
return (
|
||||||
Cq.Sketch()
|
Cq.Sketch()
|
||||||
.polygon([
|
.segment(
|
||||||
(dx_l/2, 0),
|
(y0 * math.sin(phi2), y0 * (-1 + math.cos(phi2))),
|
||||||
(dx_u/2, dy/2),
|
(yh * math.sin(phi2), -y0 + yh * math.cos(phi2)),
|
||||||
(0, dy),
|
)
|
||||||
(-dx_u/2, dy/2),
|
.arc(
|
||||||
(-dx_l/2, 0),
|
(yh * math.sin(phi2), -y0 + yh * math.cos(phi2)),
|
||||||
])
|
(yq * math.sin(phi2/2), -y0 + yq * math.cos(phi2/2)),
|
||||||
|
(0, y1 - y0),
|
||||||
|
)
|
||||||
|
.arc(
|
||||||
|
(-yh * math.sin(phi2), -y0 + yh * math.cos(phi2)),
|
||||||
|
(-yq * math.sin(phi2/2), -y0 + yq * math.cos(phi2/2)),
|
||||||
|
(0, y1 - y0),
|
||||||
|
)
|
||||||
|
.segment(
|
||||||
|
(-y0 * math.sin(phi2), y0 * (-1 + math.cos(phi2))),
|
||||||
|
(-yh * math.sin(phi2), -y0 + yh * math.cos(phi2)),
|
||||||
|
)
|
||||||
|
.arc(
|
||||||
|
(y0 * math.sin(phi2), -y0 + y0 * math.cos(phi2)),
|
||||||
|
(0, 0),
|
||||||
|
(-y0 * math.sin(phi2), y0 * (-1 + math.cos(phi2))),
|
||||||
|
)
|
||||||
|
.assemble()
|
||||||
)
|
)
|
||||||
|
|
||||||
@target(name="side", kind=TargetKind.DXF)
|
@target(name="side", kind=TargetKind.DXF)
|
||||||
|
|
Loading…
Reference in New Issue