ddg.math.projective module
Utility functions for the projective module.
- ddg.math.projective.homogenize(vector)[source]
Homogenize a coordinate vector by inserting a 1.
- Parameters:
- vectorarray_like of shape (n,)
The vector to be homogenized.
- Returns:
- numpy.ndarray of shape (n+1,)
Examples
>>> from ddg.math.projective import homogenize >>> homogenize((3, 4, 5)) array([3, 4, 5, 1])
- ddg.math.projective.dehomogenize(vector, atol=None, rtol=None)[source]
Pick an affine representative for a homogeneous coordinate vector.
- Parameters:
- vectornumpy.ndarray of shape (n+1,)
The vector to be dehomogenized.
- atol, rtolfloat (default=None)
This function uses the global tolerance defaults if
atolorrtolare set to None. Seeddg.nonexactfor details.
- Returns:
- numpy.ndarray of shape (n,)
- Raises:
- ValueError
If last value of vector is 0.
Notes
This function uses the global tolerance defaults if
atolorrtolare set to None. See ddg.abc.NonExact for details.Examples
>>> import numpy as np >>> from ddg.math.projective import dehomogenize >>> dehomogenize(np.array((1, 0, 1))) array([1., 0.])
- ddg.math.projective.in_general_position(points, atol=None, rtol=None)[source]
Checks whether a list of k+1 points in n-dimensional projective are in general position.
- Parameters:
- pointsarray_like
Array_like of numpy.ndarray of shape (n+1,).
- Returns:
- bool
True if the points are in general position, False otherwise.
- Raises:
- ValueError
If no points are given.
Notes
If k <= n, we test whether their lifts in (n+1)-dimensional space are linearly independent. If k > n, we test whether any (n+1)-subset of them is contained in a hyperplane of n-dimensional projective space.
Examples
>>> import numpy as np >>> from ddg.math.projective import in_general_position >>> points_2d = [ ... np.array([1.0, 0.0, 1.0]), ... np.array([0.0, 1.0, 1.0]), ... np.array([1.0, 1.0, 1.0]), ... np.array([0.5, 0.5, 1.0]), ... ] >>> in_general_position(points_2d) False >>> points_3d = [ ... np.array([1.0, 0.0, 0.0, 1.0]), ... np.array([0.0, 1.0, 0.0, 1.0]), ... np.array([0.0, 0.0, 1.0, 1.0]), ... np.array([1.0, 1.0, 1.0, 1.0]), ... np.array([0.5, 0.5, 0.5, 1.0]), ... ] >>> in_general_position(points_3d) True
- ddg.math.projective.is_projective_frame(points)[source]
Checks whether a list of n+2 points in n-dimensional projective space form a projective frame.
- Parameters:
- pointsarray_like
Array_like of numpy.ndarray of shape (n+1,)
- Returns:
- bool
True if the points are a projective frame, False otherwise.
- Raises:
- ValueError
If no points are given.
Notes
A list of n+1 fundamental points and one unit point in projective space are called a projective frame if they are in general position.
Examples
>>> import numpy as np >>> from ddg.math.projective import is_projective_frame >>> points_2d = [ ... np.array([1.0, 0.0, 1.0]), ... np.array([0.0, 1.0, 1.0]), ... np.array([1.0, 1.0, 1.0]), ... np.array([0.5, 0.5, 1.0]), ... ] >>> is_projective_frame(points_2d) False >>> points_3d = [ ... np.array([1.0, 0.0, 0.0, 1.0]), ... np.array([0.0, 1.0, 0.0, 1.0]), ... np.array([0.0, 0.0, 1.0, 1.0]), ... np.array([1.0, 1.0, 1.0, 1.0]), ... np.array([0.5, 0.5, 0.5, 1.0]), ... ] >>> is_projective_frame(points_3d) True
- ddg.math.projective.point_of_intersection(planes, homogeneous_coords=True)[source]
Computes the point of intersection of given hyperplanes (in dual coordinates). If more hyperplanes are given than the dimension of the space, a least square solution is computed.
E.g. in RP^3 it computes the intersection of (at least) three given planes.
- Parameters:
- planesnumpy.ndarray of shape (n, k)
Amount of planes
nand dimension of each planek.- homogeneous: bool, (default=True)
Determines whether a
1.0will be added to the output vector.
- Returns:
- intersectionnumpy.ndarray of shape (k + 1,) or (k,)
Intersection of the given planes
Examples
>>> from ddg.math.projective import point_of_intersection >>> plane1 = np.array([1.0, 0.0, 0.0, -1.0]) >>> plane2 = np.array([0.0, 1.0, 0.0, -2.0]) >>> plane3 = np.array([0.0, 0.0, 1.0, -3.0]) >>> planes = np.array((plane1, plane2, plane3)) >>> point_of_intersection(planes) array([1., 2., 3., 1.])
- ddg.math.projective.affine_transformation(A, b)[source]
Assemble affine transformation.
Given a matrix
Aand a vectorb, assemble the projective transformationA | b F = --|--- 0 | 1It corresponds in affine coordinates to the affine transformation
x -> Ax + b.- Parameters:
- Anumpy.ndarray of shape (n, m)
- bnumpy.ndarray of shape (n,)
- Returns:
- Fnumpy.ndarray of shape (n+1, m+1)
Examples
>>> import numpy as np >>> from ddg.math.projective import affine_transformation >>> A = np.arange(9).reshape((3, 3)) >>> A array([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) >>> b = np.ones(3) * 15 >>> b array([15., 15., 15.]) >>> affine_transformation(A, b) array([[ 0., 1., 2., 15.], [ 3., 4., 5., 15.], [ 6., 7., 8., 15.], [ 0., 0., 0., 1.]])
- ddg.math.projective.decompose_affine_transformation(F, atol=None, rtol=None)[source]
Decompose affine transformation.
Given a projective transformation
A | b F = --|--- 0 | sdisassemble it into a matrix
A/sand a vectorb/s.- Parameters:
- Fnumpy.ndarray of shape (n+1, m+1)
- atol, rtolfloat (default=None)
This function uses the global tolerance defaults if
atolorrtolare set to None. Seeddg.nonexactfor details.
- Returns:
- Anumpy.ndarray of shape (n, m)
- bnumpy.ndarray of shape (n,)
Examples
>>> import numpy as np >>> from ddg.math.projective import decompose_affine_transformation >>> F = np.array([[0, 1, 2, 15], [3, 4, 5, 15], [6, 7, 8, 15], [0, 0, 0, 1]]) >>> F array([[ 0, 1, 2, 15], [ 3, 4, 5, 15], [ 6, 7, 8, 15], [ 0, 0, 0, 1]]) >>> A, b = decompose_affine_transformation(F) >>> A array([[0., 1., 2.], [3., 4., 5.], [6., 7., 8.]]) >>> b array([15., 15., 15.])
- ddg.math.projective.decompose_similarity(F, atol=None, rtol=None)[source]
Decompose a similarity transformation into scaling, orthogonal matrix and translation.
- Parameters:
- Fnumpy.ndarray of shape (n+1, m+1)
- atol, rtolfloat (default=None)
- Returns:
- sfloat
Scaling factor
- Onumpy.ndarray of shape (n, m)
Orthogonal matrix
- bnumpy.ndarray of shape (n,)
Translation vector
- atol, rtolfloat (default=None)
- Raises:
- ValueError
If
Fdoes not represent a similarity embedding.
Examples
>>> import numpy as np >>> from ddg.math.projective import decompose_similarity >>> F = np.array( ... [ ... [2.0, 0.0, 0.0, 0.0], ... [0.0, 2.0, 0.0, 0.0], ... [0.0, 0.0, 2.0, 0.0], ... [0.0, 0.0, 0.0, 1.0], ... ] ... ) >>> s, O, b = decompose_similarity(F) >>> s 2.0 >>> O array([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]]) >>> b array([0., 0., 0.])
- ddg.math.projective.affine_component_transformation(n, before, after=-1)[source]
Transformation transforming between affine pictures.
If an object dehomogenized wth affine component
beforeproduces a certain affine picture, the object transformed withFwill produce the same picture when dehomogenized with affine componentafter.- Parameters:
- nint
Size of returned matrix
- beforeint
- afterint (default=-1)
- Returns:
- Fnumpy.ndarray of shape (n, n)
Examples
>>> from ddg.math.projective import affine_component_transformation >>> affine_component_transformation(4, 2) array([[1., 0., 0., 0.], [0., 1., 0., 0.], [0., 0., 0., 1.], [0., 0., 1., 0.]]) >>> affine_component_transformation(5, 4, 2) array([[1., 0., 0., 0., 0.], [0., 1., 0., 0., 0.], [0., 0., 0., 0., 1.], [0., 0., 1., 0., 0.], [0., 0., 0., 1., 0.]])
- ddg.math.projective.translation(normal, direction, atol=None, rtol=None)[source]
Projective translation.
Returns the matrix
I + direction @ normal.T
This transformation fixes all vectors v in the hyperplane orthogonal to
normal. It can also be thought of as mappingv -> v + dot(normal, v) * direction
- Parameters:
- normal, directionnumpy.ndarray of shape (n,)
directionmust lie in the hyperplane orthogonal tonormal.- atol, rtolfloat (default=None)
This function uses the global tolerance defaults if
atolorrtolare set to None. Seeddg.nonexactfor details.
- Returns:
- numpy.ndarray of shape (n, n)
- Raises:
- ValueError
If the dimensions of
normalanddirectiondo not match.If
directionis not orthogonal tonormal.
Examples
>>> from ddg.math.projective import translation >>> translation(np.array((1, 0, 1)), np.array((-1, 0, 1))) array([[ 0., 0., -1.], [ 0., 1., 0.], [ 1., 0., 2.]]) >>> translation(np.array((1, 0, 1, 0)), np.array((-1, 0, 1, 0))) array([[ 0., 0., -1., 0.], [ 0., 1., 0., 0.], [ 1., 0., 2., 0.], [ 0., 0., 0., 1.]])
- ddg.math.projective.translations_from_quad_3d(x00, x10, x11, x01, atol=None, rtol=None)[source]
Translations that map along a quadrilateral in RP2.
Returns two projective translations
T1,T2of RP2 such thatT1 x01 ---> x11 ^ ^ T2 | | T2 | | x00 ---> x10 T1- Parameters:
- x00, x10, x11, x01numpy.ndarray of shape (3,)
- atol, rtolfloat (default=None)
This function uses the global tolerance defaults if
atolorrtolare set to None. Seeddg.nonexactfor details.
- Returns:
- T1, T2numpy.ndarray of shape (4, 4)
Examples
>>> import numpy as np >>> from ddg.math.projective import translations_from_quad_3d >>> x00 = np.array([0.0, 0.0, 1.0]) >>> x10 = np.array([1.0, 0.0, 1.0]) >>> x11 = np.array([1.0, 1.0, 1.0]) >>> x01 = np.array([0.0, 1.0, 1.0]) >>> T1, T2 = translations_from_quad_3d(x00, x10, x11, x01) >>> np.array(np.round(T1), dtype=int) array([[1, 0, 1], [0, 1, 0], [0, 0, 1]]) >>> np.array(np.round(T2), dtype=int) array([[1, 0, 0], [0, 1, 1], [0, 0, 1]])
- ddg.math.projective.translations_from_quad_4d(x00, x10, x11, x01, n, atol=None, rtol=None)[source]
Translations that map along a quadrilateral in a plane in RP3.
Returns two projective translations
T1,T2of RP3 such thatT1 x01 ---> x11 ^ ^ T2 | | T2 | | x00 ---> x10 T1- Parameters:
- x00, x10, x11, x01, nnumpy.ndarray of shape (4,)
The corners of the quadrilateral must lie in the plane orthogonal to n.
- atol, rtolfloat (default=None)
This function uses the global tolerance defaults if
atolorrtolare set to None. Seeddg.nonexactfor details.
- Returns:
- T1, T2numpy.ndarray of shape (4, 4)
Examples
>>> import numpy as np >>> from ddg.math.projective import translations_from_quad_4d >>> x00 = np.array([0.0, 0.0, 0.0, 1.0]) >>> x10 = np.array([1.0, 0.0, 0.0, 1.0]) >>> x11 = np.array([1.0, 1.0, 0.0, 1.0]) >>> x01 = np.array([0.0, 1.0, 0.0, 1.0]) >>> n = np.array([0.0, 0.0, 1.0, 0.0]) >>> T1, T2 = translations_from_quad_4d(x00, x10, x11, x01, n) >>> np.array(np.round(T1), dtype=int) array([[1, 0, 0, 1], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) >>> np.array(np.round(T2), dtype=int) array([[1, 0, 0, 0], [0, 1, 0, 1], [0, 0, 1, 0], [0, 0, 0, 1]])