예제 #1
0
def rotate2d(vec: Vector, ang: Angle):
    x = vec[0] * ang.cos() - vec[1] * ang.sin()
    y = vec[0] * ang.sin() + vec[1] * ang.cos()
    if vec.dimension == 3:
        return Vector([x, y, vec[3]])
    else:
        return Vector([x, y])
예제 #2
0
def test_side_vector(array_a, array_b, value_expected):

    if value_expected is None:
        with pytest.raises(ValueError):
            Vector(array_a).side_vector(array_b)

    else:
        assert Vector(array_a).side_vector(array_b) == value_expected
예제 #3
0
def test_angle_signed(array_u, array_v, angle_expected):

    if angle_expected is None:
        with pytest.raises(ValueError, match="The vectors must be 2D."):
            Vector(array_u).angle_signed(array_v)

    else:
        angle = Vector(array_u).angle_signed(array_v)
        assert math.isclose(angle, angle_expected)
예제 #4
0
def test_unit(array, array_unit_expected):

    if array_unit_expected is None:
        with pytest.raises(ValueError,
                           match="The magnitude must not be zero."):
            Vector(array).unit()

    else:
        assert Vector(array).unit().is_close(array_unit_expected)
예제 #5
0
def test_cosine_similarity(array_u, array_v, similarity_expected):

    if similarity_expected is None:
        with pytest.raises(ValueError,
                           match="The vectors must have non-zero magnitudes."):
            Vector(array_u).cosine_similarity(array_v)

    else:
        similarity = Vector(array_u).cosine_similarity(array_v)
        assert math.isclose(similarity, similarity_expected)
def compute_basis(points_stacked: xr.DataArray) -> Tuple[Basis, xr.DataArray]:
    """
    Return origin and basis vectors of new coordinate system found with RANSAC.

    Parameters
    ----------
    points_stacked : xarray.DataArray
        (N_frames, N_dims, N_layers) array of points.

    Returns
    -------
    basis : namedtuple
        Basis of new coordinate system (origin point and three unit vectors).
        Fields include 'origin', 'forward', 'up', 'perp'.
    points_grouped_inlier : xarray.DataArray
        (N_frames, N_dims) array.
        Grouped foot points that are marked inliers by RANSAC.

    """
    frames = points_stacked.coords['frames'].values

    points_head = points_stacked.sel(layers='points_head').values
    points_a = points_stacked.sel(layers='points_a').values
    points_b = points_stacked.sel(layers='points_b').values

    points_foot_mean = (points_a + points_b) / 2

    vectors_up = points_head - points_foot_mean
    vector_up = Vector(np.median(vectors_up, axis=0)).unit()

    frames_grouped = np.repeat(frames, 2)
    points_grouped = nf.interweave_rows(points_a, points_b)

    model_ransac, is_inlier = fit_ransac(points_grouped)
    point_origin, vector_forward = model_ransac.params

    vector_perp = Vector(vector_up).cross(vector_forward)

    frames_grouped_inlier = frames_grouped[is_inlier]
    points_grouped_inlier = points_grouped[is_inlier]

    points_grouped_inlier = xr.DataArray(
        points_grouped_inlier,
        coords={
            'frames': frames_grouped_inlier,
            'cols': range(3)
        },
        dims=('frames', 'cols'),
    )

    basis = Basis(point_origin, vector_forward, vector_up, vector_perp)

    return basis, points_grouped_inlier
예제 #7
0
def test_is_close(array):

    vector = Vector(array)
    point = Point(array)

    assert point.size == vector.size

    assert point.is_close(vector)
    assert vector.is_close(point)

    assert point.is_close(array)
    assert vector.is_close(array)
예제 #8
0
def test_add_subtract(arrays):

    array_point, array_vector = arrays

    point = Point(array_point)
    vector = Vector(array_vector)

    point_2 = point + array_vector
    assert math.isclose(point.distance_point(point_2), vector.norm())

    point_3 = point_2 - array_vector
    assert point.is_close(point_3)
예제 #9
0
def test_unit(array):

    vector = Vector(array)
    vector_unit = vector.unit()

    assert math.isclose(vector_unit.norm(), 1)
    assert (vector.norm() * vector_unit).is_close(array)

    assert vector_unit.is_parallel(vector)

    angle = vector.angle_between(vector_unit)
    assert math.isclose(angle, 0, abs_tol=ATOL)
예제 #10
0
def volume_tetrahedron(
    point_a: array_like,
    point_b: array_like,
    point_c: array_like,
    point_d: array_like,
) -> np.float64:
    """
    Return the volume of a tetrahedron defined by four points.

    The points are the vertices of the tetrahedron. They must be 3D or less.

    Parameters
    ----------
    point_a, point_b, point_c, point_d : array_like
        The four vertices of the tetrahedron.

    Returns
    -------
    np.float64
        The volume of the tetrahedron.

    References
    ----------
    http://mathworld.wolfram.com/Tetrahedron.html

    Examples
    --------
    >>> from skspatial.measurement import volume_tetrahedron

    >>> volume_tetrahedron([0, 0], [3, 2], [-3, 5], [1, 8])
    0.0

    >>> volume_tetrahedron([0, 0, 0], [2, 0, 0], [1, 1, 0], [0, 0, 1]).round(3)
    0.333

    >>> volume_tetrahedron([0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1]).round(3)
    0.167

    """
    vector_ab = Vector.from_points(point_a, point_b)
    vector_ac = Vector.from_points(point_a, point_c)
    vector_ad = Vector.from_points(point_a, point_d)

    vector_cross = vector_ac.cross(vector_ad)

    # Set the dimension to 3 so it matches the cross product.
    vector_ab = vector_ab.set_dimension(3)

    return 1 / 6 * abs(vector_ab.dot(vector_cross))
예제 #11
0
def test_project_point(lines_or_planes, data):
    """Test projecting a point onto a line or plane."""

    dim = data.draw(st.integers(min_value=DIM_MIN, max_value=DIM_MAX))

    array = data.draw(arrays_fixed(dim))
    line_or_plane = data.draw(lines_or_planes(dim))

    point_projected = line_or_plane.project_point(array)

    # The projected point should lie on the line/plane.
    assert line_or_plane.contains_point(point_projected, abs_tol=ATOL)

    # The vector from the point to its projection
    # should be perpendicular to the line/plane.
    vector_projection = Vector.from_points(array, point_projected)

    # The distance from the point to its projection
    # should equal the distance to the line/plane.
    distance_projection = vector_projection.norm()
    distance_to_object = abs(line_or_plane.distance_point(array))
    assert math.isclose(distance_to_object, distance_projection, rel_tol=1e-6)

    # The distance of the projection should be the
    # shortest distance from the point to the object.
    distance_points = line_or_plane.point.distance_point(array)
    assert distance_projection < distance_points or math.isclose(
        distance_projection, distance_points)
예제 #12
0
def test_from_points(arrays):

    array_a, array_b = arrays

    point_a = Point(array_a)
    vector_ab = Vector.from_points(array_a, array_b)

    assert (point_a + vector_ab).is_close(array_b)
예제 #13
0
def area_triangle(point_a: array_like, point_b: array_like,
                  point_c: array_like) -> np.float64:
    """
    Return the area of a triangle defined by three points.

    The points are the vertices of the triangle. They must be 3D or less.

    Parameters
    ----------
    point_a, point_b, point_c : array_like
        The three vertices of the triangle.

    Returns
    -------
    np.float64
        The area of the triangle.

    References
    ----------
    http://mathworld.wolfram.com/TriangleArea.html

    Examples
    --------
    >>> from skspatial.measurement import area_triangle

    >>> area_triangle([0, 0], [0, 1], [1, 0])
    0.5

    >>> area_triangle([0, 0], [0, 2], [1, 1])
    1.0

    >>> area_triangle([3, -5, 1], [5, 2, 1], [9, 4, 2]).round(2)
    12.54

    """
    vector_ab = Vector.from_points(point_a, point_b)
    vector_ac = Vector.from_points(point_a, point_c)

    # Normal vector of plane defined by the three points.
    vector_normal = vector_ab.cross(vector_ac)

    return 0.5 * vector_normal.norm()
예제 #14
0
def test_scale(array, scalar):

    assume(abs(scalar) > ATOL)

    vector = Vector(array)
    vector_scaled = scalar * vector

    assert vector_scaled.is_parallel(array)

    angle = vector_scaled.angle_between(array)

    if scalar > 0:
        assert math.isclose(angle, 0, abs_tol=ATOL)
    else:
        assert math.isclose(angle, np.pi, rel_tol=1e-6)
예제 #15
0
def vectors_nonzero(draw, dim):
    """
    Return a strategy which generates nonzero Vector objects.

    Parameters
    ----------
    dim : int
        Dimension of the object.

    Returns
    -------
    LazyStrategy
        Hypothesis strategy.

    """
    return Vector(draw(arrays_fixed_nonzero(dim)))
예제 #16
0
def vectors(draw, dim):
    """
    Return a strategy which generates Vector objects.

    Parameters
    ----------
    dim : int
        Dimension of the object.

    Returns
    -------
    LazyStrategy
        Hypothesis strategy.

    Examples
    --------
    >>> from hypothesis import find
    >>> from tests.property.strategies import vectors

    >>> find(vectors(2), lambda x: True)
    Vector([0., 0.])

    """
    return Vector(draw(arrays_fixed(dim)))
예제 #17
0
def test_from_points(array_a, array_b, vector_expected):

    assert_array_equal(Vector.from_points(array_a, array_b), vector_expected)
예제 #18
0
"""
Vector-Plane Projection
=======================

Project a vector onto a plane.

"""
from skspatial.objects import Plane
from skspatial.objects import Vector
from skspatial.plotting import plot_3d

plane = Plane([0, 0, 0], [0, 0, 1])
vector = Vector([1, 1, 1])

vector_projected = plane.project_vector(vector)

_, ax = plot_3d(
    plane.plotter(lims_x=(-5, 5), lims_y=(-5, 5), alpha=0.3),
    vector.plotter(point=plane.point, color='k'),
    vector_projected.plotter(point=plane.point,
                             color='r',
                             linewidth=2,
                             zorder=3),
)

ax.set_zlim([-1, 1])
예제 #19
0
def test_equality(array):

    assert_array_equal(array, Point(array))
    assert_array_equal(array, Vector(array))
    assert_array_equal(array, np.array(array))
예제 #20
0
"""
3D Vector-Line Projection
=========================

Project a vector onto a line.

"""
from skspatial.objects import Vector, Line
from skspatial.plotting import plot_3d

line = Line([0, 0, 0], [1, 1, 2])
vector = Vector([1, 1, 0.1])

vector_projected = line.project_vector(vector)

plot_3d(
    line.plotter(t_1=-1, c='k', linestyle='--'),
    vector.plotter(point=line.point, color='k'),
    vector_projected.plotter(point=line.point,
                             color='r',
                             linewidth=2,
                             zorder=3),
)
예제 #21
0
def test_is_perpendicular(array_u, array_v, bool_expected):
    """Test checking if vector u is perpendicular to vector v."""
    vector_u = Vector(array_u)

    assert vector_u.is_perpendicular(array_v) == bool_expected
예제 #22
0
def test_two_vectors(arrays):

    array_a, array_b = arrays
    vector_a = Vector(array_a)

    is_perpendicular = vector_a.is_perpendicular(array_b)
    is_parallel = vector_a.is_parallel(array_b)

    # Two non-zero vectors cannot be both perpendicular and parallel.
    assert not (is_perpendicular and is_parallel)

    angle = vector_a.angle_between(array_b)

    if is_perpendicular:
        assert math.isclose(angle, np.pi / 2)

    if is_parallel:
        assert math.isclose(angle, 0, abs_tol=ATOL) or math.isclose(
            angle, np.pi, rel_tol=1e-6)

    # The zero vector is perpendicular and parallel to any other vector.
    vector_zero = np.zeros(vector_a.size)
    assert vector_a.is_perpendicular(vector_zero)
    assert vector_a.is_parallel(vector_zero)

    # The angle with the zero vector is undefined.
    with pytest.raises(Exception):
        vector_a.angle_between(vector_zero)

    # The projection of vector B onto A is parallel to A.
    vector_b_projected = vector_a.project_vector(array_b)
    assert vector_a.is_parallel(vector_b_projected)

    # The projection is zero if vectors A and B are perpendicular.
    if is_perpendicular:
        assert vector_b_projected.is_zero(abs_tol=ATOL)
예제 #23
0
from skspatial.objects import Plane
from skspatial.objects import Point
from skspatial.objects import Points
from skspatial.objects import Sphere
from skspatial.objects import Triangle
from skspatial.objects import Vector


@pytest.mark.parametrize(
    ("obj_spatial", "repr_expected"),
    [
        (Point([0]), "Point([0])"),
        (Point([0, 0]), "Point([0, 0])"),
        (Point([0.5, 0]), "Point([0.5, 0. ])"),
        (Point([-11, 0]), "Point([-11,   0])"),
        (Vector([-11, 0]), "Vector([-11,   0])"),
        (Vector([-11.0, 0.0]), "Vector([-11.,   0.])"),
        (Vector([0, 0]), "Vector([0, 0])"),
        (Vector([0.5, 0]), "Vector([0.5, 0. ])"),
        (Points([[1.5, 2], [5, 3]]), "Points([[1.5, 2. ],\n        [5. , 3. ]])"),
        (Line([0, 0], [1, 0]), "Line(point=Point([0, 0]), direction=Vector([1, 0]))"),
        (Line([-1, 2, 3], [5, 4, 2]), "Line(point=Point([-1,  2,  3]), direction=Vector([5, 4, 2]))"),
        (Line(np.zeros(2), [1, 0]), "Line(point=Point([0., 0.]), direction=Vector([1, 0]))"),
        (Plane([0, 0], [1, 0]), "Plane(point=Point([0, 0]), normal=Vector([1, 0]))"),
        (Plane([-1, 2, 3], [5, 4, 2]), "Plane(point=Point([-1,  2,  3]), normal=Vector([5, 4, 2]))"),
        (Circle([0, 0], 1), "Circle(point=Point([0, 0]), radius=1)"),
        (Circle([0, 0], 2.5), "Circle(point=Point([0, 0]), radius=2.5)"),
        (Sphere([0, 0, 0], 1), "Sphere(point=Point([0, 0, 0]), radius=1)"),
        (
            Triangle([0, 0], [0, 1], [1, 0]),
            "Triangle(point_a=Point([0, 0]), point_b=Point([0, 1]), point_c=Point([1, 0]))",
예제 #24
0
def test_is_parallel(array_u, array_v, bool_expected):
    """Test checking if vector u is parallel to vector v."""
    vector_u = Vector(array_u)

    assert vector_u.is_parallel(array_v) == bool_expected
예제 #25
0
def test_add_subtract(array):
    vector = Vector(array)
    assert (vector + array - array).is_close(array)
예제 #26
0
def test_is_zero(array, kwargs, bool_expected):

    assert Vector(array).is_zero(**kwargs) == bool_expected
예제 #27
0
import math

import pytest
from numpy.testing import assert_array_equal

from skspatial.objects import Vector


@pytest.mark.parametrize(
    "array_a, array_b, vector_expected",
    [
        ([0, 0], [1, 0], Vector([1, 0])),
        ([1, 0], [1, 0], Vector([0, 0])),
        ([1, 0], [2, 0], Vector([1, 0])),
        ([8, 3, -5], [3, 7, 1], Vector([-5, 4, 6])),
        ([5, 7, 8, 9], [2, 5, 3, -4], Vector([-3, -2, -5, -13])),
    ],
)
def test_from_points(array_a, array_b, vector_expected):

    assert_array_equal(Vector.from_points(array_a, array_b), vector_expected)


@pytest.mark.parametrize(
    "array, array_unit_expected",
    [
        ([1, 0], [1, 0]),
        ([2, 0], [1, 0]),
        ([-1, 0], [-1, 0]),
        ([0, 0, 5], [0, 0, 1]),
        ([1, 1], [math.sqrt(2) / 2, math.sqrt(2) / 2]),
예제 #28
0
def test_different_direction_failure(array):

    message_expected = "The vector must not be the zero vector."

    with pytest.raises(ValueError, match=message_expected):
        Vector(array).different_direction()
예제 #29
0
def test_project_vector(vector_u, vector_v, vector_expected):
    """Test projecting vector u onto vector v."""

    vector_u_projected = Vector(vector_v).project_vector(vector_u)

    assert vector_u_projected.is_close(vector_expected)
예제 #30
0
"""
Point-Plane Projection
======================

Project a point onto a plane.

"""
from skspatial.objects import Plane
from skspatial.objects import Point
from skspatial.objects import Vector
from skspatial.plotting import plot_3d


plane = Plane(point=[0, 0, 2], normal=[1, 0, 2])
point = Point([5, 9, 3])

point_projected = plane.project_point(point)
vector_projection = Vector.from_points(point, point_projected)


plot_3d(
    plane.plotter(lims_x=(0, 10), lims_y=(0, 15), alpha=0.3),
    point.plotter(s=75, c='k'),
    point_projected.plotter(c='r', s=75, zorder=3),
    vector_projection.plotter(point=point, c='k', linestyle='--'),
)