File: test_align.py

package info (click to toggle)
trimesh 4.5.1-3
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 33,416 kB
  • sloc: python: 35,596; makefile: 96; javascript: 85; sh: 38
file content (106 lines) | stat: -rw-r--r-- 3,749 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
try:
    from . import generic as g
except BaseException:
    import generic as g

tol_norm = 1e-10


class AlignTests(g.unittest.TestCase):
    def test_align(self):
        """
        Test aligning two 3D vectors
        """

        # function we're testing
        align = g.trimesh.geometry.align_vectors
        is_rigid = g.trimesh.transformations.is_rigid

        # start with some edge cases and make sure the transform works
        target = g.np.array([0, 0, -1], dtype=g.np.float64)
        vectors = g.np.vstack(
            (
                g.trimesh.unitize(g.random((1000, 3)) - 0.5),
                g.random((1000, 3)) - 0.5,
                [-target, target],
                g.trimesh.util.generate_basis(target),
                [
                    [7.12106798e-07, -7.43194705e-08, 1.00000000e00],
                    [0, 0, -1],
                    [1e-4, 1e-4, -1],
                ],
            )
        )

        # collect errors
        norms = []
        unitized = g.trimesh.unitize(vectors)
        for unit_dest, dest in zip(unitized[-10:], vectors[-10:]):
            for unit, vector in zip(unitized, vectors):
                T, _a = align(vector, dest, return_angle=True)
                assert is_rigid(T)
                assert g.np.isclose(g.np.linalg.det(T), 1.0)
                # rotate vector with transform
                check = g.np.dot(T[:3, :3], unit)
                # compare to target vector
                norm = g.np.linalg.norm(check - unit_dest)
                norms.append(norm)
                assert norm < tol_norm

        norms = g.np.array(norms)
        # these vectors should be perpendicular and zero
        angles = [
            align(i, target, return_angle=True)[1]
            for i in g.trimesh.util.generate_basis(target)
        ]
        assert g.np.allclose(angles, [g.np.pi / 2, g.np.pi / 2, 0.0])

    def test_range(self):
        # function we're testing
        align = g.trimesh.geometry.align_vectors
        is_rigid = g.trimesh.transformations.is_rigid

        # generate angles from 0 to 180 degrees
        angles = g.np.linspace(0.0, g.np.pi / 1e7, 10000)
        # generate on- plane vectors
        vectors = g.np.column_stack(
            (g.np.cos(angles), g.np.sin(angles), g.np.zeros(len(angles)))
        )

        # rotate them arbitrarily off the plane just for funsies
        vectors = g.trimesh.transform_points(vectors, g.transforms[20])

        for angle, vector in zip(angles, vectors):
            g.trimesh.util.generate_basis(vector)
            # check alignment to first vector
            # which was created with zero angle
            T, a = align(vector, vectors[0], return_angle=True)
            assert is_rigid(T)
            # check to make sure returned angle corresponds with truth

            assert g.np.isclose(a, angle, atol=1e-6)

            # check to make sure returned transform is correct
            check = g.np.dot(T[:3, :3], vector)
            norm = g.np.linalg.norm(check - vectors[0])

            assert norm < tol_norm

    def test_rigid(self):
        # check issues with near-reversed vectors not returning rigid
        align = g.trimesh.geometry.align_vectors
        T = align([0, 0, -1], [-1e-17, 1e-17, 1])
        assert g.np.isclose(g.np.linalg.det(T), 1.0)

        T = align([0, 0, -1], [-1e-4, 1e-4, 1])
        assert g.np.isclose(g.np.linalg.det(T), 1.0)

        vector_1 = g.np.array([7.12106798e-07, -7.43194705e-08, 1.00000000e00])
        vector_2 = g.np.array([0, 0, -1])
        T, _angle = align(vector_1, vector_2, return_angle=True)
        assert g.np.isclose(g.np.linalg.det(T), 1.0)


if __name__ == "__main__":
    g.trimesh.util.attach_to_log()
    g.unittest.main()