#! /usr/bin/env python # -*- coding: utf-8 -*- # Author: Hamilton Kibbe <ham@hamiltonkib.be> import pytest from operator import add from ..primitives import * def test_primitive_smoketest(): p = Primitive() try: p.bounding_box assert not True, "should have thrown the exception" except NotImplementedError: pass # pytest.raises(NotImplementedError, p.bounding_box) p.to_metric() p.to_inch() # try: # p.offset(1, 1) # assert_false(True, 'should have thrown the exception') # except NotImplementedError: # pass def test_line_angle(): """ Test Line primitive angle calculation """ cases = [ ((0, 0), (1, 0), math.radians(0)), ((0, 0), (1, 1), math.radians(45)), ((0, 0), (0, 1), math.radians(90)), ((0, 0), (-1, 1), math.radians(135)), ((0, 0), (-1, 0), math.radians(180)), ((0, 0), (-1, -1), math.radians(225)), ((0, 0), (0, -1), math.radians(270)), ((0, 0), (1, -1), math.radians(315)), ] for start, end, expected in cases: l = Line(start, end, 0) line_angle = (l.angle + 2 * math.pi) % (2 * math.pi) pytest.approx(line_angle, expected) def test_line_bounds(): """ Test Line primitive bounding box calculation """ cases = [ ((0, 0), (1, 1), ((-1, -1), (2, 2))), ((-1, -1), (1, 1), ((-2, -2), (2, 2))), ((1, 1), (-1, -1), ((-2, -2), (2, 2))), ((-1, 1), (1, -1), ((-2, -2), (2, 2))), ] c = Circle((0, 0), 2) r = Rectangle((0, 0), 2, 2) for shape in (c, r): for start, end, expected in cases: l = Line(start, end, shape) assert l.bounding_box == expected # Test a non-square rectangle r = Rectangle((0, 0), 3, 2) cases = [ ((0, 0), (1, 1), ((-1.5, -1), (2.5, 2))), ((-1, -1), (1, 1), ((-2.5, -2), (2.5, 2))), ((1, 1), (-1, -1), ((-2.5, -2), (2.5, 2))), ((-1, 1), (1, -1), ((-2.5, -2), (2.5, 2))), ] for start, end, expected in cases: l = Line(start, end, r) assert l.bounding_box == expected def test_line_vertices(): c = Circle((0, 0), 2) l = Line((0, 0), (1, 1), c) assert l.vertices == None # All 4 compass points, all 4 quadrants and the case where start == end test_cases = [ ((0, 0), (1, 0), ((-1, -1), (-1, 1), (2, 1), (2, -1))), ((0, 0), (1, 1), ((-1, -1), (-1, 1), (0, 2), (2, 2), (2, 0), (1, -1))), ((0, 0), (0, 1), ((-1, -1), (-1, 2), (1, 2), (1, -1))), ((0, 0), (-1, 1), ((-1, -1), (-2, 0), (-2, 2), (0, 2), (1, 1), (1, -1))), ((0, 0), (-1, 0), ((-2, -1), (-2, 1), (1, 1), (1, -1))), ((0, 0), (-1, -1), ((-2, -2), (1, -1), (1, 1), (-1, 1), (-2, 0), (0, -2))), ((0, 0), (0, -1), ((-1, -2), (-1, 1), (1, 1), (1, -2))), ((0, 0), (1, -1), ((-1, -1), (0, -2), (2, -2), (2, 0), (1, 1), (-1, 1))), ((0, 0), (0, 0), ((-1, -1), (-1, 1), (1, 1), (1, -1))), ] r = Rectangle((0, 0), 2, 2) for start, end, vertices in test_cases: l = Line(start, end, r) assert set(vertices) == set(l.vertices) def test_line_conversion(): c = Circle((0, 0), 25.4, units="metric") l = Line((2.54, 25.4), (254.0, 2540.0), c, units="metric") # No effect l.to_metric() assert l.start == (2.54, 25.4) assert l.end == (254.0, 2540.0) assert l.aperture.diameter == 25.4 l.to_inch() assert l.start == (0.1, 1.0) assert l.end == (10.0, 100.0) assert l.aperture.diameter == 1.0 # No effect l.to_inch() assert l.start == (0.1, 1.0) assert l.end == (10.0, 100.0) assert l.aperture.diameter == 1.0 c = Circle((0, 0), 1.0, units="inch") l = Line((0.1, 1.0), (10.0, 100.0), c, units="inch") # No effect l.to_inch() assert l.start == (0.1, 1.0) assert l.end == (10.0, 100.0) assert l.aperture.diameter == 1.0 l.to_metric() assert l.start == (2.54, 25.4) assert l.end == (254.0, 2540.0) assert l.aperture.diameter == 25.4 # No effect l.to_metric() assert l.start == (2.54, 25.4) assert l.end == (254.0, 2540.0) assert l.aperture.diameter == 25.4 r = Rectangle((0, 0), 25.4, 254.0, units="metric") l = Line((2.54, 25.4), (254.0, 2540.0), r, units="metric") l.to_inch() assert l.start == (0.1, 1.0) assert l.end == (10.0, 100.0) assert l.aperture.width == 1.0 assert l.aperture.height == 10.0 r = Rectangle((0, 0), 1.0, 10.0, units="inch") l = Line((0.1, 1.0), (10.0, 100.0), r, units="inch") l.to_metric() assert l.start == (2.54, 25.4) assert l.end == (254.0, 2540.0) assert l.aperture.width == 25.4 assert l.aperture.height == 254.0 def test_line_offset(): c = Circle((0, 0), 1) l = Line((0, 0), (1, 1), c) l.offset(1, 0) assert l.start == (1.0, 0.0) assert l.end == (2.0, 1.0) l.offset(0, 1) assert l.start == (1.0, 1.0) assert l.end == (2.0, 2.0) def test_arc_radius(): """ Test Arc primitive radius calculation """ cases = [((-3, 4), (5, 0), (0, 0), 5), ((0, 1), (1, 0), (0, 0), 1)] for start, end, center, radius in cases: a = Arc(start, end, center, "clockwise", 0, "single-quadrant") assert a.radius == radius def test_arc_sweep_angle(): """ Test Arc primitive sweep angle calculation """ cases = [ ((1, 0), (0, 1), (0, 0), "counterclockwise", math.radians(90)), ((1, 0), (0, 1), (0, 0), "clockwise", math.radians(270)), ((1, 0), (-1, 0), (0, 0), "clockwise", math.radians(180)), ((1, 0), (-1, 0), (0, 0), "counterclockwise", math.radians(180)), ] for start, end, center, direction, sweep in cases: c = Circle((0, 0), 1) a = Arc(start, end, center, direction, c, "single-quadrant") assert a.sweep_angle == sweep def test_arc_bounds(): """ Test Arc primitive bounding box calculation """ cases = [ (( 1, 0), ( 0, 1), (0, 0), "clockwise", ((-1.5, -1.5), (1.5, 1.5))), (( 1, 0), ( 0, 1), (0, 0), "counterclockwise", ((-0.5, -0.5), (1.5, 1.5))), (( 0, 1), (-1, 0), (0, 0), "clockwise", ((-1.5, -1.5), (1.5, 1.5))), (( 0, 1), (-1, 0), (0, 0), "counterclockwise", ((-1.5, -0.5), (0.5, 1.5))), ((-1, 0), ( 0, -1), (0, 0), "clockwise", ((-1.5, -1.5), (1.5, 1.5))), ((-1, 0), ( 0, -1), (0, 0), "counterclockwise", ((-1.5, -1.5), (0.5, 0.5))), (( 0, -1), ( 1, 0), (0, 0), "clockwise", ((-1.5, -1.5), (1.5, 1.5))), (( 0, -1), ( 1, 0), (0, 0), "counterclockwise", ((-0.5, -1.5), (1.5, 0.5))), # Arcs with the same start and end point render a full circle (( 1, 0), ( 1, 0), (0, 0), "clockwise", ((-1.5, -1.5), (1.5, 1.5))), (( 1, 0), ( 1, 0), (0, 0), "counterclockwise", ((-1.5, -1.5), (1.5, 1.5))), ] for start, end, center, direction, bounds in cases: c = Circle((0, 0), 1) a = Arc(start, end, center, direction, c, "multi-quadrant") assert a.bounding_box == bounds def test_arc_bounds_no_aperture(): """ Test Arc primitive bounding box calculation ignoring aperture """ cases = [ ((1, 0), (0, 1), (0, 0), "clockwise", ((-1.0, -1.0), (1.0, 1.0))), ((1, 0), (0, 1), (0, 0), "counterclockwise", ((0.0, 0.0), (1.0, 1.0))), ((0, 1), (-1, 0), (0, 0), "clockwise", ((-1.0, -1.0), (1.0, 1.0))), ((0, 1), (-1, 0), (0, 0), "counterclockwise", ((-1.0, 0.0), (0.0, 1.0))), ((-1, 0), (0, -1), (0, 0), "clockwise", ((-1.0, -1.0), (1.0, 1.0))), ((-1, 0), (0, -1), (0, 0), "counterclockwise", ((-1.0, -1.0), (0.0, 0.0))), ((0, -1), (1, 0), (0, 0), "clockwise", ((-1.0, -1.0), (1.0, 1.0))), ((0, -1), (1, 0), (0, 0), "counterclockwise", ((-0.0, -1.0), (1.0, 0.0))), # Arcs with the same start and end point render a full circle ((1, 0), (1, 0), (0, 0), "clockwise", ((-1.0, -1.0), (1.0, 1.0))), ((1, 0), (1, 0), (0, 0), "counterclockwise", ((-1.0, -1.0), (1.0, 1.0))), ] for start, end, center, direction, bounds in cases: c = Circle((0, 0), 1) a = Arc(start, end, center, direction, c, "multi-quadrant") assert a.bounding_box_no_aperture == bounds def test_arc_conversion(): c = Circle((0, 0), 25.4, units="metric") a = Arc( (2.54, 25.4), (254.0, 2540.0), (25400.0, 254000.0), "clockwise", c, "single-quadrant", units="metric", ) # No effect a.to_metric() assert a.start == (2.54, 25.4) assert a.end == (254.0, 2540.0) assert a.center == (25400.0, 254000.0) assert a.aperture.diameter == 25.4 a.to_inch() assert a.start == (0.1, 1.0) assert a.end == (10.0, 100.0) assert a.center == (1000.0, 10000.0) assert a.aperture.diameter == 1.0 # no effect a.to_inch() assert a.start == (0.1, 1.0) assert a.end == (10.0, 100.0) assert a.center == (1000.0, 10000.0) assert a.aperture.diameter == 1.0 c = Circle((0, 0), 1.0, units="inch") a = Arc( (0.1, 1.0), (10.0, 100.0), (1000.0, 10000.0), "clockwise", c, "single-quadrant", units="inch", ) a.to_metric() assert a.start == (2.54, 25.4) assert a.end == (254.0, 2540.0) assert a.center == (25400.0, 254000.0) assert a.aperture.diameter == 25.4 def test_arc_offset(): c = Circle((0, 0), 1) a = Arc((0, 0), (1, 1), (2, 2), "clockwise", c, "single-quadrant") a.offset(1, 0) assert a.start == (1.0, 0.0) assert a.end == (2.0, 1.0) assert a.center == (3.0, 2.0) a.offset(0, 1) assert a.start == (1.0, 1.0) assert a.end == (2.0, 2.0) assert a.center == (3.0, 3.0) def test_circle_radius(): """ Test Circle primitive radius calculation """ c = Circle((1, 1), 2) assert c.radius == 1 def test_circle_hole_radius(): """ Test Circle primitive hole radius calculation """ c = Circle((1, 1), 4, 2) assert c.hole_radius == 1 def test_circle_bounds(): """ Test Circle bounding box calculation """ c = Circle((1, 1), 2) assert c.bounding_box == ((0, 0), (2, 2)) def test_circle_conversion(): """Circle conversion of units""" # Circle initially metric, no hole c = Circle((2.54, 25.4), 254.0, units="metric") c.to_metric() # shouldn't do antyhing assert c.position == (2.54, 25.4) assert c.diameter == 254.0 assert c.hole_diameter == None c.to_inch() assert c.position == (0.1, 1.0) assert c.diameter == 10.0 assert c.hole_diameter == None # no effect c.to_inch() assert c.position == (0.1, 1.0) assert c.diameter == 10.0 assert c.hole_diameter == None # Circle initially metric, with hole c = Circle((2.54, 25.4), 254.0, 127.0, units="metric") c.to_metric() # shouldn't do antyhing assert c.position == (2.54, 25.4) assert c.diameter == 254.0 assert c.hole_diameter == 127.0 c.to_inch() assert c.position == (0.1, 1.0) assert c.diameter == 10.0 assert c.hole_diameter == 5.0 # no effect c.to_inch() assert c.position == (0.1, 1.0) assert c.diameter == 10.0 assert c.hole_diameter == 5.0 # Circle initially inch, no hole c = Circle((0.1, 1.0), 10.0, units="inch") # No effect c.to_inch() assert c.position == (0.1, 1.0) assert c.diameter == 10.0 assert c.hole_diameter == None c.to_metric() assert c.position == (2.54, 25.4) assert c.diameter == 254.0 assert c.hole_diameter == None # no effect c.to_metric() assert c.position == (2.54, 25.4) assert c.diameter == 254.0 assert c.hole_diameter == None c = Circle((0.1, 1.0), 10.0, 5.0, units="inch") # No effect c.to_inch() assert c.position == (0.1, 1.0) assert c.diameter == 10.0 assert c.hole_diameter == 5.0 c.to_metric() assert c.position == (2.54, 25.4) assert c.diameter == 254.0 assert c.hole_diameter == 127.0 # no effect c.to_metric() assert c.position == (2.54, 25.4) assert c.diameter == 254.0 assert c.hole_diameter == 127.0 def test_circle_offset(): c = Circle((0, 0), 1) c.offset(1, 0) assert c.position == (1.0, 0.0) c.offset(0, 1) assert c.position == (1.0, 1.0) def test_rectangle_ctor(): """ Test rectangle creation """ test_cases = (((0, 0), 1, 1), ((0, 0), 1, 2), ((1, 1), 1, 2)) for pos, width, height in test_cases: r = Rectangle(pos, width, height) assert r.position == pos assert r.width == width assert r.height == height def test_rectangle_hole_radius(): """ Test rectangle hole diameter calculation """ r = Rectangle((0, 0), 2, 2) assert 0 == r.hole_radius r = Rectangle((0, 0), 2, 2, 1) assert 0.5 == r.hole_radius def test_rectangle_bounds(): """ Test rectangle bounding box calculation """ r = Rectangle((0, 0), 2, 2) bounds = r.bounding_box pytest.approx(bounds[0], (-1, -1)) pytest.approx(bounds[1], (1, 1)) r = Rectangle((0, 0), 2, 2, rotation=45) bounds = r.bounding_box pytest.approx(bounds[0], (-math.sqrt(2), -math.sqrt(2))) pytest.approx(bounds[1], (math.sqrt(2), math.sqrt(2))) def test_rectangle_vertices(): sqrt2 = math.sqrt(2.0) TEST_VECTORS = [ ((0, 0), 2.0, 2.0, 0.0, ((-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0), (1.0, -1.0))), ((0, 0), 2.0, 3.0, 0.0, ((-1.0, -1.5), (-1.0, 1.5), (1.0, 1.5), (1.0, -1.5))), ((0, 0), 2.0, 2.0, 90.0, ((-1.0, -1.0), (-1.0, 1.0), (1.0, 1.0), (1.0, -1.0))), ((0, 0), 3.0, 2.0, 90.0, ((-1.0, -1.5), (-1.0, 1.5), (1.0, 1.5), (1.0, -1.5))), ( (0, 0), 2.0, 2.0, 45.0, ((-sqrt2, 0.0), (0.0, sqrt2), (sqrt2, 0), (0, -sqrt2)), ), ] for pos, width, height, rotation, expected in TEST_VECTORS: r = Rectangle(pos, width, height, rotation=rotation) for test, expect in zip(sorted(r.vertices), sorted(expected)): pytest.approx(test, expect) r = Rectangle((0, 0), 2.0, 2.0, rotation=0.0) r.rotation = 45.0 for test, expect in zip( sorted(r.vertices), sorted(((-sqrt2, 0.0), (0.0, sqrt2), (sqrt2, 0), (0, -sqrt2))), ): pytest.approx(test, expect) def test_rectangle_segments(): r = Rectangle((0, 0), 2.0, 2.0) expected = [vtx for segment in r.segments for vtx in segment] for vertex in r.vertices: assert vertex in expected def test_rectangle_conversion(): """Test converting rectangles between units""" # Initially metric no hole r = Rectangle((2.54, 25.4), 254.0, 2540.0, units="metric") r.to_metric() assert r.position == (2.54, 25.4) assert r.width == 254.0 assert r.height == 2540.0 r.to_inch() assert r.position == (0.1, 1.0) assert r.width == 10.0 assert r.height == 100.0 r.to_inch() assert r.position == (0.1, 1.0) assert r.width == 10.0 assert r.height == 100.0 # Initially metric with hole r = Rectangle((2.54, 25.4), 254.0, 2540.0, 127.0, units="metric") r.to_metric() assert r.position == (2.54, 25.4) assert r.width == 254.0 assert r.height == 2540.0 assert r.hole_diameter == 127.0 r.to_inch() assert r.position == (0.1, 1.0) assert r.width == 10.0 assert r.height == 100.0 assert r.hole_diameter == 5.0 r.to_inch() assert r.position == (0.1, 1.0) assert r.width == 10.0 assert r.height == 100.0 assert r.hole_diameter == 5.0 # Initially inch, no hole r = Rectangle((0.1, 1.0), 10.0, 100.0, units="inch") r.to_inch() assert r.position == (0.1, 1.0) assert r.width == 10.0 assert r.height == 100.0 r.to_metric() assert r.position == (2.54, 25.4) assert r.width == 254.0 assert r.height == 2540.0 r.to_metric() assert r.position == (2.54, 25.4) assert r.width == 254.0 assert r.height == 2540.0 # Initially inch with hole r = Rectangle((0.1, 1.0), 10.0, 100.0, 5.0, units="inch") r.to_inch() assert r.position == (0.1, 1.0) assert r.width == 10.0 assert r.height == 100.0 assert r.hole_diameter == 5.0 r.to_metric() assert r.position == (2.54, 25.4) assert r.width == 254.0 assert r.height == 2540.0 assert r.hole_diameter == 127.0 r.to_metric() assert r.position == (2.54, 25.4) assert r.width == 254.0 assert r.height == 2540.0 assert r.hole_diameter == 127.0 def test_rectangle_offset(): r = Rectangle((0, 0), 1, 2) r.offset(1, 0) assert r.position == (1.0, 0.0) r.offset(0, 1) assert r.position == (1.0, 1.0) def test_round_rectangle_ctor(): """ Test round rectangle creation """ test_cases = ( ((0, 0), 1, 1, 0.2, (True, True, False, False)), ((0, 0), 1, 2, 0.3, (True, True, True, True)), ((1, 1), 1, 2, 0.4, (False, False, False, False)), ) for pos, width, height, radius, corners in test_cases: r = RoundRectangle(pos, width, height, radius, corners) assert r.position == pos assert r.width == width assert r.height == height assert r.radius == radius pytest.approx(r.corners, corners) def test_round_rectangle_bounds(): """ Test round rectangle bounding box calculation """ r = RoundRectangle((0, 0), 2, 2, 0.2, (True, True, False, False)) bounds = r.bounding_box pytest.approx(bounds[0], (-1, -1)) pytest.approx(bounds[1], (1, 1)) r = RoundRectangle((0, 0), 2, 2, 0.2, (True, True, False, False), rotation=45) bounds = r.bounding_box pytest.approx(bounds[0], (-math.sqrt(2), -math.sqrt(2))) pytest.approx(bounds[1], (math.sqrt(2), math.sqrt(2))) def test_obround_ctor(): """ Test obround creation """ test_cases = (((0, 0), 1, 1), ((0, 0), 1, 2), ((1, 1), 1, 2)) for pos, width, height in test_cases: o = Obround(pos, width, height) assert o.position == pos assert o.width == width assert o.height == height def test_obround_bounds(): """ Test obround bounding box calculation """ o = Obround((2, 2), 2, 4) bounds = o.bounding_box pytest.approx(bounds[0], (1, 0)) pytest.approx(bounds[1], (3, 4)) o = Obround((2, 2), 4, 2) bounds = o.bounding_box pytest.approx(bounds[0], (0, 1)) pytest.approx(bounds[1], (4, 3)) def test_obround_orientation(): o = Obround((0, 0), 2, 1) assert o.orientation == "horizontal" o = Obround((0, 0), 1, 2) assert o.orientation == "vertical" def test_obround_subshapes(): o = Obround((0, 0), 1, 4) ss = o.subshapes pytest.approx(ss["rectangle"].position, (0, 0)) pytest.approx(ss["circle1"].position, (0, 1.5)) pytest.approx(ss["circle2"].position, (0, -1.5)) o = Obround((0, 0), 4, 1) ss = o.subshapes pytest.approx(ss["rectangle"].position, (0, 0)) pytest.approx(ss["circle1"].position, (1.5, 0)) pytest.approx(ss["circle2"].position, (-1.5, 0)) def test_obround_conversion(): o = Obround((2.54, 25.4), 254.0, 2540.0, units="metric") # No effect o.to_metric() assert o.position == (2.54, 25.4) assert o.width == 254.0 assert o.height == 2540.0 o.to_inch() assert o.position == (0.1, 1.0) assert o.width == 10.0 assert o.height == 100.0 # No effect o.to_inch() assert o.position == (0.1, 1.0) assert o.width == 10.0 assert o.height == 100.0 o = Obround((0.1, 1.0), 10.0, 100.0, units="inch") # No effect o.to_inch() assert o.position == (0.1, 1.0) assert o.width == 10.0 assert o.height == 100.0 o.to_metric() assert o.position == (2.54, 25.4) assert o.width == 254.0 assert o.height == 2540.0 # No effect o.to_metric() assert o.position == (2.54, 25.4) assert o.width == 254.0 assert o.height == 2540.0 def test_obround_offset(): o = Obround((0, 0), 1, 2) o.offset(1, 0) assert o.position == (1.0, 0.0) o.offset(0, 1) assert o.position == (1.0, 1.0) def test_polygon_ctor(): """ Test polygon creation """ test_cases = (((0, 0), 3, 5, 0), ((0, 0), 5, 6, 0), ((1, 1), 7, 7, 45)) for pos, sides, radius, hole_diameter in test_cases: p = Polygon(pos, sides, radius, hole_diameter) assert p.position == pos assert p.sides == sides assert p.radius == radius assert p.hole_diameter == hole_diameter def test_polygon_bounds(): """ Test polygon bounding box calculation """ p = Polygon((2, 2), 3, 2, 0) bounds = p.bounding_box pytest.approx(bounds[0], (0, 0)) pytest.approx(bounds[0], (4, 4)) p = Polygon((2, 2), 3, 4, 0) bounds = p.bounding_box pytest.approx(bounds[0], (-2, -2)) pytest.approx(bounds[1], (6, 6)) def test_polygon_conversion(): p = Polygon((2.54, 25.4), 3, 254.0, 0, units="metric") # No effect p.to_metric() assert p.position == (2.54, 25.4) assert p.radius == 254.0 p.to_inch() assert p.position == (0.1, 1.0) assert p.radius == 10.0 # No effect p.to_inch() assert p.position == (0.1, 1.0) assert p.radius == 10.0 p = Polygon((0.1, 1.0), 3, 10.0, 0, units="inch") # No effect p.to_inch() assert p.position == (0.1, 1.0) assert p.radius == 10.0 p.to_metric() assert p.position == (2.54, 25.4) assert p.radius == 254.0 # No effect p.to_metric() assert p.position == (2.54, 25.4) assert p.radius == 254.0 def test_polygon_offset(): p = Polygon((0, 0), 5, 10, 0) p.offset(1, 0) assert p.position == (1.0, 0.0) p.offset(0, 1) assert p.position == (1.0, 1.0) def test_region_ctor(): """ Test Region creation """ apt = Circle((0, 0), 0) lines = ( Line((0, 0), (1, 0), apt), Line((1, 0), (1, 1), apt), Line((1, 1), (0, 1), apt), Line((0, 1), (0, 0), apt), ) points = ((0, 0), (1, 0), (1, 1), (0, 1)) r = Region(lines) for i, p in enumerate(lines): assert r.primitives[i] == p def test_region_bounds(): """ Test region bounding box calculation """ apt = Circle((0, 0), 0) lines = ( Line((0, 0), (1, 0), apt), Line((1, 0), (1, 1), apt), Line((1, 1), (0, 1), apt), Line((0, 1), (0, 0), apt), ) r = Region(lines) bounds = r.bounding_box pytest.approx(bounds[0], (0, 0)) pytest.approx(bounds[1], (1, 1)) def test_region_offset(): apt = Circle((0, 0), 0) lines = ( Line((0, 0), (1, 0), apt), Line((1, 0), (1, 1), apt), Line((1, 1), (0, 1), apt), Line((0, 1), (0, 0), apt), ) r = Region(lines) xlim, ylim = r.bounding_box r.offset(0, 1) new_xlim, new_ylim = r.bounding_box pytest.approx(new_xlim, xlim) pytest.approx(new_ylim, tuple([y + 1 for y in ylim])) def test_drill_ctor(): """ Test drill primitive creation """ test_cases = (((0, 0), 2), ((1, 1), 3), ((2, 2), 5)) for position, diameter in test_cases: d = Drill(position, diameter) assert d.position == position assert d.diameter == diameter assert d.radius == diameter / 2.0 def test_drill_ctor_validation(): """ Test drill argument validation """ pytest.raises(TypeError, Drill, 3, 5) pytest.raises(TypeError, Drill, (3, 4, 5), 5) def test_drill_bounds(): d = Drill((0, 0), 2) bounds = d.bounding_box pytest.approx(bounds[0], (-1, -1)) pytest.approx(bounds[1], (1, 1)) d = Drill((1, 2), 2) bounds = d.bounding_box pytest.approx(bounds[0], (0, 1)) pytest.approx(bounds[1], (2, 3)) def test_drill_conversion(): d = Drill((2.54, 25.4), 254.0, units="metric") # No effect d.to_metric() assert d.position == (2.54, 25.4) assert d.diameter == 254.0 d.to_inch() assert d.position == (0.1, 1.0) assert d.diameter == 10.0 # No effect d.to_inch() assert d.position == (0.1, 1.0) assert d.diameter == 10.0 d = Drill((0.1, 1.0), 10.0, units="inch") # No effect d.to_inch() assert d.position == (0.1, 1.0) assert d.diameter == 10.0 d.to_metric() assert d.position == (2.54, 25.4) assert d.diameter == 254.0 # No effect d.to_metric() assert d.position == (2.54, 25.4) assert d.diameter == 254.0 def test_drill_offset(): d = Drill((0, 0), 1.0) d.offset(1, 0) assert d.position == (1.0, 0.0) d.offset(0, 1) assert d.position == (1.0, 1.0) def test_drill_equality(): d = Drill((2.54, 25.4), 254.0) d1 = Drill((2.54, 25.4), 254.0) assert d == d1 d1 = Drill((2.54, 25.4), 254.2) assert d != d1 def test_slot_bounds(): """ Test Slot primitive bounding box calculation """ cases = [ (( 0, 0), ( 1, 1), ((-1, -1), (2, 2))), ((-1, -1), ( 1, 1), ((-2, -2), (2, 2))), (( 1, 1), (-1, -1), ((-2, -2), (2, 2))), ((-1, 1), ( 1, -1), ((-2, -2), (2, 2))), ] for start, end, expected in cases: s = Slot(start, end, 2.0) assert s.bounding_box == expected