ddg.geometry package

Submodules

Module contents

ddg.geometry.elliptic

alias of ProjectiveModel

ddg.geometry.euclidean

alias of ProjectiveModel

ddg.geometry.dual_euclidean

alias of DualProjectiveModel

ddg.geometry.hyperbolic

alias of ProjectiveModel

ddg.geometry.laguerre

alias of ProjectiveModel

ddg.geometry.lie

alias of ProjectiveModel

ddg.geometry.moebius

alias of ProjectiveModel

ddg.geometry.spherical

alias of ProjectiveModel

class ddg.geometry.Quadric(matrix, subspace=None, atol=None, rtol=None)[source]

Bases: Embeddable, LinearTransformable

Quadric in real projective space.

Let q be a quadratic form on R^(n+1). The quadric corresponding to q is the set

{ [x] in RP^n : q(x) = 0 }.
Parameters:
matrixnumpy.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.geometry.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 matrix is not symmetric

  • If 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)
subspaceddg.geometry.Subspace
ambient_dimension
dimension

The (real) dimension of the quadric.

dimension_complex

Complex dimension of the quadric.

rank

Rank of self.matrix.

corank

Corank of self.matrix.

is_degenerate

Whether the quadric is degenerate.

singular_subspace

Singular subspace.

non_degenerate_subspace

Non-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
at_infinity()[source]

Whether the object is contained in the hyperplane at infinity.

Returns:
bool
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 matrix of S, we define

X.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 that X.embed(S) is also a euclidean sphere.

Parameters:
subspaceddg.geometry.Subspace (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 of subspace.

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:
subspaceddg.geometry.Subspace (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, where a and b are the coordinates of v and w in 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 ddg.geometry.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) == 0 for all v in S1 and w in S2.

Parameters:
S1, S2ddg.geometry.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
polarize(obj)[source]

Alias for polarize(obj, self).

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.Signature and ddg.math.symmetric_matrices.AffineSignature for more information.

If affine=True, Q_normalized.subspace.points will 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_normalizedddg.geometry.Quadric
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.Subspace of dimension corank - 1 and the
same ambient dimension as the quadric.
property non_degenerate_subspace

Non-degenerate subspace.

Complementary subspace of the kernel of self.matrix.

Returns:
ddg.geometry.Subspace

Has dimension rank - 1 and the same ambient dimension as the quadric.

property is_degenerate

Whether the quadric is degenerate.

Returns:
bool
dualize()[source]
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)), where B_dual is 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 after will produce the same affine picture as dehomogenizing the object pre-transform with affine component before.

The actual transformation that achieves this just permutes the homogeneous coordinates as follows: It deletes the entry at before and inserts it again at position after.

Here are two examples of how you might use this function:

  1. You defined a projective object X with 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 component i. To do this, you would just do X_ = X.change_affine_picture(i) and then visualize the object normally.

  2. You don’t like our convention of dehomogenizing by the last component and want to define your object X with the affine picture with respect to affine component i in mind. To visualize your object as you imagine it, you would also do X_ = X.change_affine_picture(i).

Parameters:
beforeint
afterint (default=-1)
Returns:
type(self)
class ddg.geometry.Pencil(Q1, Q2, **kwargs)[source]

Bases: LinearTransformable

Pencil of quadrics in a projective space.

Parameters:
Q1, Q2ddg.geometry.Quadric 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

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:
ddg.geometry.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 than N := subspace.dimension + 1 ,which means that Q2 is degenerate, complex('inf') is added and assigned the “remaining” multiplicity N - 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 ddg.geometry.Quadric
change_affine_picture(before, after=-1)

Transform the object to a different affine view.

Dehomogenizing the object post-transform with affine component after will produce the same affine picture as dehomogenizing the object pre-transform with affine component before.

The actual transformation that achieves this just permutes the homogeneous coordinates as follows: It deletes the entry at before and inserts it again at position after.

Here are two examples of how you might use this function:

  1. You defined a projective object X with 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 component i. To do this, you would just do X_ = X.change_affine_picture(i) and then visualize the object normally.

  2. You don’t like our convention of dehomogenizing by the last component and want to define your object X with the affine picture with respect to affine component i in mind. To visualize your object as you imagine it, you would also do X_ = X.change_affine_picture(i).

Parameters:
beforeint
afterint (default=-1)
Returns:
type(self)
ddg.geometry.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 of p and quadric.

Parameters:
pnumpy.ndarray of shape (quadric.ambient_dimension+1,) or ddg.geometry.Point

Point in homogeneous coordinates. Must lie in quadric.subspace if in_subspace is True.

quadricddg.geometry.Quadric
in_subspacebool (default=False)
Returns:
ddg.geometry.Quadric or ddg.geometry.Subspace
Raises:
ValueError

If in_subspace is True and p is not contained in quadric.subspace.

ddg.geometry.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 center lies on the absolute, you will just get the polar hyperplane of center.

Parameters:
centerddg.geometry.Point
radiusfloat
absoluteddg.geometry.Quadric
Returns:
ddg.geometry.Quadric
Raises:
ValueError

If center is not in absolute.subspace.

ddg.geometry.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 radius radius * b(center, center).

Parameters:
centerddg.geometry.Point
radiusfloat
absoluteddg.geometry.Quadric
Returns:
ddg.geometry.Quadric
Raises:
ValueError

If center is not in absolute.subspace.

ddg.geometry.cone_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:
coneddg.geometry.Quadric
Returns:
ddg.geometry.Subspace
Raises:
ValueError

If Quadric does not have the signature mentioned above.

ddg.geometry.quadric_normalization(quadric, affine=False)[source]

Signature and normalizing transformation.

Approximately satisfies:

F.T @ quadric.matrix @ F == sgn.matrix

See ddg.math.symmetric_matrices.Signature and ddg.math.symmetric_matrices.AffineSignature for 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:
quadricddg.geometry.Quadric
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.polarize(obj, quadric)[source]

Polarize a geometric object with respect to a quadric.

Parameters:
objGeometric object

Currently supported: ddg.geometry.Subspace, Quadric.

quadricddg.geometry.Quadric
Returns:
type(obj)
Raises:
TypeError

If the type of object is not supported.

ddg.geometry.signature(quadric, subspace=None, affine=False)[source]

Signature of a quadric, optionally restricted to a subspace.

Parameters:
subspaceddg.geometry.Subspace 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.

class ddg.geometry.Point(point, atol=None, rtol=None)[source]

Bases: Subspace

Subclass for points (0-dim. projective subspaces).

Parameters:
pointlist or numpy.ndarray of shape (n,)
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.

Attributes:
point

Homogeneous coordinate vector representing the point.

affine_point

Affine coordinate vector representing the point.

property point

Homogeneous coordinate vector representing the point.

Returns:
numpy.ndarray (dimension+1,)
property affine_point

Affine coordinate vector representing the point.

Returns:
numpy.ndarray of shape (dimension,)
Raises:
ValueError

If the point is at infinity.

property affine_matrix

Matrix whose columns span the affine part of the subspace.

Computes points in affine coordinates that, when homogenized, form a basis for the subspace. Returns them as the columns of a matrix.

Returns:
numpy.ndarray of shape (ambient_dimension, dimension+1)
Raises:
ValueError

If the subspace is at infinity.

property affine_point_and_directions

Return point in the subspace and directions.

Returns affine coordinate vectors p and d1, …, dk such that the original subspace is spanned by [p,1], [d1,0], …, [dk,0].

The point is the one that is closest to the zero vector in affine coordinates and the directions are orthonormal.

Returns:
numpy.ndarray, list of numpy.ndarray
property affine_points

List of points spanning the affine part of the subspace.

Computes points in affine coordinates that, when homogenized, form a basis for the subspace.

Returns:
list of numpy.ndarray of shape (ambient_dimension,)
property ambient_dimension
at_infinity()

Whether the object is contained in the hyperplane at infinity.

Returns:
bool
center(center, remove_index=None, insert_index=0)

Returns subspace with a point inserted into the basis. Useful for visualization.

See center_subspace() for full documentation.

See also

ddg.geometry.center_subspace

Equivalent function

change_affine_picture(before, after=-1)

Transform the object to a different affine view.

Dehomogenizing the object post-transform with affine component after will produce the same affine picture as dehomogenizing the object pre-transform with affine component before.

The actual transformation that achieves this just permutes the homogeneous coordinates as follows: It deletes the entry at before and inserts it again at position after.

Here are two examples of how you might use this function:

  1. You defined a projective object X with 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 component i. To do this, you would just do X_ = X.change_affine_picture(i) and then visualize the object normally.

  2. You don’t like our convention of dehomogenizing by the last component and want to define your object X with the affine picture with respect to affine component i in mind. To visualize your object as you imagine it, you would also do X_ = X.change_affine_picture(i).

Parameters:
beforeint
afterint (default=-1)
Returns:
type(self)
property codimension
dehomogenize()

Returns subspace with last entries of basis vectors normalized to 1. Useful for visualization.

See dehomogenize_subspace() for full documentation.

See also

ddg.geometry.dehomogenize_subspace

Equivalent function

property dimension
dualize(ambient_space=None)

Return dual subspace.

Parameters:
ambient_spaceddg.geometry.Subspace (default=None)

Other subspace containing this subspace that should be used as ambient space when dualizing. None means whole space.

Returns:
ddg.geometry.Subspace
embed(subspace=None)

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 matrix of S, we define

X.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 that X.embed(S) is also a euclidean sphere.

Parameters:
subspaceddg.geometry.Subspace (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 of subspace.

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.

orthonormalize()

Returns subspace with a regularized basis. Useful for visualization.

See orthonormalize_subspace() for full documentation.

See also

ddg.geometry.orthonormalize_subspace

Equivalent function

orthonormalize_and_center(center)

Returns subspace with a regularized basis and a point inserted in the basis Useful for visualization.

See orthonormalize_and_center_subspace() for full documentation.

property points

List of points spanning the subspace in homogeneous coordinates.

Returns:
list of numpy.ndarray of shape (ambient_dimension+1,)
transform(F)

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)
unembed(subspace=None)

Inverse of embed.

Parameters:
subspaceddg.geometry.Subspace (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.

class ddg.geometry.Subspace(*points, atol=None, rtol=None)[source]

Bases: Embeddable, LinearTransformable

Subspace of a projective space. Represented by a number of vectors in homogeneous coordinates.

Parameters:
*pointsarray_like of list or numpy.ndarray of shape (n,)

Homogeneous coordinate vectors spanning the subspace. If the span is 1-dimensional, automatically casts to _subspaces.Point

Non-float dtypes will be converted to float.

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.

Notes

Subspaces can be empty. In this case, points are stored as an empty matrix with shape (n,0) if the ambient dimension is n-1. Empty spaces must be initialized with 0-vectors.

Attributes:
points

List of points spanning the subspace in homogeneous coordinates.

matrix
affine_points

List of points spanning the affine part of the subspace.

affine_matrix

Matrix whose columns span the affine part of the subspace.

affine_point_and_directions

Return point in the subspace and directions.

dimension
ambient_dimension
codimension

Methods

at_infinity()

Whether the object is contained in the hyperplane at infinity.

property points

List of points spanning the subspace in homogeneous coordinates.

Returns:
list of numpy.ndarray of shape (ambient_dimension+1,)
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 matrix of S, we define

X.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 that X.embed(S) is also a euclidean sphere.

Parameters:
subspaceddg.geometry.Subspace (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 of subspace.

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:
subspaceddg.geometry.Subspace (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.

property affine_points

List of points spanning the affine part of the subspace.

Computes points in affine coordinates that, when homogenized, form a basis for the subspace.

Returns:
list of numpy.ndarray of shape (ambient_dimension,)
property affine_matrix

Matrix whose columns span the affine part of the subspace.

Computes points in affine coordinates that, when homogenized, form a basis for the subspace. Returns them as the columns of a matrix.

Returns:
numpy.ndarray of shape (ambient_dimension, dimension+1)
Raises:
ValueError

If the subspace is at infinity.

property affine_point_and_directions

Return point in the subspace and directions.

Returns affine coordinate vectors p and d1, …, dk such that the original subspace is spanned by [p,1], [d1,0], …, [dk,0].

The point is the one that is closest to the zero vector in affine coordinates and the directions are orthonormal.

Returns:
numpy.ndarray, list of numpy.ndarray
at_infinity()[source]

Whether the object is contained in the hyperplane at infinity.

Returns:
bool
property dimension
property ambient_dimension
property codimension
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)
dualize(ambient_space=None)[source]

Return dual subspace.

Parameters:
ambient_spaceddg.geometry.Subspace (default=None)

Other subspace containing this subspace that should be used as ambient space when dualizing. None means whole space.

Returns:
ddg.geometry.Subspace
orthonormalize()[source]

Returns subspace with a regularized basis. Useful for visualization.

See orthonormalize_subspace() for full documentation.

See also

ddg.geometry.orthonormalize_subspace

Equivalent function

center(center, remove_index=None, insert_index=0)[source]

Returns subspace with a point inserted into the basis. Useful for visualization.

See center_subspace() for full documentation.

See also

ddg.geometry.center_subspace

Equivalent function

orthonormalize_and_center(center)[source]

Returns subspace with a regularized basis and a point inserted in the basis Useful for visualization.

See orthonormalize_and_center_subspace() for full documentation.

dehomogenize()[source]

Returns subspace with last entries of basis vectors normalized to 1. Useful for visualization.

See dehomogenize_subspace() for full documentation.

See also

ddg.geometry.dehomogenize_subspace

Equivalent function

change_affine_picture(before, after=-1)

Transform the object to a different affine view.

Dehomogenizing the object post-transform with affine component after will produce the same affine picture as dehomogenizing the object pre-transform with affine component before.

The actual transformation that achieves this just permutes the homogeneous coordinates as follows: It deletes the entry at before and inserts it again at position after.

Here are two examples of how you might use this function:

  1. You defined a projective object X with 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 component i. To do this, you would just do X_ = X.change_affine_picture(i) and then visualize the object normally.

  2. You don’t like our convention of dehomogenizing by the last component and want to define your object X with the affine picture with respect to affine component i in mind. To visualize your object as you imagine it, you would also do X_ = X.change_affine_picture(i).

Parameters:
beforeint
afterint (default=-1)
Returns:
type(self)
ddg.geometry.angle_bisector_orientation_preserving(hyperplane1, hyperplane2)[source]

Create the orientation preserving angle bisecting hyperplane of two given hyperplanes. It is orientation preserving in the sense, that reflection in this angle bisector maps one hyperplane to the other with matching orientation.

Parameters:
hyperplane1ddg.geometry.Subspace
hyperplane2ddg.geometry.Subspace
Returns:
ddg.geometry.Subspace
ddg.geometry.angle_bisector_orientation_reversing(hyperplane1, hyperplane2)[source]

Create the orientation reversing angle bisecting hyperplane of two given hyperplanes. It is orientation reversing in the sense, that reflection in this angle bisector maps one hyperplane to the other with opposite orientation.

Parameters:
hyperplane1ddg.geometry.Subspace
hyperplane2ddg.geometry.Subspace
Returns:
ddg.geometry.Subspace
ddg.geometry.angle_bisectors(hyperplane1, hyperplane2)[source]

Create the two angle bisecting hyperplanes of two given hyperplanes. The first entry in the output is the angle bisector that is orientation preserving. The second one is orientation reversing.

Parameters:
hyperplane1ddg.geometry.Subspace
hyperplane2ddg.geometry.Subspace
Returns:
(ddg.geometry.Subspace, ddg.geometry.Subspace)
ddg.geometry.center_subspace(subspace, center, remove_index=None, insert_index=0)[source]

Insert a specific point into the basis of a subspace.

This is especially useful in preparation for visualization: When applying this function and then using the “convex” parametrization in to_smooth_net, the parametrization will be centered around the new center, if it is a point not at infinity.

Parameters:
subspaceddg.geometry.Subspace
centerddg.geometry.Point or numpy.ndarray of shape (k,) or (k+1,)

Where k is the ambient dimension of the subspace. Point must lie in subspace. Can be given as Point object or as array containing affine or homogeneous coordinates.

remove_indexint (default=None)

Index of basis vector that should be replaced with center. If None, we search for one.

insert_indexint (default=0)

Index where center should be inserted.

Returns:
ddg.geometry.Subspace

The same subspace with a basis that has center at position insert_index.

Raises:
ValueError
  • If center does not lie in the subspace.

  • If the vector at remove_index could not be replaced with center while still having a basis.

ddg.geometry.coordinate_hyperplane(n, zero_component=-1, origin_index=-1)[source]

“Equatorial plane” in n-dimensional space.

Returns the coordinate hyperplane {x_i = 0}, where i=zero_component.

Parameters:
nint

Ambient dimension

zero_componentint (default=-1)

Which component should be 0 in this hyperplane in affine coordinates.

origin_indexint (default=-1)

Where to insert the “origin” (the point not at infinity)

Returns:
ddg.geometry.Subspace
ddg.geometry.dehomogenize_subspace(subspace)[source]

Normalize last entries of basis vectors not at infinity to 1.

Parameters:
subspaceddg.geometry.Subspace
Returns:
ddg.geometry.Subspace

The same subspace with normalized basis vectors.

ddg.geometry.hyperplane_from_normal(normal, level=None, point=None, **kwargs)[source]

An affine hyperplane defined by either <x, normal> == level, or the normal and a point (given in affine coordinates) on the plane.

ddg.geometry.least_square_subspace(points, k)[source]

Computes the k-dimensional subspace closest to the affine coordinates of N points.

Parameters:
pointssequence of ddg.geometry.Point

Points containing homogeneous coordinates.

kint

Dimension of the subspace.

Returns:
subspaceddg.geometry.Subspace

k-dimensional projective subspace.

ddg.geometry.least_square_subspace_from_affine_points(points, k)[source]

Computes the k-dimensional subspace closest to N affine points. See below for more details.

Parameters:
pointssequence of numpy.ndarray, each of shape (n,)

Affine coordinates of N points.

kint

Dimension of the subspace.

Returns:
subspaceddg.geometry.Subspace

k-dimensional projective subspace.

Raises:
ValueError

If k is strictly greater than the ambient projective dimension n.

Notes

The returned subspace is best-fitting k-dimensional subspace to the N given points in the sense that it minimizes the sum of the squares of the Euclidean distances of the points to it.

ddg.geometry.level(hyperplane)[source]

Level l of a hyperplane.

The hyperplane consists of all points x such that

<x, N> = l

where N is the unit normal of the hyperplane.

The level is the distance of the hyperplane from the origin in the normal direction, i.e. the hyperplane contains l * N.

Parameters:
hyperplaneddg.geometry.Subspace

Hyperplane in n-dimensional ambient space.

Returns:
lfloat
ddg.geometry.normal(hyperplane)[source]

Unit normal vector N of a hyperplane.

The hyperplane consists of all points x such that

<x, N> = l

where l is the level of the hyperplane.

Parameters:
hyperplaneddg.geometry.Subspace

Hyperplane in n-dimensional ambient space.

Returns:
Nnumpy.ndarray of shape (n,)
ddg.geometry.normal_with_level(hyperplane)[source]

Unit normal vector and negative level of a hyperplane in one vector.

A hyperplane having normal N and level l means that in affine coordinates, the hyperplane is the set of points x such that

<x, N> = l,

which is equivalent to

<x, N> - l = 0.

This function computes a representative vector v = [N, -l] of the dual space, normalized such that N has unit length.

-N and -l define the same hyperplane. To fix this sign, an orientation would have to be given on the hyperplane. This function does not distinguish between the two choices, so the sign should be treated as random.

Parameters:
hyperplaneddg.geometry.Subspace

Hyperplane in n-dimensional ambient space.

Returns:
Nlnumpy.ndarray of shape (n+1,)

The vector [N, -l]. The subspace Point(Nl).dualize() is the original hyperplane.

ddg.geometry.normals(subspace)[source]

Return all normal directions of a subspace.

If p1, p2 are two points in the subspace in affine coordinates and n is a normal direction, then

<p1 - p2, n> = 0.

Parameters:
subspaceddg.geometry.Subspace
Returns:
list of numpy.ndarray of shape (subspace.ambient_dimension,)

Normals in affine coordinates.

ddg.geometry.orthonormalize_and_center_subspace(subspace, center)[source]

Regularize the basis of a subspace. Useful for visualization.

Returns an equal subspace with a basis of the form [p, v1,...,vk], where p is the center with last entry 1 and v1,...,vk are orthonormal direction vectors at infinity. This is only possible if the subspace is not at infinity.

When using the “convex” parametrization in to_smooth_net, the parametrization of the subspace with this new basis will be

f(x1,...,xk) = p + x1 * v1 + ... + xk * vk
Parameters:
subspaceddg.geometry.Subspace
centerddg.geometry.Point or numpy.ndarray of shape (k,) or (k+1,)

Where k is the ambient dimension of the subspace. Point must lie in subspace. Can be given as Point object or as array containing affine or homogeneous coordinates.

Returns:
ddg.geometry.Subspace

The same subspace with the regularized basis.

Raises:
ValueError
  • If center does not lie in the subspace.

  • If subspace is at infinity.

ddg.geometry.orthonormalize_subspace(subspace)[source]

Regularize the basis of a subspace. Useful for visualization.

Returns an equal subspace with a basis of the form [p, v1,...,vk], where p is the point in the subspace closest to the origin with last entry 1 and v1,...,vk are orthonormal direction vectors at infinity. This is only possible if the subspace is not at infinity.

When using the “convex” parametrization in to_smooth_net, the parametrization of the subspace with this new basis will be

f(x1,...,xk) = p + x1 * v1 + ... + xk * vk
Parameters:
subspaceddg.geometry.Subspace
Returns:
ddg.geometry.Subspace

The same subspace with the regularized basis.

Raises:
ValueError

If subspace is at infinity.

ddg.geometry.perpendicular_bisector(p1, p2)[source]

Create a hyperplane orthogonal to the join of p1 and p2.

It intersects this line in the midpoint of p1.affine_point and p2.affine_point.

Parameters:
p1: ddg.geometry.Point
p2: ddg.geometry.Point
Returns:
ddg.geometry.Subspace

Hyperplane that is orthogonal to the input line.

ddg.geometry.random_contained_subspace(subspace, dimension=None, seed=None)[source]

Create a random subspace contained in another subspace.

Parameters:
subspaceddg.geometry.Subspace

The subspace that should contain the resulting subspace.

dimensionint (default=None)

Dimension of the resulting subspace. If None, this is chosen randomly between 0 and subspace.dimension (inclusive).

seedint, numpy.random.Generator or None (default=None)

Passes a fixed seed to default Generator class. If passed a Generator, just uses that generator for random generation.

Returns:
ddg.geometry.Subspace
Raises:
ValueError

If dimension is greater than subspace.dimension.

ddg.geometry.random_subspace(ambient_dimension, subspace_dimension=None, seed=None)[source]

Create a random subspace.

Parameters:
ambient_dimensionint
subspace_dimensionint (default=None)

Dimension of the resulting subspace. If None, this is chosen randomly between 0 and ambient_dimension (inclusive).

seedint, numpy.random.Generator or None (default=None)

Passes a fixed seed to default Generator class. If passed a Generator, just uses that generator for random generation.

Returns:
ddg.geometry.Subspace
ddg.geometry.reflect_in_hyperplane(subspace, hyperplane)[source]

Reflects a subspace in a hyperplane.

Parameters:
subspaceddg.geometry.Subspace

Subspace to reflect in the hyperplane.

hyperplaneddg.geometry.Subspace

Hyperplane in n-dimensional ambient space.

Returns:
reflected_hyperplaneddg.geometry.Subspace

The reflected subspace.

Raises:
ValueError

if the reflecor is not a hyperplane, if the hyperplane is at infinity, or if the ambient dimensions don’t match.

ddg.geometry.subspace_from_affine_columns(matrix, **kwargs)[source]

Create a subspace from the columns of a matrix, interpreted as affine coordinates.

Parameters:
matrixnumpy.ndarray

Array whichs columns describe the affine points

**kwargsdict

Other keyword arguments to be passed to the subspace.

Returns:
ddg.geometry.Subspace

Subspace spanned by the given points

ddg.geometry.subspace_from_affine_points(*points, **kwargs)[source]

Create a subspace from affine points.

Parameters:
*pointsiterable of numpy.ndarray or list

Affine coordinate vectors

**kwargsdict

Other keyword arguments to be passed to the subspace.

Returns:
ddg.geometry.Subspace

Subspace spanned by the given points

ddg.geometry.subspace_from_affine_points_and_directions(points, directions, **kwargs)[source]

Create a subspace from affine points and directions.

Parameters:
points(list of numpy.array) or numpy.array

List of points or a single point

directions(list of numpy.array) or numpy.array

List of directions or a single direction

**kwargsdict

Other keyword arguments to be passed to the subspace.

Returns:
ddg.geometry.Subspace

Subspace spanned by the given points and directions

Raises:
ValueError

If both points and directions are empty lists.

ddg.geometry.subspace_from_affine_rows(matrix, **kwargs)[source]

Create a subspace from the rows of a matrix, interpreted as affine coordinates.

Parameters:
matrixnumpy.ndarray

Array whichs columns describe the affine points

**kwargsdict

Other keyword arguments to be passed to the subspace.

Returns:
ddg.geometry.Subspace

Subspace spanned by the given points

ddg.geometry.subspace_from_columns(matrix, **kwargs)[source]

Create subspace using the columns of a matrix as points.

Parameters:
matrixnumpy.ndarray of shape (n+1,k+1)
**kwargsdict

Other arguments to be passed to the Subspace.

Returns:
ddg.geometry.Subspace

Notes

An empty subspace can be created by giving a 0-matrix or a matrix with shape (n,0).

ddg.geometry.subspace_from_rows(matrix, **kwargs)[source]

Create subspace using the rows of a matrix as points.

Parameters:
matrixnumpy.ndarray of shape (k+1,n+1)
**kwargsdict

Other arguments to be passed to the Subspace.

Returns:
ddg.geometry.Subspace

Notes

An empty subspace can be created by giving a 0-matrix or a matrix with shape (0,n+1).

ddg.geometry.whole_space(dimension, **kwargs)[source]

Create whole space of a certain dimension as a trivial subspace.

Parameters:
Dimensionint

Dimension of the space.

**kwargs

Keyword arguments other than points to be passed to Subspace.

Returns:
ddg.geometry.Subspace
ddg.geometry.cayley_klein_sphere_to_quadric(sphere)[source]

Convert Cayley-Klein sphere to quadric.

Parameters:
sphereddg.geometry.spheres.CayleyKleinSphere or
ddg.geometry.spheres.MetricCayleyKleinSphere
Returns:
ddg.geometry.Quadric
ddg.geometry.euclidean_sphere_to_quadric(sphere)[source]

Convert Euclidean sphere to quadric

Parameters:
sphereddg.geometry.spheres.SphereLike
Returns:
ddg.geometry.Quadric
ddg.geometry.generalized_cayley_klein_sphere_to_quadric(sphere)[source]

Convert generalized Cayley-Klein sphere to quadric.

Parameters:
sphereddg.geometry.spheres.GeneralizedCayleyKleinSphere
Returns:
ddg.geometry.Quadric
ddg.geometry.quadric_to_euclidean_sphere(quadric, atol=None, rtol=None)[source]

Convert quadric to a Euclidean sphere, if it is one.

Parameters:
quadricddg.geometry.Quadric
atol, rtolfloat (default=None)

If None is given, the global defaults are used. See ddg.nonexact for details.

Returns:
ddg.geometry.spheres.SphereLike
Raises:
ValueError

If quadric is not a sphere.

ddg.geometry.quadric_to_subspaces(quadric)[source]

If a quadric is equal to a finite collection of subspaces, convert it.

This is the case if and only if Q = quadric.matrix is semidefinite or its rank is less than or equal to 2. In the first case, return ker(Q). Otherwise, return join(ker(Q), P1) and join(ker(Q), P2), where P1, P2 are the two points making up the non-degenerate part of the quadric.

Parameters:
quadricddg.geometry.Quadric
Returns:
tuple of ddg.geometry.Subspace

Notes

No non-degenerate quadric with ambient dimension at least 2 is equal to a collection of subspaces. A degenerate quadric Q is the join of its kernel with its non-degenerate part, i.e. the quadric obtained by restricting the quadratic form to a subspace complementary to the kernel. For this set to be a collection of subspaces, the non-degenerate part must itself be a collection of subspaces. This is only possible if it is contained in a line (i.e. the rank of Q is 2) or it is empty (i.e. Q is positive semidefinite).

class ddg.geometry.Intersection(*obj)[source]

Bases: _IntersectionJoinAux, Iterable

Base class for Intersections.

Parameters:
*objobject

Intersecting objects

Notes

This class supports the “in” keyword, meaning the set element relation.

Attributes:
objectstuple

Tuple of intersecting objects.

Methods

resolve()

Resolve the intersection.

resolve()[source]

Resolve the intersection.

This performs a functools.reduce-like operation on the objects contained in objects until no further reduction is possible with the existing elementary intersection functions.

Returns:
ddg.geometry.Intersection or resolved type

Returns an Intersection object if full reduction was not possible. Otherwise, returns the result of the final reduction step.

property atol

Maximum of absolute tolerances of objects.

Returns:
float
property rtol

Maximum of relative tolerances of objects.

Returns:
float
property types

Set of types of objects.

Returns:
Set
class ddg.geometry.Join(*obj)[source]

Bases: _IntersectionJoinAux, Iterable

Base class for joins.

Parameters:
*objobject

Objects to join

Attributes:
objectstuple

Tuple of joined objects.

Methods

resolve()

Resolve the Join.

property atol

Maximum of absolute tolerances of objects.

Returns:
float
resolve()[source]

Resolve the Join.

This performs a functools.reduce-like operation on the objects contained in objects until no further reduction is possible with the existing elementary join functions.

Returns:
ddg.geometry.Join or resolved type

Returns a Join object if full reduction was not possible. Otherwise, returns the result of the final reduction step.

property rtol

Maximum of relative tolerances of objects.

Returns:
float
property types

Set of types of objects.

Returns:
Set
ddg.geometry.intersect(*objects, resolve=True)[source]

Intersect any number of supported geometric objects.

Parameters:
*objectsAny

Objects to intersect

resolvebool (default=False)

Whether or not the intersection should be resolved immediately

Returns:
ddg.geometry.Intersection or resolved Intersection

Instance of Intersection containing obj1 and obj2 or the intersection of the class obtained by resolving the intersection

ddg.geometry.join(*objects, resolve=True)[source]

Join any number of supported geometric objects.

Parameters:
*objectsAny

Objects to join

resolvebool (default=False)

Whether or not the join should be resolved immediately

Returns:
ddg.geometry.Join or resolved Intersection

Instance of Join containing obj1 and obj2 or the join of the class obtained by resolving the join

ddg.geometry.meet(*objects, resolve=True)

Intersect any number of supported geometric objects.

Parameters:
*objectsAny

Objects to intersect

resolvebool (default=False)

Whether or not the intersection should be resolved immediately

Returns:
ddg.geometry.Intersection or resolved Intersection

Instance of Intersection containing obj1 and obj2 or the intersection of the class obtained by resolving the intersection

ddg.geometry.central_project(object_, target, center)[source]

Central projection dispatcher.

ddg.geometry.central_project_complex(object_, target, center)[source]

Central projection dispatcher (complex mode).

ddg.geometry.central_project_contour(object_, target, center)[source]

Central projection dispatcher (contour mode).

This returns the boundary of the shadow instead of the shadow itself, so to speak.

ddg.geometry.inverse_stereographic_project(object_)[source]
ddg.geometry.inverse_stereographic_project(point: Point, quadric=None, projection_point=None)
ddg.geometry.inverse_stereographic_project(subspace: Subspace, quadric=None, projection_point=None)
ddg.geometry.inverse_stereographic_project(sphere: SphereLike, quadric=None, projection_point=None)

Inverse stereographic projection (Subspace to Quadric) dispatcher.

Accepts different keyword arguments based on type. See the type-specific functions for details.

ddg.geometry.lift_sphere_to_quadric(sphere, quadric, projection_point)[source]

Find the lift of a sphere to a quadric via a point.

This is the inverse of the following map: Map a planar section of quadric to quadric.polarize(projection_point) via projection_point, giving a Cayley-Klein sphere.

Because the inverse map (the projection) is a double cover, this will always return two quadrics.

Parameters:
sphereddg.geometry.spheres.CayleyKleinSphere
quadricddg.geometry.Quadric

Quadric to lift to.

projection_pointddg.geometry.Point

A point not on the quadric.

Returns:
ddg.geometry.Quadric, ddg.geometry.Quadric
Raises:
ValueError
  • If projection_point is on the quadric

  • If center of sphere does not lie in quadric.polarize(projection_point).

  • If no preimage exists. This is the case if the center of the sphere does not lie in the projection image of the quadric.

Notes

Taken from Non-Euclidean Laguerre Geometry and Incircular Nets, page 43.

ddg.geometry.stereographic_project(object_)[source]
ddg.geometry.stereographic_project(subspace: Subspace, hyperplane=None, projection_point=None)
ddg.geometry.stereographic_project(quadric: Quadric, hyperplane=None, projection_point=None)

Stereographic projection (Quadric to subspace) dispatcher.

Accepts different keyword arguments based on type. See the type-specific functions for details.