ddg.geometry.quadrics module
Projective quadric module.
Contains classes for quadrics and pencils of quadrics and utility functions.
- class ddg.geometry.quadrics.Quadric(matrix, subspace=None, atol=None, rtol=None)[source]
Bases:
Embeddable,LinearTransformableQuadric in real projective space.
Let
qbe a quadratic form on R^(n+1). The quadric corresponding toqis the set{ [x] in RP^n : q(x) = 0 }.- Parameters:
- matrixnp.ndarray of shape (n, n)
Symmetric matrix representing the quadratic form in homogeneous coordinates.
The matrix is interpreted as the Gram matrix with respect to the given basis of
subspace.Non-float dtypes will be converted to float.
- subspaceddg.Subspace or iterable of numpy.ndarray (default=None)
Subspace containing the quadric. Can be given as a list of homogeneous coordinate vectors.
If None is given, uses whole space with standard basis.
- atol, rtolfloat (default=None)
Tolerances that will be used internally by the class. If these are set to None, the global defaults will be used.
- Raises:
- ValueError
If
matrixis not symmetricIf the dimension of the subspace does not match the shape of
matrix.
Notes
This class supports the following operators:
==, meaning equality of the quadratic forms.<=, meaning that one quadratic form is a restriction of the other.in, meaning set membership.
- Attributes:
- matrixnumpy.ndarray of shape (n, n)
- subspaceSubspace
- ambient_dimension
dimensionThe (real) dimension of the quadric.
dimension_complexComplex dimension of the quadric.
rankRank of self.matrix.
corankCorank of self.matrix.
is_degenerateWhether the quadric is degenerate.
singular_subspaceSingular subspace.
non_degenerate_subspaceNon-degenerate subspace.
- atol, rtol
- property ambient_dimension
- property dimension
The (real) dimension of the quadric.
More precisely, the maximum of the dimensions of the manifolds contained in the set of real points in the quadric.
Ignores affine coordinates! I.e. we don’t distinguish between the quadric lying at infinity or not.
- Returns:
- int
Notes
This function was fully intuited. There is no guarantee that this gives correct results.
- property dimension_complex
Complex dimension of the quadric.
This is the same as the real dimension, except that the positive definite quadric is not empty and not a special case anymore. In fact, there is only one non-degenerate quadric up to projective transformation, the one with diagonal
[1,...,1].- Returns:
- int
- embed(subspace=None)[source]
The embedded object.
We can embed a subset X of n-dimensional projective space into m-dimensional space (where m >= n) by choosing an n-dimensional subspace S in RP^m together with a basis B. We then interpret the original homogeneous coordinates as coordinates w.r.t. this basis B.
More concretely: If M is the
matrixof S, we defineX.embed(S) := { [M @ x] | [x] in X }.X.embed(S)must be the same kind of object as X, for example if X is a euclidean sphere, the basis M must be chosen so thatX.embed(S)is also a euclidean sphere.- Parameters:
- subspaceSubspace (default=None)
Subspace in m-dimensional ambient space whose dimension is the ambient dimension of
self(where m >= n). The homogeneous coordinates of points are used as cordinates w.r.t. the given basis ofsubspace.The default is the coordinate hyperplane {x_n+1 = 0} in (n+1)-dimensional space, where n is the ambient dimension of
self. The basis is the standard basis with the second to last basis vector missing.
- Returns:
- type(self)
Object in m-dimensional ambient space contained in
subspace.
- Raises:
- ValueError
If embedding w.r.t. the given basis would result in an object of a different type.
- unembed(subspace=None)[source]
Inverse of
embed.- Parameters:
- subspaceSubspace (default=None)
k-dim. subspace to treat as the new ambient space. coordinates of points will be computed w.r.t. the given basis of
subspace.The default is the coordinate hyperplane {x_n = 0} which will fail if the object is not contained in this subspace.
- Returns:
- type(self)
Object in
k-dim. ambient space.
- Raises:
- ValueError
If object is not contained in
subspace.If coordinate computation would result in an object of a different type.
- inner_product(v, w)[source]
Inner product defined by / defining the quadric.
- Parameters:
- v, wnumpy.ndarray of shape (ambient_dimension + 1,)
Two vectors that lie in the containing subspace.
- Returns:
- float
a.T @ matrix @ b, whereaandbare the coordinates ofvandwin terms of the given basis of the containing subspace.
- cayley_klein_distance(v, w)[source]
Cayley-Klein “distance”.
This is defined as
b(v, w) ** 2 / (b(v, v) * b(w, w))
Where b is the inner product induced by the absolute. None of the points can lie on the absolute.
- Parameters:
- v, wnumpy.ndarray or Point
Homogeneous coordinate vectors or Point instances
- Returns:
- float
- Raises:
- ValueError
If either of the points is contained in the absolute quadric.
- conjugate(S1, S2)[source]
Conjugacy of two subspaces.
Whether two subspaces are conjugate, i.e. if approximately
inner_product(v, w) == 0for all v in S1 and w in S2.- Parameters:
- S1, S2ddg.geometry.subspaces.Subspace or numpy.ndarray
Subspaces contained in self.subspace. Arrays will be interpreted as matrices whose columns are points in homogeneous coordinates. In particular, 1D arrays are simply points in homogeneous coordinates.
- Returns:
- bool
- signature(subspace=None, affine=False)[source]
Alias for
signature().
- normalize(affine=False)[source]
Return an equal quadric expressed in coordinates that normalize it.
Returns an equal quadric Q_normalized such that
Q_normalized.matrix == sgn.matrix
where sgn = self.signature(affine). See
ddg.math.symmetric_matrices.Signatureandddg.math.symmetric_matrices.AffineSignaturefor more information.If
affine=True,Q_normalized.subspace.pointswill be in the form [d1,…,dn, p], where n is the dimension of the subspace, d1,…,dn are directions at infinity and p is a point in the subspace not at infinity.- Parameters:
- affinebool (default=False)
- Returns:
- Q_normalizedQuadric
- property rank
Rank of self.matrix.
- Returns:
- int
- property corank
Corank of self.matrix.
- Returns:
- int
- property singular_subspace
Singular subspace.
Subspace containing all singular points of the quadric (points in the kernel of
self.matrix).- Returns:
- ddg.geometry.subspaces.Subspace of dimension
corank - 1and the - same ambient dimension as the quadric.
- ddg.geometry.subspaces.Subspace of dimension
- property non_degenerate_subspace
Non-degenerate subspace.
Complementary subspace of the kernel of
self.matrix.- Returns:
- ddg.geometry.subspaces.Subspace
Has dimension
rank - 1and the same ambient dimension as the quadric.
- property is_degenerate
Whether the quadric is degenerate.
- Returns:
- bool
- dual_transformation(F)[source]
Dualizes a transformation of the ambient space.
- Parameters:
- Fnumpy.ndarray of shape (ambient_dimension+1, ambient_dimension+1)
An invertible matrix.
- Returns:
- F_dualnumpy.ndarray of shape (ambient_dimension+1,ambient_dimension+1)
This is an invertible matrix that approximately satisfies
F_dual @ B_dual == F @ B @ np.linalg.inv((F @ B).T @ (F @ B)), whereB_dualis the subspace of the dual quadric. That is, it maps the old dual basis to the new one.
- transform(F)[source]
Return a linearly transformed copy.
The transformation is assumed to be a projective transformation in homogeneous coordinates.
- Parameters:
- Fnumpy.ndarray of shape (ambient_dimension + 1, ambient_dimension + 1)
- Returns:
- type(self)
- change_affine_picture(before, after=-1)
Transform the object to a different affine view.
Dehomogenizing the object post-transform with affine component
afterwill produce the same affine picture as dehomogenizing the object pre-transform with affine componentbefore.The actual transformation that achieves this just permutes the homogeneous coordinates as follows: It deletes the entry at
beforeand inserts it again at positionafter.Here are two examples of how you might use this function:
You defined a projective object
Xwith a certain affine picture in mind and you followed our convention of using affine component -1. You now want to see what it would look like when dehomogenized using a different affine componenti. To do this, you would just doX_ = X.change_affine_picture(i)and then visualize the object normally.You don’t like our convention of dehomogenizing by the last component and want to define your object
Xwith the affine picture with respect to affine componentiin mind. To visualize your object as you imagine it, you would also doX_ = X.change_affine_picture(i).
- Parameters:
- beforeint
- afterint (default=-1)
- Returns:
- type(self)
- class ddg.geometry.quadrics.Pencil(Q1, Q2, **kwargs)[source]
Bases:
LinearTransformablePencil of quadrics in a projective space.
- Parameters:
- Q1, Q2Quadric or numpy.ndarray
Quadrics spanning the pencil. If given as arrays, they will be created.
- **kwargsdict
Keyword arguments to be passed to Quadric during creation of Q1 and Q2, if they are given as arrays.
- Raises:
- ValueError
If the geometries of the quadrics don’t match
If the quadrics are not in the same subspace
See also
- property ambient_dimension
- property subspace
- transform(F)[source]
Return a linearly transformed copy.
The transformation is assumed to be a projective transformation in homogeneous coordinates.
- Parameters:
- Fnumpy.ndarray of shape (ambient_dimension + 1, ambient_dimension + 1)
- Returns:
- type(self)
- matrix(u)[source]
Return the matrix of a quadric in the pencil.
The pencil is parametrized as:
RP^1 -> pencil, [u1, u2] -> [u1*Q1 + u2*Q2].
We identify [1, a] <-> a and [0, 1] <-> inf.
- Parameters:
- uarray_like (float, float) or float
A finite float will be interpreted as (1, u) and inf will be interpreted as (0, 1). -inf is interpreted as (0, -1).
- Returns:
- numpy.ndarray of shape (n, n)
- quadric(u)[source]
Return a quadric in the pencil. Complex quadrics are not supported.
The pencil is parametrized as:
RP^1 -> pencil, [u1, u2] -> [u1*Q1 + u2*Q2].
We identify [1, a] <-> a and [0, 1] <-> inf.
- Parameters:
- uarray_like (float, float) or float including inf.
A finite float will be interpreted as (1, u) and inf will be interpreted as (0, 1). -inf is interpreted as (0, -1).
- Returns:
- Quadric
- roots()[source]
Find values for which quadrics in the pencil are degenerate.
This function calculates the complex roots of the polynomial
P := det(Q1 + lambda * Q2)and their multiplicity. If the sum of the multiplicities less thanN := subspace.dimension + 1,which means thatQ2is degenerate,complex('inf')is added and assigned the “remaining” multiplicityN - deg(P).- Returns:
- dict {complex: int}
Dictionary whose keys are the roots as complex numbers (including infinity) and whose values are their multiplicity.
- degenerate_quadrics()[source]
Calculate real degenerate quadrics in the pencil.
- Returns:
- list of Quadric
- change_affine_picture(before, after=-1)
Transform the object to a different affine view.
Dehomogenizing the object post-transform with affine component
afterwill produce the same affine picture as dehomogenizing the object pre-transform with affine componentbefore.The actual transformation that achieves this just permutes the homogeneous coordinates as follows: It deletes the entry at
beforeand inserts it again at positionafter.Here are two examples of how you might use this function:
You defined a projective object
Xwith a certain affine picture in mind and you followed our convention of using affine component -1. You now want to see what it would look like when dehomogenized using a different affine componenti. To do this, you would just doX_ = X.change_affine_picture(i)and then visualize the object normally.You don’t like our convention of dehomogenizing by the last component and want to define your object
Xwith the affine picture with respect to affine componentiin mind. To visualize your object as you imagine it, you would also doX_ = X.change_affine_picture(i).
- Parameters:
- beforeint
- afterint (default=-1)
- Returns:
- type(self)
- ddg.geometry.quadrics.touching_cone(p, quadric, in_subspace=False)[source]
Calculate touching cone.
The touching cone of a quadric Q and a point P is the set of lines through P that are tangent to Q.
Note that by default, this function looks at tangency in the ambient space as opposed to within
quadric.subspace. This means that if the quadric is contained in a proper subspace, the function returns the join ofpandquadric.- Parameters:
- pnumpy.ndarray of shape (quadric.ambient_dimension+1,) or Point
Point in homogeneous coordinates. Must lie in
quadric.subspaceif in_subspace is True.- quadricQuadric
- in_subspacebool (default=False)
- Returns:
- Quadric or Subspace
- Raises:
- ValueError
If
in_subspaceis True andpis not contained inquadric.subspace.
- ddg.geometry.quadrics.cayley_klein_sphere(center, radius, absolute)[source]
Create a Cayley-Klein sphere from center, radius and absolute.
Let b be the inner product induced by the
absolute. A Cayley-Klein sphere is defined as the solution set of:b(center, x) ** 2 - radius * b(center, center) * b(x, x) = 0
Note that if
centerlies on theabsolute, you will just get the polar hyperplane ofcenter.- Parameters:
- centerPoint
- radiusfloat
- absoluteQuadric
- Returns:
- Quadric
- Raises:
- ValueError
If
centeris not inabsolute.subspace.
- ddg.geometry.quadrics.generalized_cayley_klein_sphere(center, radius, absolute)[source]
Create Generalized Cayley-Klein sphere from center, “radius” and absolute.
Let b be the inner product induced by the
absolute. A Cayley-Klein sphere is defined as the solution set of:b(center, x) ** 2 - radius * b(x, x) = 0
This allows centers to lie on the absolute quadric, at the expense of depending on the representative vector of
center. The equation of a regular Cayley-Klein sphere can still be obtained by using the new radiusradius * b(center, center).- Parameters:
- centerPoint
- radiusfloat
- absoluteQuadric
- Returns:
- Quadric
- Raises:
- ValueError
If
centeris not inabsolute.subspace.
- ddg.geometry.quadrics.axis(cone)[source]
Find the axis of a non-parabolic cone.
More precisely: The axis of a non-parabolic quadric with signature (n-1, 1, 1), where n is the dimension of the containing subspace.
- Parameters:
- coneQuadric
- Returns:
- Subspace
- Raises:
- ValueError
If Quadric does not have the signature mentioned above.
- ddg.geometry.quadrics.normalization(quadric, affine=False)[source]
Signature and normalizing transformation.
Approximately satisfies:
F.T @ quadric.matrix @ F == sgn.matrix
See
ddg.math.symmetric_matrices.Signatureandddg.math.symmetric_matrices.AffineSignaturefor more information.Note that this is a transformation within the subspace as opposed to a transformation of the ambient space and thus cannot be used with
quadric.transform.- Parameters:
- quadricQuadric
- affinebool (default=False)
Whether to normalize to projective or affine normal form.
- Returns:
- sgnSignature or AffineSignature
- Fnumpy.ndarray of shape (ambient_dimension+1, dimension+2)
Transformation that normalizes the quadric
- ddg.geometry.quadrics.intersect_quadric_subspace(quadric, subspace)[source]
Intersect quadric with subspace
- Parameters:
- quadricQuadric
- subspaceSubspace
- Returns:
- Quadric
See also
ddg.geometry.intersection.intersectTo intersect more than two objects of various types.
- ddg.geometry.quadrics.join_quadric_subspace(quadric, subspace)[source]
Join a quadric and a subspace.
The result will be the projective cone with top S and basis Q.
- Parameters:
- quadricQuadric
- subspaceSubspace
- Returns:
- Quadric or Subspace
- Raises:
- ValueError
If
quadric.subspaceandsubspaceare not disjoint.- NotImplementedError
If quadric.subspace and subspace are not disjoint and subspace is not a point
If the join is an object like a “solid cone”, which we can’t represent.
See also
ddg.geometry.intersection.joinTo join more than two objects of various types.
- ddg.geometry.quadrics.intersect_quadrics(quadric1, quadric2, affine=False, atol=1e-09, rtol=0.0)[source]
Intersection curve of certain quadrics.
Currently only works for two quadrics that are both contained in a pencil
u1 * diag([1, 1, 0, -1]) + u2 * diag([0, k, 1, -1]) \_______ ________/ \_______ ________/ \/ \/ D1 D2for some k in [0, 1]. The quadrics can be contained in any 3D subspace as long as they are given w.r.t. the same basis. The function checks if both quadrics are contained in a pencil like this.
If you know your two quadrics with matrices Q1, Q2 are contained in a transformed version of such a pencil, i.e.
u1 * F.T @ D1 @ F + u2 * F.T @ D2 @ F
for some known invertible F, you can make it work as well: Let B be quadric1.subspace.matrix. Then the quadrics
Quadric(inv(F.T) @ Q1 @ inv(F), subspace=(B @ inv(F)).T) Quadric(inv(F.T) @ Q1 @ inv(F), subspace=(B @ inv(F)).T)
can be intersected with this function. Automatic detection of this is not yet implemented.
- Parameters:
- quadric1, quadric2Quadric
- affinebool (default=False)
Whether the resulting curve should output affine or homogeneous coordinates.
- atolfloat (default=1e-9)
- rtolfloat (default=0.0)
This function uses the global tolerance defaults if
atolorrtolare set to None. Seeddg.nonexactfor details.
- Returns:
- NetCollection
- Raises:
- ValueError
If the two quadrics are given in different coordinate systems.
If quadric1 and quadric2 do not span the above-mentioned pencil.
Notes
For visualization purposes, not all subspace bases work well, because the curve might pass through infinity.
- ddg.geometry.quadrics.polarize(obj, quadric)[source]
Polarize a geometric object with respect to a quadric.
- Parameters:
- objGeometric object
Currently supported: Subspace, Quadric.
- quadricQuadric
- Returns:
- type(obj)
- Raises:
- TypeError
If the type of object is not supported.
- ddg.geometry.quadrics.signature(quadric, subspace=None, affine=False)[source]
Signature of a quadric, optionally restricted to a subspace.
- Parameters:
- subspaceSubspace or None (default=None)
Subspace contained in self.subspace
- affinebool (default=False)
Whether to return projective or affine signature
- Returns:
- Signature or AffineSignature
- Raises:
- ValueError
If subspace is not contained in self.subspace.