Source code for ddg.geometry.conversion

"""Conversion module for geometries.

This module contains functions for conversion between different types of
geometric objects.
"""
import numpy as np

import ddg.math.projective as pmath
import ddg.math.symmetric_matrices as sm
from ddg.geometry import euclidean_models
from ddg.geometry.intersection import join
from ddg.geometry.quadrics import (
    Quadric,
    cayley_klein_sphere,
    generalized_cayley_klein_sphere,
    intersect_quadric_subspace,
)
from ddg.geometry.subspaces import Point, subspace_from_affine_points


[docs]def quadric_to_euclidean_sphere(quadric, atol=None, rtol=None): """Convert quadric to a Euclidean sphere, if it is one. Parameters ---------- quadric : Quadric atol, rtol : float (default=None) If None is given, the global defaults are used. See :py:mod:`ddg.nonexact` for details. Returns ------- Sphere Raises ------ ValueError If quadric is not a sphere. """ # Check signature sgn = quadric.signature(affine=True) k = quadric.subspace.dimension if sgn != sm.AffineSignature(k, 1, last_entry=-1): raise ValueError( f"Signature of quadric is {sgn}, but has to be (k, 1) with -1 as " "last entry for it to be a sphere." ) Q = quadric.normalize(affine=True) B = Q.subspace.matrix try: r, _, c = pmath.decompose_similarity(B, atol=atol, rtol=rtol) except ValueError: raise ValueError("Quadric is not a Euclidean sphere.") c = subspace_from_affine_points(c) return euclidean_models.ProjectiveModel.sphere(c, r, subspace=Q.subspace)
[docs]def euclidean_sphere_to_quadric(sphere): """Convert Euclidean sphere to quadric Parameters ---------- sphere : Sphere Returns ------- Quadric """ r = sphere.radius c = sphere.center.affine_point k = sphere.ambient_dimension Q = np.eye(k + 1) Q[-1, -1] = -1 Q = Quadric(Q) F = pmath.affine_transformation(r * np.eye(k), c) Q = Q.transform(F) if sphere.subspace.codimension > 0: Q = intersect_quadric_subspace(Q, sphere.subspace) return Q
[docs]def cayley_klein_sphere_to_quadric(sphere): """Convert Cayley-Klein sphere to quadric. Parameters ---------- sphere : CayleyKleinSphere or MetricCayleyKleinSphere Returns ------- Quadric """ return cayley_klein_sphere( sphere.center, sphere.cayley_klein_radius(), absolute=sphere.absolute )
[docs]def generalized_cayley_klein_sphere_to_quadric(sphere): """Convert generalized Cayley-Klein sphere to quadric. Parameters ---------- sphere : GeneralizedCayleyKleinSphere Returns ------- quadric """ return generalized_cayley_klein_sphere( sphere.center, sphere.generalized_radius(), absolute=sphere.absolute )
[docs]def quadric_to_subspaces(quadric): """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 ---------- quadric : Quadric Returns ------- tuple of 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). """ sgn = quadric.signature() if sgn.is_semi_definite: return (quadric.singular_subspace,) if quadric.rank > 2: raise ValueError("Quadric is not equal to a collection of subspaces.") Q = quadric.normalize() kernel = Q.singular_subspace # The only case remaining is diag(1, -1, 0,...,0) v1, v2 = Q.subspace.points[:2] P1 = Point(v1 + v2) P2 = Point(v1 - v2) return join(kernel, P1), join(kernel, P2)