.. contents:: Geometries ========== Geometric objects can be represented in different ways depending on which geometry is used to express them. For example an oriented euclidean line in the plane can be represented as an oriented subspace of projective dimension 1 in the euclidean geometry, or as a point on the quadric of the Laguerre geometry (Blaschke cylinder). To distinguish between them some of our geometric objects allow you to pass a geometry upon initialization of a new instance. Obtaining defined geometries ---------------------------- Our library already comes with some predefined geometries. Use get_geometry to obtain them with their identifier and your desired dimension: +---------------+----------+------------+-----------+-----------+-----------+------------+ | Name | elliptic | hyperbolic | laguerre | moebius | euclidean | projective | +===============+==========+============+===========+===========+===========+============+ | inner product | yes | yes | yes | yes | no | no | +---------------+----------+------------+-----------+-----------+-----------+------------+ | signature | (n,0,0) | (n-1,1,0) | (n-2,1,1) | (n-1,1,0) | / | / | +---------------+----------+------------+-----------+-----------+-----------+------------+ | dual ip | yes | yes | no | yes | yes | no | +---------------+----------+------------+-----------+-----------+-----------+------------+ | dual sign | (n,0,0) | (n-1,1,0) | / | (n-1,1,0) | (n-1,0,1) | / | +---------------+----------+------------+-----------+-----------+-----------+------------+ .. doctest:: >>> import ddg >>> ddg.geometry.geometries.get_geometry('elliptic 3d') EllipticGeometry(3, is_dual=False) >>> ddg.geometry.geometries.get_geometry('hyperbolic', 3) HyperbolicGeometry(3, is_dual=False) >>> ddg.geometry.geometries.get_geometry('laguerre 2d') LaguerreGeometry(3, is_dual=False) >>> ddg.geometry.geometries.get_geometry('moebius', 3) MoebiusGeometry(3, is_dual=False) >>> euclidean = ddg.geometry.geometries.get_geometry('euclidean', 4) >>> euclidean EuclideanGeometry(4, is_dual=False) >>> euclidean.dualize() EuclideanGeometry(4, is_dual=True) >>> ddg.geometry.geometries.get_geometry('lie', 5) LieGeometry(5, is_dual=False) Creating a new geometry ----------------------- Sometimes none of our predefined geometries will fit our problem. In this case you can easily create your own geometry: .. doctest:: >>> import numpy as np >>> ddg.geometry.geometries.Geometry(dimension = 4) Geometry(name=None, dimension=4) >>> ddg.geometry.geometries.ProjectiveGeometry('example name 1', ... dimension=4, is_dual=True) ProjectiveGeometry(name='dual example name 1', dimension=4, is_dual=True) >>> ddg.geometry.geometries.CayleyKleinGeometry(np.diag([1,0,3,2]), ... 'example name 2') CayleyKleinGeometry( Quadric( array([[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 3, 0], [0, 0, 0, 2]]) ), name='example name 2' ) We have to take care when we choose names for our new geometry as only one geometry can have the same combination of name and dimension. Similar to the predefined geometries you can reobtain your own geometries with ``get_geometry`` as long as you gave it a name. Differences between the geometry classes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * ``Geometry``, the most basic geometry class * ``ProjectiveGeometry``, can be dualized. * ``CayleyKleinGeometry``, inherits from ``ProjectiveGeometry``, but also can have inner product and requires either a quadric, inner product function, or matrix representation of it when initialized Conversion between geometries ----------------------------- We sometimes want to represent an object in a different model. For this we can use our (geometry) convert function, which chooses the appropriate way to convert an object for us. Just give source and target geometries or geometry identifiers: .. doctest:: >>> import ddg.geometry.conversion >>> points = [[1,0,1],[0,1,1]] >>> subspace = ddg.geometry.subspaces.Subspace(*points) >>> subspace Subspace(array([1., 0., 1.]), array([0., 1., 1.])) >>> laguerre_point = ddg.geometry.conversion.convert(subspace, source_geometry='euclidean 2d', target_geometry='laguerre 2d') >>> laguerre_point Point(array([-0.70710678, -0.70710678, 0.70710678, 1. ])) >>> conv_back = ddg.geometry.conversion.convert(laguerre_point, 'laguerre 2d', 'euclidean 2d') >>> conv_back == subspace True Adding new conversion functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ All newly added conversion functions have to be located in the ``geometry.conversion`` module and have to follow a naming convention to allow the ``convert`` function to find it: 1) ``_[source geometry w/o dimension]_to_[target geometry w/o dimension]``, e.g. ``_laguerre_to_euclidean`` 2) ``_[source geometry w/ dimension]_to_[target geometry w/ dimension]``, e.g. ``_laguerre2d_to_euclidean2d`` The function ``convert`` will always try to use the dimension specific conversion functions first.