def test_distance_values_for_square_triangle(): """Check shape distance of a triangle with infinite slopes.""" verts = np.array([[1, 1], [-1, 0], [1, -1]]) theta = np.linspace(0, 2 * np.pi, 1000000) shape = ConvexPolygon(verts) distance = shape.distance_to_surface(theta) assert_distance_to_surface_2d(shape, theta, distance)
def test_convex_polygon_distance_to_surface_unit_area_ngon_non_first_quadrant( shape, ): """Check shape distance consistency with the relaxation of first quadrant vertex.""" theta = np.linspace(0, 2 * np.pi, 1000000) # Roll the verts so we don't start in first quadrant verts = np.roll(shape.vertices, 1, axis=0) shape = ConvexPolygon(verts) distance = shape.distance_to_surface(theta) assert_distance_to_surface_2d(shape, theta, distance)
def test_nonregular_convex_polygon_distance_to_surface_unit_area_ngon(shape): """Check shape distance consistency with perimeter and area.""" theta = np.linspace(0, 2 * np.pi, 1000000) verts = shape.vertices[:, :2] # shift making shape a nonregular polygon verts[0, 1] = verts[0, 1] + 0.2 shape = ConvexPolygon(verts) distance = shape.distance_to_surface(theta) assert_distance_to_surface_2d(shape, theta, distance)
def test_is_inside(convex_square): rotated_square = ConvexPolygon(convex_square.vertices[::-1, :]) assert convex_square.is_inside(convex_square.center) assert rotated_square.is_inside(rotated_square.center) @given(floats(0, 1), floats(0, 1)) def testfun(x, y): assert convex_square.is_inside([[x, y, 0]]) assert rotated_square.is_inside([[x, y, 0]]) testfun()
def test_set_perimeter(square_points): """Test the perimeter and circumference setter.""" original_square = ConvexPolygon(square_points) square = ConvexPolygon(square_points) @given(floats(0.1, 1000)) def testfun(value): square.perimeter = value assert square.perimeter == approx(value) assert square.vertices == approx(original_square.vertices * (value / original_square.perimeter)) testfun()
def test_inertia_tensor(square): """Test the inertia tensor calculation.""" square.center = (0, 0, 0) assert np.sum(square.inertia_tensor > 1e-6) == 1 assert square.inertia_tensor[2, 2] == 1 / 6 # Validate yz plane. rotation = rowan.from_axis_angle([0, 1, 0], np.pi / 2) rotated_verts = rowan.rotate(rotation, square.vertices) rotated_square = ConvexPolygon(rotated_verts) assert np.sum(rotated_square.inertia_tensor > 1e-6) == 1 assert rotated_square.inertia_tensor[0, 0] == 1 / 6 # Validate xz plane. rotation = rowan.from_axis_angle([1, 0, 0], np.pi / 2) rotated_verts = rowan.rotate(rotation, square.vertices) rotated_square = ConvexPolygon(rotated_verts) assert np.sum(rotated_square.inertia_tensor > 1e-6) == 1 assert rotated_square.inertia_tensor[1, 1] == 1 / 6 # Validate translation along each axis. delta = 2 area = square.area for i in range(3): translation = [0] * 3 translation[i] = delta translated_verts = square.vertices + translation translated_square = ConvexPolygon(translated_verts) offdiagonal_tensor = translated_square.inertia_tensor.copy() diag_indices = np.diag_indices(3) offdiagonal_tensor[diag_indices] = 0 assert np.sum(offdiagonal_tensor > 1e-6) == 0 expected_diagonals = [0, 0, 1 / 6] for j in range(3): if i != j: expected_diagonals[j] += area * delta * delta assert np.allclose(np.diag(translated_square.inertia_tensor), expected_diagonals)
def test_distance_to_surface_unit_area_ngon_vertex_distance(shape, ): """Check that the actual distances are computed correctly.""" distances = np.linalg.norm(shape.vertices - shape.center, axis=-1) theta = np.linspace(0, 2 * np.pi, shape.num_vertices + 1) assert np.allclose(shape.distance_to_surface(theta)[:-1], distances) # Try a positive rotation. verts = rowan.rotate(rowan.from_axis_angle([0, 0, 1], 0.1), shape.vertices) shape = ConvexPolygon(verts) assert np.allclose(shape.distance_to_surface(theta + 0.1)[:-1], distances) # Now try a negative rotation. verts = rowan.rotate(rowan.from_axis_angle([0, 0, 1], -0.2), shape.vertices) shape = ConvexPolygon(verts) assert np.allclose(shape.distance_to_surface(theta - 0.1)[:-1], distances)
def test_convex_polygon_distance_to_surface_unit_area_ngon_rotated(shape, ): """Check shape distance consistency with the final edge wraparound.""" theta = np.linspace(0, 2 * np.pi, 1000000) # Try a positive rotation. verts = rowan.rotate(rowan.from_axis_angle([0, 0, 1], 0.1), shape.vertices) shape = ConvexPolygon(verts) distance = shape.distance_to_surface(theta) assert_distance_to_surface_2d(shape, theta, distance) # Now try a negative rotation. verts = rowan.rotate(rowan.from_axis_angle([0, 0, 1], -0.2), shape.vertices) shape = ConvexPolygon(verts) distance = shape.distance_to_surface(theta) assert_distance_to_surface_2d(shape, theta, distance)
def convex_square(): return ConvexPolygon(get_square_points())
def check_rotation_invariance(quat): rotated_poly = ConvexPolygon(rowan.rotate(quat, poly.vertices)) assert sphere_isclose(poly.incircle, rotated_poly.incircle)