cosplay: Touhou/Houjuu Nue #4
|
@ -6,6 +6,33 @@ def binary_intersection(a: Cq.Assembly) -> Cq.Shape:
|
||||||
obj1, obj2 = objs[:2]
|
obj1, obj2 = objs[:2]
|
||||||
return obj1.intersect(obj2)
|
return obj1.intersect(obj2)
|
||||||
|
|
||||||
|
def visualize_intersection(assembly: Cq.Assembly, tol: float=1e-6) -> Cq.Shape:
|
||||||
|
"""
|
||||||
|
Given an assembly, test the pairwise intersection volume of its components.
|
||||||
|
Return the pairs whose intersection volume exceeds `tol`.
|
||||||
|
"""
|
||||||
|
m = {name: (i, shape.moved(loc))
|
||||||
|
for i, (shape, name, loc, _)
|
||||||
|
in enumerate(assembly)}
|
||||||
|
for name, (i1, sh1) in m.items():
|
||||||
|
for name2, (i2, sh2) in m.items():
|
||||||
|
if name == name2:
|
||||||
|
assert i1 == i2
|
||||||
|
continue
|
||||||
|
if i2 <= i1:
|
||||||
|
# Remove the upper diagonal
|
||||||
|
continue
|
||||||
|
head = name.split('/', 2)[1]
|
||||||
|
head2 = name2.split('/', 2)[1]
|
||||||
|
if head == head2:
|
||||||
|
# Do not test into subassemblies
|
||||||
|
continue
|
||||||
|
|
||||||
|
isect = sh1.intersect(sh2)
|
||||||
|
vol = isect.Volume()
|
||||||
|
if vol > tol:
|
||||||
|
return isect
|
||||||
|
return None
|
||||||
|
|
||||||
def pairwise_intersection(assembly: Cq.Assembly, tol: float=1e-6) -> list[(str, str, float)]:
|
def pairwise_intersection(assembly: Cq.Assembly, tol: float=1e-6) -> list[(str, str, float)]:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -218,6 +218,7 @@ class TorsionJoint:
|
||||||
assert self.radius_rider > self.groove_radius_outer > self.groove_radius_inner + self.groove_inner_gap
|
assert self.radius_rider > self.groove_radius_outer > self.groove_radius_inner + self.groove_inner_gap
|
||||||
assert self.groove_radius_inner > self.spring.radius > self.radius_axle
|
assert self.groove_radius_inner > self.spring.radius > self.radius_axle
|
||||||
assert self.spring.height > self.groove_depth, "Groove is too deep"
|
assert self.spring.height > self.groove_depth, "Groove is too deep"
|
||||||
|
assert self.groove_depth < self.spring.height - self.spring.thickness * 2
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def total_height(self):
|
def total_height(self):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import unittest
|
import unittest
|
||||||
import cadquery as Cq
|
import cadquery as Cq
|
||||||
from nhf.checks import binary_intersection, pairwise_intersection
|
from nhf.checks import binary_intersection, pairwise_intersection
|
||||||
from nhf.parts import joints, handle, metric_threads
|
from nhf.parts import joints, handle, metric_threads, springs
|
||||||
|
|
||||||
class TestJoints(unittest.TestCase):
|
class TestJoints(unittest.TestCase):
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ class TestJoints(unittest.TestCase):
|
||||||
with self.subTest(slot=slot, right_handed=False):
|
with self.subTest(slot=slot, right_handed=False):
|
||||||
self.torsion_joint_case(j, slot)
|
self.torsion_joint_case(j, slot)
|
||||||
def test_torsion_joint_right_handed(self):
|
def test_torsion_joint_right_handed(self):
|
||||||
j = joints.TorsionJoint(right_handed=True)
|
j = joints.TorsionJoint(springs.TorsionSpring(right_handed=True))
|
||||||
for slot in range(j.rider_n_slots):
|
for slot in range(j.rider_n_slots):
|
||||||
with self.subTest(slot=slot, right_handed=True):
|
with self.subTest(slot=slot, right_handed=True):
|
||||||
self.torsion_joint_case(j, slot)
|
self.torsion_joint_case(j, slot)
|
||||||
|
|
|
@ -18,6 +18,7 @@ class ShoulderJoint(Model):
|
||||||
torsion_joint: TorsionJoint = field(default_factory=lambda: TorsionJoint(
|
torsion_joint: TorsionJoint = field(default_factory=lambda: TorsionJoint(
|
||||||
radius_track=18,
|
radius_track=18,
|
||||||
radius_rider=18,
|
radius_rider=18,
|
||||||
|
groove_depth=4.8,
|
||||||
groove_radius_outer=16,
|
groove_radius_outer=16,
|
||||||
groove_radius_inner=13,
|
groove_radius_inner=13,
|
||||||
track_disk_height=5.0,
|
track_disk_height=5.0,
|
||||||
|
|
|
@ -6,6 +6,10 @@ from nhf.checks import pairwise_intersection
|
||||||
|
|
||||||
class TestJoints(unittest.TestCase):
|
class TestJoints(unittest.TestCase):
|
||||||
|
|
||||||
|
def test_shoulder_collision_of_torsion_joint(self):
|
||||||
|
j = MJ.ShoulderJoint()
|
||||||
|
assembly = j.torsion_joint.rider_track_assembly()
|
||||||
|
self.assertEqual(pairwise_intersection(assembly), [])
|
||||||
def test_shoulder_collision_0(self):
|
def test_shoulder_collision_0(self):
|
||||||
j = MJ.ShoulderJoint()
|
j = MJ.ShoulderJoint()
|
||||||
assembly = j.assembly()
|
assembly = j.assembly()
|
||||||
|
|
Loading…
Reference in New Issue