Example #1
0
def test_perpendicular():
    v1 = np.array([1.0, 2.0, 3.0])
    v2 = np.array([4.0, 5.0, 6.0])

    expected = np.array([-3.0, 6.0, -3.0])
    expected_magnitude = math.sqrt(9.0 + 36.0 + 9.0)

    np.testing.assert_array_almost_equal(
        vg.perpendicular(v1, v2, normalized=False), expected)

    np.testing.assert_array_almost_equal(
        vg.perpendicular(v1, v2, normalized=True),
        expected / expected_magnitude)
Example #2
0
def test_perpendicular_mixed():
    v1 = np.array([[1.0, 0.0, -1.0], [1.0, 2.0, 3.0]])
    v2 = np.array([4.0, 5.0, 6.0])

    expected = np.array([[5.0, -10.0, 5.0], [-3.0, 6.0, -3.0]])
    expected_magnitude = np.array(
        [math.sqrt(25.0 + 100.0 + 25.0),
         math.sqrt(9.0 + 36.0 + 9.0)])
    np.testing.assert_array_almost_equal(
        vg.perpendicular(v1, v2, normalized=False), expected)
    np.testing.assert_array_almost_equal(
        vg.perpendicular(v1, v2, normalized=True),
        expected / expected_magnitude.reshape(-1, 1),
    )
Example #3
0
    def normal(self, other: "Vector") -> "Vector":
        """Compute the vector normal to this vector & another vector

        Note:
            This is equivalent to computing the normalized cross product
            between this vector & the other vector, and so is anticommutative.

        Args:
            other: The vector with respect to which to compute the normal

        Raises:
            NoNormalForParallels: If the input vectors are parallel
            NoNormalForAntiparallels: If the input vectors are antiparallel
            NoNormalForNulls: If one of the vectors has 0 magnitude
        """
        try:
            return self.from_components(
                vg.perpendicular(self.array, other.array))
        except NaNVector:
            if self.magnitude and other.magnitude:
                if self.normalized == other.normalized:
                    raise NoNormalForParallels(self, other)
                else:
                    raise NoNormalForAntiparallels(self, other)
            else:
                raise NoNormalForNulls(min(self, other), max(self, other))
Example #4
0
def test_project_to_line_stacked_both():
    p1 = np.array([5.0, 5.0, 4.0])
    p2 = np.array([10.0, 10.0, 6.0])
    along_line = p2 - p1

    common_kwargs = dict(
        reference_points_of_lines=np.array([p1, p1, p1]),
        vectors_along_lines=np.array([along_line, along_line, along_line]),
    )

    other_point_on_line = np.array([0.0, 0.0, 2.0])

    example_perpendicular_displacement = [
        k * vg.perpendicular(vg.normalize(along_line), vg.basis.x)
        for k in [0.1, 0.5, -2.0]
    ]

    example_points = np.vstack([p1, p2, other_point_on_line])
    expected_projected_points = np.vstack([p1, p2, other_point_on_line])

    np.testing.assert_array_almost_equal(
        project_to_line(points=example_points, **common_kwargs),
        expected_projected_points,
    )
    np.testing.assert_array_almost_equal(
        project_to_line(points=example_points +
                        example_perpendicular_displacement,
                        **common_kwargs),
        expected_projected_points,
    )
Example #5
0
def test_project_to_line():
    p1 = np.array([5.0, 5.0, 4.0])
    p2 = np.array([10.0, 10.0, 6.0])
    along_line = p2 - p1

    common_kwargs = dict(reference_points_of_lines=p1,
                         vectors_along_lines=along_line)

    np.testing.assert_array_almost_equal(
        project_to_line(points=p1, **common_kwargs), p1)
    np.testing.assert_array_almost_equal(
        project_to_line(points=p2, **common_kwargs), p2)

    other_point_on_line = np.array([0.0, 0.0, 2.0])
    np.testing.assert_array_almost_equal(
        project_to_line(points=other_point_on_line, **common_kwargs),
        other_point_on_line,
    )

    example_perpendicular_displacement = [
        k * vg.perpendicular(vg.normalize(along_line), vg.basis.x)
        for k in [0.1, 0.5, -2.0]
    ]
    for point_on_line in [p1, p2, other_point_on_line]:
        for displacement in example_perpendicular_displacement:
            np.testing.assert_array_almost_equal(
                project_to_line(points=point_on_line + displacement,
                                **common_kwargs),
                point_on_line,
            )
Example #6
0
def test_perpendicular_error():
    v1 = np.array([[1.0, 0.0, -1.0], [1.0, 2.0, 3.0]])
    v2 = np.array([[4.0, 5.0, 6.0]])

    with pytest.raises(
            ValueError,
            match="v2 must be an array with shape \\(2, 3\\); got \\(1, 3\\)"):
        vg.perpendicular(v1, v2, normalized=False)

    v1 = np.array([[1.0, 0.0, -1.0], [1.0, 2.0, 3.0]])
    v2 = np.array([[[4.0, 5.0, 6.0]]])

    with pytest.raises(
            ValueError,
            match="Not sure what to do with 2 dimensions and 3 dimensions"):
        vg.perpendicular(v1, v2, normalized=False)
Example #7
0
def test_perpendicular_stacked():
    v1 = np.array([[1.0, 0.0, -1.0], [1.0, 2.0, 3.0]])
    v2 = np.array([[2.0, 2.0, 2.0], [4.0, 5.0, 6.0]])

    expected = np.array([[2.0, -4.0, 2.0], [-3.0, 6.0, -3.0]])
    expected_magnitude = np.array(
        [math.sqrt(4.0 + 16.0 + 4.0),
         math.sqrt(9.0 + 36.0 + 9.0)])

    np.testing.assert_array_almost_equal(
        vg.perpendicular(v1, v2, normalized=False), expected)

    np.testing.assert_array_almost_equal(
        vg.perpendicular(v1, v2, normalized=True),
        expected / expected_magnitude[:, np.newaxis],
    )
Example #8
0
    def tilted(self, new_point, coplanar_point):
        """
        Create a new plane, tilted so it passes through `new_point`. Also
        specify a `coplanar_point` which the old and new planes should have
        in common.

        Args:
            new_point (np.arraylike): A point on the desired plane, with shape
                `(3,)`.
            coplanar_point (np.arraylike): The `(3,)` point which the old and
                new planes have in common.

        Returns:
            Plane: The adjusted plane.
        """
        vg.shape.check(locals(), "new_point", (3, ))
        vg.shape.check(locals(), "coplanar_point", (3, ))

        vector_along_old_plane = self.project_point(new_point) - coplanar_point
        vector_along_new_plane = new_point - coplanar_point
        axis_of_rotation = vg.perpendicular(vector_along_old_plane,
                                            self.normal)
        angle_between_vectors = vg.signed_angle(
            vector_along_old_plane,
            vector_along_new_plane,
            look=axis_of_rotation,
            units="rad",
        )
        new_normal = vg.rotate(
            self.normal,
            around_axis=axis_of_rotation,
            angle=angle_between_vectors,
            units="rad",
        )
        return Plane(point_on_plane=coplanar_point, unit_normal=new_normal)
Example #9
0
    def _rotmat(self, vector, points):
        """
        Rotates a 3xn array of 3D coordinates from the +z normal to an
        arbitrary new normal vector.
        """

        vector = vg.normalize(vector)
        axis = vg.perpendicular(vg.basis.z, vector)
        angle = vg.angle(vg.basis.z, vector, units='rad')

        a = np.hstack((axis, (angle, )))
        R = matrix_from_axis_angle(a)

        r = Rot.from_matrix(R)
        rotmat = r.apply(points)

        return rotmat
Example #10
0
def test_project():
    p1 = np.array([5.0, 5.0, 4.0])
    p2 = np.array([10.0, 10.0, 6.0])
    line = Line.from_points(p1, p2)

    np.testing.assert_array_almost_equal(line.project(p1), p1)
    np.testing.assert_array_almost_equal(line.project(p2), p2)

    other_point_on_line = np.array([0.0, 0.0, 2.0])
    np.testing.assert_array_almost_equal(line.project(other_point_on_line),
                                         other_point_on_line)

    example_perpendicular_displacement = [
        k * vg.perpendicular(line.along, vg.basis.x) for k in [0.1, 0.5, -2.0]
    ]
    for p in [p1, p2, other_point_on_line]:
        for displacement in example_perpendicular_displacement:
            np.testing.assert_array_almost_equal(
                line.project(p + displacement), p)
Example #11
0
def test_project_stacked():
    p1 = np.array([5.0, 5.0, 4.0])
    p2 = np.array([10.0, 10.0, 6.0])
    line = Line.from_points(p1, p2)

    other_point_on_line = np.array([0.0, 0.0, 2.0])

    example_perpendicular_displacement = [
        k * vg.perpendicular(line.along, vg.basis.x) for k in [0.1, 0.5, -2.0]
    ]

    example_points = np.vstack([p1, p2, other_point_on_line])
    expected_projected_points = np.vstack([p1, p2, other_point_on_line])

    np.testing.assert_array_almost_equal(line.project(example_points),
                                         expected_projected_points)
    np.testing.assert_array_almost_equal(
        line.project(example_points + example_perpendicular_displacement),
        expected_projected_points,
    )