def test_construction(self): # Radius/diameter with self.assertNothingRaised(): sphere = Sphere(1) # Zero size with self.assertWarnsRegex(UserWarning, r'radius is 0'): Sphere(0)
def test_equality(self): # Same object self.assertEqualToItself(Sphere(11)) # Equal object self.assertEqual(Sphere(11), Sphere(11)) # Different objects self.assertNotEqual(Sphere(11), Sphere(22))
def test_to_scad(self): sphere = Sphere(2) cube = Cuboid(10, 10, 10) cylinder = Frustum(origin, Z, 11, 11) self.assertEqual( Difference([sphere, cube, cylinder]).to_scad(), ScadObject("difference", None, None, [ sphere.to_scad(), cube.to_scad(), cylinder.to_scad(), ]))
def test_sum(self): sphere = Sphere(2) cube = Cuboid(10, 10, 10) cylinder = Frustum(origin, Z, 11, 11) objects = [sphere, cube, cylinder] self.assertEqual(sum(objects, Union.empty()), Union(objects))
def test_to_scad(self): sphere = Sphere(2) cube = Cuboid(10, 10, 10) cylinder = Frustum(origin, Z, 11, 11) self.assertEqual( Union([sphere, cube, cylinder]).to_scad(), ScadObject("union", None, None, [ sphere.to_scad(), cube.to_scad(), cylinder.to_scad(), ])) # Empty self.assertEqual( Union([]).to_scad(), ScadObject("union", None, None, None))
def test_sphere_generators(self): self.assertEqual(sphere(2), Sphere(2)) self.assertEqual(sphere(r=2), Sphere(r=2)) self.assertEqual(sphere(d=2), Sphere(r=1)) # Invalid with self.assertRaises(TypeError): sphere(r="2") with self.assertRaises(TypeError): sphere(d="2") # Errors caught by _get_radius with self.assertRaises(TypeError): sphere(r=2, d=2) # Both radius and diameter with self.assertRaises(TypeError): sphere() # Neither radius nor diameter
def test_construction(self): sphere = Sphere(11) cube = Cuboid(22, 22, 22) cylinder = Frustum(origin, Z, 11, 11) object_list = [sphere, cube, cylinder] # Empty Csg([]) # With objects self.assertEqual(Csg(object_list).children, object_list) # With generator self.assertEqual(Csg(o for o in object_list).children, object_list) # With invalid objects with self.assertRaises(TypeError): Csg(None) # None instead of empty list with self.assertRaises(TypeError): Csg([Sphere]) # Class instead of object with self.assertRaises(TypeError): Csg(sphere) # Object instead of list with self.assertRaises(TypeError): Csg([None]) # List with invalid value with self.assertRaises(TypeError): Csg([sphere, None]) # List with object and invalid value
def test_to_scad(self): sphere = Sphere(2) cube = Cuboid(10, 10, 10) cylinder = Frustum(origin, Z, 5, 5) mixed = Union( [Intersection([sphere, cylinder]), Difference([cube, sphere])]) self.assertEqual( mixed.to_scad(), ScadObject("union", None, None, [ ScadObject( "intersection", None, None, [sphere.to_scad(), cylinder.to_scad()]), ScadObject("difference", None, None, [cube.to_scad(), sphere.to_scad()]), ]))
def test_csg_generators(self): sphere = Sphere(11) cuboid = Cuboid(11, 22, 33) cylinder = Frustum(origin, Z, 11, 11) object_list = [sphere, cuboid, cylinder] self.assertEqual(union(object_list), Union(object_list)) self.assertEqual(difference(object_list), Difference(object_list)) self.assertEqual(intersection(object_list), Intersection(object_list))
def test_equality(self): sphere = Sphere(11) cube = Cuboid(22, 22, 22) cylinder = Frustum(origin, Z, 11, 11) objects = [sphere, cube, cylinder] # Different types of CSG are not equal, even if their children are identical self.assertNotEqual(Union(objects), Intersection(objects)) self.assertNotEqual(Intersection(objects), Difference(objects)) self.assertNotEqual(Difference(objects), Union(objects))
def test_operators_with_transforms(self): a = Sphere(2) t = Translate([0, 0, 0]) # The only operation we can do with a Transform is Transform*Object, which results in a Transformed Object. with self.assertRaises(TypeError): a + t with self.assertRaises(TypeError): a - t with self.assertRaises(TypeError): a * t with self.assertRaises(TypeError): t + a with self.assertRaises(TypeError): t - a self.assertEqual(t * a, Transformed(t, a))
def test_multiplication_with_object_and_transform(self): # Multiplication is used for both intersection (Object * Object) and transform (Transform * Object) a = Sphere(2) b = Cuboid(3, 3, 3) s = ScaleAxes(1, 2, -1) t = Translate([0, 0, 0]) self.assertEqual( t * (a * b), Transformed(t, Intersection([a, b]))) self.assertEqual((t * a) * b , Intersection([Transformed(t, a), b])) self.assertEqual((s * t) * a , Transformed(Chained([s, t]), a)) self.assertEqual( s * (t * a), Transformed(Chained([s, t]), a))
def test_invalid_operations(self): a = Sphere(2) b = Cuboid(10, 10, 10) s = ScaleUniform(1) t = Translate([0, 0, 0]) for target in [a, t, t*a, a+b, a-b, a*b, s*t]: for invalid in [None, 0, 0.0, ""]: with self.assertRaises(TypeError): target + invalid with self.assertRaises(TypeError): target - invalid with self.assertRaises(TypeError): target * invalid with self.assertRaises(TypeError): invalid + target with self.assertRaises(TypeError): invalid - target with self.assertRaises(TypeError): invalid * target
def test_multiplication(self): a = Sphere(2) b = Cuboid(10, 10, 10) c = Frustum(origin, Z, 11, 11) d = Cuboid(20, 20, 20) self.assertEqual( a * b , Intersection([a, b ])) self.assertEqual( c * c , Intersection([c, c ])) self.assertEqual( (a * b) * c , Intersection([a, b, c ])) self.assertEqual( a * (b * c) , Intersection([a, b, c ])) self.assertEqual( a * b * c * d , Intersection([a, b, c, d])) self.assertEqual( ((a * b) * c) * d , Intersection([a, b, c, d])) self.assertEqual( a * (b * (c * d)), Intersection([a, b, c, d])) self.assertEqual( (a * b) * (c * d) , Intersection([a, b, c, d]))
def sphere(r=None, d=None): """Generate a sphere. Signatures (canonical forms): * sphere(r = radius) * sphere(d = diameter) Signatures (convenience forms): * sphere(radius) The sphere will be centered at the origin. """ r = _get_radius(r, d) return Sphere(r)
def test_subtraction(self): a = Sphere(2) b = Cuboid(10, 10, 10) c = Frustum(origin, Z, 11, 11) d = Cuboid(20, 20, 20) # Difference is non-associative, so we get nested differences self.assertEqual( a - b , Difference([a, b ])) self.assertEqual( c - c , Difference([c, c ])) self.assertEqual( (a - b) - c , Difference([a, b, c ])) self.assertEqual( a - (b - c) , Difference([a, Difference([b, c])])) self.assertEqual( a - b - c - d , Difference([a, b, c, d])) self.assertEqual( ((a - b) - c) - d , Difference([a, b, c, d])) self.assertEqual( a - (b - (c - d)), Difference([a, Difference([b, Difference([c, d])])])) self.assertEqual( (a - b) - (c - d) , Difference([Difference([a, b]), Difference([c, d])]))
def test_addition(self): a = Sphere(2) b = Cuboid(10, 10, 10) c = Frustum(origin, Z, 11, 11) d = Cuboid(20, 20, 20) self.assertEqual( a + b , Union([a, b ])) self.assertEqual( c + c , Union([c, c ])) self.assertEqual( (a + b) + c , Union([a, b, c ])) self.assertEqual( a + (b + c) , Union([a, b, c ])) self.assertEqual( a + b + c + d , Union([a, b, c, d])) self.assertEqual( ((a + b) + c) + d , Union([a, b, c, d])) self.assertEqual( a + (b + (c + d)), Union([a, b, c, d])) self.assertEqual( (a + b) + (c + d) , Union([a, b, c, d])) # Empty union self.assertEqual(Union([]) + Union([]), Union([])) self.assertEqual(Union([]) + a, Union([a])) self.assertEqual(a + Union([]), Union([a]))
def test_equality(self): sphere = Sphere(11) cuboid = Cuboid(11, 22, 33) cylinder = Frustum(origin, Z, 11, 11) objects = [sphere, cuboid, cylinder] # Same object self.assertEqualToItself(Union([])) self.assertEqualToItself(Union(objects)) # Equal objects self.assertEqual(Union([]), Union([])) self.assertEqual(Union(objects), Union(objects)) # Different objects self.assertNotEqual(Union(objects), Union([sphere, cuboid])) self.assertNotEqual(Union([cuboid, sphere]), Union([sphere, cuboid])) # Equal objects from different specifications self.assertEqual(Union.empty(), Union([]))
def test_render_to_file(self): part = Sphere(0.6) + Cuboid(1, 2, 3) - Frustum([0, 0, 0], [0, 0, 4], 0.5, 0.5) expected_file_name = os.path.join(os.path.dirname(__file__), "test_scad_object_render_to_file_expected.scad") actual_file_name = os.path.join(os.path.dirname(__file__), "test_scad_object_render_to_file_actual.scad") self.assertTrue(os.path.isfile(expected_file_name)) self.assertFalse(os.path.exists(actual_file_name)) try: render_to_file(part, actual_file_name, fn=60) with open(actual_file_name) as actual_file: actual = actual_file.read() with open(expected_file_name) as expected_file: expected = expected_file.read() self.assertNotEqual(expected, "") self.assertEqual(actual, expected) finally: if os.path.exists(actual_file_name): os.unlink(actual_file_name)
def test_to_tree(self): a = Sphere(2) b = Cuboid(3, 3, 3) s = ScaleAxes(1, 2, -1) t = Translate([0, 0, 0]) part = a + s*t*b actual = part.to_tree() expected = Node(part, [ Node(a), Node(s*t*b, [ Node(s*t, [ Node(s), Node(t), ]), Node(b), ]), ]) self.assertEqual(actual, expected)
def test_to_scad(self): # Primitives self.assertScadObject(Sphere(11), "sphere", [11], None, None)
def test_str(self): self.assertStr(Sphere(11), "Sphere with radius 11")
from cadlib.object.primitives import Sphere, Cuboid, Frustum # from cadlib.object.generators import * #from cadlib.transform.primitives import RotateXyz, ScaleAxes, Translate from cadlib.util.vector import X, Y, Z from cadlib.scad import render_to_file # def test_case(name, object): # print(name) # print(" Cadlib tree:") # print(object.to_tree().format(top_indent=" ")) # print(" OpenSCAD tree:") # print(object.to_scad().to_tree().format(top_indent=" ")) # print(" OpenSCAD source:") # print(object.to_scad().to_code(top_indent=" ")) c = Cuboid(50, 50, 50).rotate(Z, 30).right(25) #c = Frustum(0, 20*Y, 5, 5) # TODO base/cap/center print(c.to_tree().format()) s = Sphere(25) #c2 = Cuboid(10, 10, 10).top_face.at([0, 0, 0]) assembly = c + s.center.at(c.top_face) + c2 print(assembly.to_scad().to_tree().format()) print(assembly.to_scad().to_code()) render_to_file(assembly, "anchor_test.scad", fn=30)
def test_repr(self): self.assertRepr(Sphere(11), "Sphere(r=11)")
from cadlib.object.primitives import Cuboid, Cylinder, Sphere from cadlib.util.vector import Z def test_case(name, object): print(name) print(" Cadlib tree:") print(object.to_tree().format(top_indent=" ")) print(" OpenSCAD tree:") print(object.to_scad().to_tree().format(top_indent=" ")) o1 = Cuboid(10, 10, 10) o2 = Cylinder(Z, 5, 5) o3 = Sphere(2) test_case("2-intersection", o1 * o2) test_case("3-intersection (1)", (o1 * o2) * o3) test_case("3-intersection (2)", o1 * (o2 * o3)) test_case("2-union", o1 + o2) test_case("2-difference", o1 - o2)