Пример #1
0
def test_translate_inertia(translation):
    shape = PlatonicFamily.get_shape("Cube")
    # Choose a volume > 1 to test the volume scaling, but don't choose one
    # that's too large because the uncentered polyhedral calculation has
    # massive error without fixing that.
    shape.volume = 2
    shape.center = (0, 0, 0)

    translated_shape = ConvexPolyhedron(shape.vertices + translation)

    translated_inertia = translate_inertia_tensor(translation,
                                                  shape.inertia_tensor,
                                                  shape.volume)
    mc_tensor = compute_inertia_mc(translated_shape.vertices, 1e4)

    assert np.allclose(
        translated_inertia,
        translated_shape._compute_inertia_tensor(False),
        atol=2e-1,
        rtol=2e-1,
    )
    assert np.allclose(mc_tensor,
                       translated_shape._compute_inertia_tensor(False),
                       atol=2e-1,
                       rtol=2e-1)

    assert np.allclose(mc_tensor, translated_inertia, atol=1e-2, rtol=1e-2)
    assert np.allclose(mc_tensor,
                       translated_shape.inertia_tensor,
                       atol=1e-2,
                       rtol=1e-2)
Пример #2
0
def test_rotate_inertia(points):
    # Use the input as noise rather than the base points to avoid precision and
    # degenerate cases provided by hypothesis.
    tet = PlatonicFamily.get_shape("Tetrahedron")
    vertices = tet.vertices + points

    rotation = rowan.random.rand()
    shape = ConvexPolyhedron(vertices)
    rotated_shape = ConvexPolyhedron(rowan.rotate(rotation, vertices))

    mat = rowan.to_matrix(rotation)
    rotated_inertia = rotate_order2_tensor(mat, shape.inertia_tensor)

    assert np.allclose(rotated_inertia, rotated_shape.inertia_tensor)
Пример #3
0
def test_curvature():
    """Regression test against values computed with older method."""
    # The shapes in the PlatonicFamily are normalized to unit volume.
    known_shapes = {
        "Cube": 0.75,
        "Dodecahedron": 0.6703242780091758,
        "Icosahedron": 0.6715997848012972,
        "Octahedron": 0.75518565565632,
        "Tetrahedron": 0.9303430847680867,
    }

    for name, curvature in known_shapes.items():
        poly = PlatonicFamily.get_shape(name)
        if name == "Dodecahedron":
            poly.merge_faces(rtol=1)
        assert np.isclose(poly.mean_curvature, curvature)
Пример #4
0
def test_dihedrals():
    known_shapes = {
        "Tetrahedron": np.arccos(1 / 3),
        "Cube": np.pi / 2,
        "Octahedron": np.pi - np.arccos(1 / 3),
        "Dodecahedron": np.pi - np.arctan(2),
        "Icosahedron": np.pi - np.arccos(np.sqrt(5) / 3),
    }
    for name, dihedral in known_shapes.items():
        poly = PlatonicFamily.get_shape(name)
        # The dodecahedron needs a more expansive merge to get all the
        # faces joined.
        if name == "Dodecahedron":
            poly.merge_faces(rtol=1)
        for i in range(poly.num_faces):
            for j in poly.neighbors[i]:
                assert np.isclose(poly.get_dihedral(i, j), dihedral)
Пример #5
0
def test_rotate_inertia(tetrahedron):
    # Use the input as noise rather than the base points to avoid precision and
    # degenerate cases provided by hypothesis.
    tet = PlatonicFamily.get_shape("Tetrahedron")

    @given(
        arrays(np.float64, (4, 3),
               elements=floats(-10, 10, width=64),
               unique=True),
        Random3DRotationStrategy,
    )
    def testfun(points, rotation):
        vertices = tet.vertices + points
        shape = ConvexPolyhedron(vertices)
        rotated_shape = ConvexPolyhedron(rowan.rotate(rotation, vertices))

        mat = rowan.to_matrix(rotation)
        rotated_inertia = rotate_order2_tensor(mat, shape.inertia_tensor)

        assert np.allclose(rotated_inertia, rotated_shape.inertia_tensor)

    testfun()
Пример #6
0
def platonic_solids():
    for shape_name in PlatonicFamily.data:
        yield PlatonicFamily.get_shape(shape_name)
Пример #7
0
def tetrahedron():
    tet = PlatonicFamily.get_shape("Tetrahedron")
    tet.volume = 1
    return tet
Пример #8
0
def platonic_solids():
    """Generate platonic solids."""
    for shape_name in PlatonicFamily.data:
        yield PlatonicFamily.get_shape(shape_name)
Пример #9
0
        c1.center, c2.center, *args, **kwargs)


def platonic_solids():
    """Generate platonic solids."""
    for shape_name in PlatonicFamily.data:
        yield PlatonicFamily.get_shape(shape_name)


# A convenient mark decorator that also includes names for the polyhedra.
# Assumes that the argument name is "poly".
_platonic_shape_names = PlatonicFamily.data.keys()
named_platonic_mark = pytest.mark.parametrize(
    argnames="poly",
    argvalues=[
        PlatonicFamily.get_shape(name) for name in _platonic_shape_names
    ],
    ids=_platonic_shape_names,
)


def regular_polygons(n=10):
    """Generate regular polygons."""
    for i in range(3, n + 1):
        yield RegularNGonFamily.get_shape(i)


def _test_get_set_minimal_bounding_sphere_radius(shape, centered=False):
    """Test getting and setting the minimal bounding circle radius.

    This function will work for any shape in two or three dimensions based on