2024-07-06 16:41:13 -07:00
|
|
|
"""
|
|
|
|
Unit tests for tooling
|
|
|
|
"""
|
2024-06-20 23:29:18 -07:00
|
|
|
import unittest
|
2024-06-24 11:13:11 -07:00
|
|
|
import cadquery as Cq
|
2024-07-04 00:42:14 -07:00
|
|
|
from nhf.build import Model, target
|
2024-07-06 16:41:13 -07:00
|
|
|
import nhf.checks
|
|
|
|
import nhf.utils
|
|
|
|
|
|
|
|
# Color presets for testing purposes
|
|
|
|
color_parent = Cq.Color(0.7, 0.7, 0.5, 0.5)
|
|
|
|
color_child = Cq.Color(0.5, 0.7, 0.7, 0.5)
|
|
|
|
|
|
|
|
def makeSphere(r: float) -> Cq.Solid:
|
|
|
|
"""
|
|
|
|
Makes a full sphere. The default function makes a hemisphere
|
|
|
|
"""
|
|
|
|
return Cq.Solid.makeSphere(r, angleDegrees1=-90)
|
2024-06-20 23:29:18 -07:00
|
|
|
|
2024-07-04 00:42:14 -07:00
|
|
|
class BuildScaffold(Model):
|
2024-06-20 23:29:18 -07:00
|
|
|
|
2024-07-06 16:41:13 -07:00
|
|
|
def __init__(self):
|
|
|
|
super().__init__(name="scaffold")
|
|
|
|
|
2024-07-04 00:42:14 -07:00
|
|
|
@target(name="obj1")
|
|
|
|
def o1(self):
|
|
|
|
return Cq.Solid.makeBox(10, 10, 10)
|
2024-06-30 14:28:42 -07:00
|
|
|
|
2024-07-04 00:42:14 -07:00
|
|
|
def o2(self):
|
|
|
|
return Cq.Solid.makeCylinder(10, 20)
|
2024-06-20 23:29:18 -07:00
|
|
|
|
2024-07-04 00:42:14 -07:00
|
|
|
class TestBuild(unittest.TestCase):
|
2024-06-25 06:11:48 -07:00
|
|
|
|
2024-07-04 00:42:14 -07:00
|
|
|
def test_build_scaffold(self):
|
|
|
|
s = BuildScaffold()
|
|
|
|
names = ["obj1"]
|
|
|
|
self.assertEqual(s.target_names, names)
|
|
|
|
self.assertEqual(s.check_all(), len(names))
|
2024-06-26 08:28:25 -07:00
|
|
|
|
2024-07-06 16:41:13 -07:00
|
|
|
class TestChecks(unittest.TestCase):
|
|
|
|
|
|
|
|
def intersect_test_case(self, offset):
|
|
|
|
assembly = (
|
|
|
|
Cq.Assembly()
|
|
|
|
.add(Cq.Solid.makeBox(10, 10, 10),
|
|
|
|
name="c1",
|
|
|
|
loc=Cq.Location((0, 0, 0)))
|
|
|
|
.add(Cq.Solid.makeBox(10, 10, 10),
|
|
|
|
name="c2",
|
|
|
|
loc=Cq.Location((0, 0, offset)))
|
|
|
|
)
|
|
|
|
coll = nhf.checks.pairwise_intersection(assembly)
|
|
|
|
if -10 < offset and offset < 10:
|
|
|
|
self.assertEqual(len(coll), 1)
|
|
|
|
else:
|
|
|
|
self.assertEqual(coll, [])
|
|
|
|
|
|
|
|
def test_intersect(self):
|
|
|
|
for offset in [9, 10, 11, -10]:
|
|
|
|
with self.subTest(offset=offset):
|
|
|
|
self.intersect_test_case(offset)
|
|
|
|
|
|
|
|
class TestUtils(unittest.TestCase):
|
|
|
|
|
2024-07-17 14:47:34 -07:00
|
|
|
def test_2d_orientation(self):
|
|
|
|
l1 = Cq.Location.from2d(1.2, 0)
|
|
|
|
l2 = Cq.Location.from2d(0, 0, 90)
|
|
|
|
l3 = l2 * l1
|
|
|
|
(x, y), r = l3.to2d()
|
|
|
|
self.assertAlmostEqual(x, 0)
|
|
|
|
self.assertAlmostEqual(y, 1.2)
|
|
|
|
self.assertAlmostEqual(r, 90)
|
|
|
|
|
|
|
|
def test_2d_planar(self):
|
|
|
|
l1 = Cq.Location.from2d(1.2, 4.5, 67)
|
|
|
|
l2 = Cq.Location.from2d(98, 5.4, 36)
|
|
|
|
l3 = Cq.Location.from2d(10, 10, 0)
|
|
|
|
l = l3 * l2 * l1
|
|
|
|
self.assertTrue(l.is2d())
|
|
|
|
|
2024-07-06 16:41:13 -07:00
|
|
|
def test_tag_point(self):
|
|
|
|
"""
|
|
|
|
A board with 3 holes of unequal sizes. Each hole is marked
|
|
|
|
"""
|
|
|
|
p4x, p4y = 5, 5
|
|
|
|
p3x, p3y = 0, 0
|
|
|
|
p2x, p2y = -5, 0
|
|
|
|
board = (
|
|
|
|
Cq.Workplane('XY')
|
|
|
|
.box(15, 15, 5)
|
|
|
|
.faces("<Z")
|
|
|
|
.workplane()
|
|
|
|
.pushPoints([(p4x, p4y)])
|
|
|
|
.hole(4, depth=2)
|
|
|
|
.pushPoints([(p3x, p3y)])
|
|
|
|
.hole(3, depth=1.5)
|
|
|
|
.pushPoints([(p2x, p2y)])
|
|
|
|
.hole(2, depth=1)
|
|
|
|
)
|
|
|
|
board.moveTo(p4x, p4y).tagPoint("h4")
|
|
|
|
board.moveTo(p3x, p3y).tagPoint("h3")
|
|
|
|
board.moveTo(p2x, p2y).tagPoint("h2")
|
|
|
|
|
|
|
|
assembly = (
|
|
|
|
Cq.Assembly()
|
|
|
|
.add(board, name="board", color=color_parent)
|
|
|
|
.add(makeSphere(2), name="s4", color=color_child)
|
|
|
|
.add(makeSphere(1.5), name="s3", color=color_child)
|
|
|
|
.add(makeSphere(1), name="s2", color=color_child)
|
|
|
|
.constrain("board?h4", "s4", "Point")
|
|
|
|
.constrain("board?h3", "s3", "Point")
|
|
|
|
.constrain("board?h2", "s2", "Point")
|
|
|
|
.solve()
|
|
|
|
)
|
|
|
|
self.assertEqual(nhf.checks.pairwise_intersection(assembly), [])
|
|
|
|
bbox = assembly.toCompound().BoundingBox()
|
|
|
|
self.assertAlmostEqual(bbox.xlen, 15)
|
|
|
|
self.assertAlmostEqual(bbox.ylen, 15)
|
|
|
|
self.assertAlmostEqual(bbox.zlen, 7)
|
|
|
|
|
|
|
|
def test_tag_plane(self):
|
|
|
|
p4x, p4y = 5, 5
|
|
|
|
p3x, p3y = 0, 0
|
|
|
|
p2x, p2y = -5, 0
|
|
|
|
board = (
|
|
|
|
Cq.Workplane('XY')
|
|
|
|
.box(15, 15, 5)
|
|
|
|
.faces("<Z")
|
|
|
|
.workplane()
|
|
|
|
.pushPoints([(p4x, p4y)])
|
|
|
|
.hole(4, depth=2)
|
|
|
|
.pushPoints([(p3x, p3y)])
|
|
|
|
.hole(3, depth=1.5)
|
|
|
|
.pushPoints([(p2x, p2y)])
|
|
|
|
.hole(2, depth=1)
|
|
|
|
)
|
|
|
|
board.moveTo(p4x, p4y).tagPlane("h4")
|
|
|
|
board.moveTo(p3x, p3y).tagPlane("h3")
|
|
|
|
board.moveTo(p2x, p2y).tagPlane("h2")
|
|
|
|
|
|
|
|
def markedCylOf(r):
|
|
|
|
cyl = (
|
|
|
|
Cq.Workplane('XY')
|
|
|
|
.cylinder(radius=r, height=r)
|
|
|
|
)
|
|
|
|
cyl.faces("<Z").tag("mate")
|
|
|
|
return cyl
|
|
|
|
|
|
|
|
assembly = (
|
|
|
|
Cq.Assembly()
|
|
|
|
.add(board, name="board", color=color_parent)
|
|
|
|
.add(markedCylOf(2), name="c4", color=color_child)
|
|
|
|
.add(markedCylOf(1.5), name="c3", color=color_child)
|
|
|
|
.add(markedCylOf(1), name="c2", color=color_child)
|
|
|
|
.constrain("board?h4", "c4?mate", "Plane", param=0)
|
|
|
|
.constrain("board?h3", "c3?mate", "Plane", param=0)
|
|
|
|
.constrain("board?h2", "c2?mate", "Plane", param=0)
|
|
|
|
.solve()
|
|
|
|
)
|
|
|
|
self.assertEqual(nhf.checks.pairwise_intersection(assembly), [])
|
|
|
|
bbox = assembly.toCompound().BoundingBox()
|
|
|
|
self.assertAlmostEqual(bbox.xlen, 15)
|
|
|
|
self.assertAlmostEqual(bbox.ylen, 15)
|
|
|
|
self.assertAlmostEqual(bbox.zlen, 5)
|
2024-06-25 06:11:48 -07:00
|
|
|
|
2024-07-20 23:52:11 -07:00
|
|
|
def test_abs_location(self):
|
|
|
|
box = Cq.Solid.makeBox(1, 1, 1)
|
|
|
|
assembly = (
|
|
|
|
Cq.Assembly()
|
|
|
|
.add(box, name="b1")
|
|
|
|
.add(box, name="b2", loc=Cq.Location((0,0,1)))
|
|
|
|
.add(box, name="b3", loc=Cq.Location((0,0,2)))
|
|
|
|
)
|
|
|
|
(x, y, z), _ = assembly.get_abs_location("b2@faces@>Y").toTuple()
|
|
|
|
self.assertAlmostEqual(x, 0.5)
|
|
|
|
self.assertAlmostEqual(y, 1)
|
|
|
|
self.assertAlmostEqual(z, 1.5)
|
|
|
|
(rx, ry, rz), _ = assembly.get_abs_direction("b2@faces@>Y").toTuple()
|
|
|
|
self.assertAlmostEqual(rx, 0)
|
|
|
|
self.assertAlmostEqual(ry, 1)
|
|
|
|
self.assertAlmostEqual(rz, 0)
|
|
|
|
|
2024-06-20 23:29:18 -07:00
|
|
|
if __name__ == '__main__':
|
|
|
|
unittest.main()
|