Ejemplo n.º 1
0
def coplanar_points_are_on_same_side_of_line(a, b, p1, p2, atol=1e-8):
    """
    Using "same-side technique" from http://blackpawn.com/texts/pointinpoly/default.html
    """
    along_line = b - a
    return vg.dot(vg.cross(along_line, p1 - a), vg.cross(along_line,
                                                         p2 - a)) >= -atol
Ejemplo n.º 2
0
def test_cross_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]])
    np.testing.assert_array_almost_equal(vg.cross(v1, v2), expected)
    np.testing.assert_array_almost_equal(vg.cross(v2, v1), -expected)
Ejemplo n.º 3
0
def test_cross_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.cross(v1, v2)

    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.cross(v1, v2)
Ejemplo n.º 4
0
def coplanar_points_are_on_same_side_of_line(a, b, p1, p2):
    """
    Test if the given points are on the same side of the given line.

    Args:
        a (np.arraylike): The first 3D point of interest.
        b (np.arraylike): The second 3D point of interest.
        p1 (np.arraylike): A first point which lies on the line of interest.
        p2 (np.arraylike): A second point which lies on the line of interest.

    Returns:
        bool: `True` when `a` and `b` are on the same side of the line defined
        by `p1` and `p2`.
    """
    check_shape_any(a, (3,), (-1, 3), name="a")
    vg.shape.check(locals(), "b", a.shape)
    vg.shape.check(locals(), "p1", a.shape)
    vg.shape.check(locals(), "p2", a.shape)

    # Uses "same-side technique" from http://blackpawn.com/texts/pointinpoly/default.html
    along_line = b - a
    return vg.dot(vg.cross(along_line, p1 - a), vg.cross(along_line, p2 - a)) >= 0
Ejemplo n.º 5
0
def world_to_view(position, target, up=vg.basis.y, inverse=False):
    """
    Create a transform matrix which sends world-space coordinates to
    view-space coordinates.

    Args:
        position (np.ndarray): The camera's position in world coordinates.
        target (np.ndarray): The camera's target in world coordinates.
            `target - position` is the "look at" vector.
        up (np.ndarray): The approximate up direction, in world coordinates.
        inverse (bool): When `True`, return the inverse transform instead.

    Returns:
        np.ndarray: The `4x4` transformation matrix, which can be used with
        `polliwog.transform.apply_transform()`.

    See also:
        https://cseweb.ucsd.edu/classes/wi18/cse167-a/lec4.pdf
        http://www.songho.ca/opengl/gl_camera.html
    """
    vg.shape.check(locals(), "position", (3, ))
    vg.shape.check(locals(), "target", (3, ))

    look = vg.normalize(target - position)
    left = vg.normalize(vg.cross(look, up))
    recomputed_up = vg.cross(left, look)

    rotation = transform_matrix_for_rotation(
        np.array([left, recomputed_up, look]))
    if inverse:
        inverse_rotation = rotation.T
        inverse_translation = transform_matrix_for_translation(position)
        return compose_transforms(inverse_rotation, inverse_translation)
    else:
        translation = transform_matrix_for_translation(-position)
        return compose_transforms(translation, rotation)
Ejemplo n.º 6
0
def plane_normal_from_points(points):
    """
    Given a set of three points, compute the normal of the plane which
    passes through them. Also works on stacked inputs (i.e. many sets
    of three points).
    """
    points, _, transform_result = columnize(points, (-1, 3, 3), name="points")

    p1s = points[:, 0]
    p2s = points[:, 1]
    p3s = points[:, 2]
    v1s = p2s - p1s
    v2s = p3s - p1s
    unit_normals = vg.normalize(vg.cross(v1s, v2s))

    return transform_result(unit_normals)
Ejemplo n.º 7
0
def surface_normals(points, normalize=True):
    """
    Compute the surface normal of a triangle. The direction of the normal
    follows conventional counter-clockwise winding and the right-hand
    rule.

    Also works on stacked inputs (i.e. many sets of three points).
    """
    points, _, transform_result = columnize(points, (-1, 3, 3), name="points")

    p1s = points[:, 0]
    p2s = points[:, 1]
    p3s = points[:, 2]
    v1s = p2s - p1s
    v2s = p3s - p1s
    normals = vg.cross(v1s, v2s)

    if normalize:
        normals = vg.normalize(normals)

    return transform_result(normals)