Source code for ddg.conversion.nets.geometry.quadrics

import ddg.datastructures.nets.net as net
import ddg.datastructures.nets.utils as nutils
import ddg.math.symmetric_matrices as sm
import ddg.datastructures.nets.net_generators.quadrics as qng


[docs]def quadric_to_smooth_net(quadric, affine=False, affine_component=-1): """Convert a quadric to a smooth net. Currently supported are all quadrics contained in lines, planes or 3D subspaces. Parameters ---------- quadric : Quadric affine : bool (default=False) Whether the resulting net should return affine or homogeneous coordinates. affine_component : int (default=-1) Used to determine parametrization and optionally dehomogenize. This is one of the rare cases where this has an effect even if affine=False. Returns ------- SmoothNet, SmoothCurve, EmptyNet, PointNet or NetCollection Resulting smooth net. """ sgn = quadric.signature(affine=True, affine_component=affine_component) Q = quadric.normalize(affine=True, affine_component=affine_component) B = Q.subspace.matrix net_fct = _SGN_DICT[sgn].get('net_fct') net_args = _SGN_DICT[sgn].get('net_args', {}) if net_fct is None: raise KeyError(f"Unknown signature: {repr(sgn)}") s = net_fct(**net_args) # Parametrization in B - coordinates nutils.homogenize(s) # Final parametrization in the ambient space s.transform(B) if affine: nutils.dehomogenize(s, affine_component=affine_component) return s
_SGN_DICT = { ######################### # Conics (?) in 0D space ######################### sm.AffineSignature(2, 0): { # complex quadric 'net_fct': net.EmptyNet, 'net_args': {'coordinates': [0.], 'name': 'ComplexQuadric'} }, sm.AffineSignature(1, 1, affine_component_entry=-1): { # two points 'net_fct': qng.two_points }, sm.AffineSignature(1, 0, 1, affine_component_entry=0): { # double point (?) 'net_fct': net.PointNet, 'net_args': {'value': [0.], 'name': 'DoublePoint'} }, sm.AffineSignature(1, 0, 1, affine_component_entry=1): { # point at infinity 'net_fct': net.EmptyNet, 'net_args': {'coordinates': [0.], 'name': 'PointAtInfinity'} }, sm.AffineSignature(0, 0, 2): { # fully degenerate 'net_fct': net.EmptyNet, 'net_args': {'coordinates': [0.], 'name': 'FullyDegenerateQuadric'} }, sm.AffineSignature(1, 1, affine_component_entry='parabolic'): { # one point (and one at infinity) 'net_fct': net.PointNet, 'net_args': {'value': [0.], 'name': 'OnePoint'} }, ##################### # Conics in 2D space ##################### # non-parabolic cases # non-degenerate sm.AffineSignature(3, 0): { # complex conic 'net_fct': net.EmptyNet, 'net_args': {'coordinates': [0., 0.], 'name': 'ComplexConic'} }, sm.AffineSignature(2, 1, affine_component_entry=-1): { # ellipse 'net_fct': qng.circle }, sm.AffineSignature(2, 1, affine_component_entry=1): { # hyperbola 'net_fct': qng.hyperbola }, # once degenerate sm.AffineSignature(2, 0, 1, affine_component_entry=0): { # single point (two intersecting complex lines) 'net_fct': net.PointNet, 'net_args': {'value': [0., 0.], 'name': 'ConjugateLines'} }, sm.AffineSignature(1, 1, 1, affine_component_entry=-1): { # pair of parallel lines 'net_fct': qng.linepair }, sm.AffineSignature(1, 1, 1, affine_component_entry=0): { # pair of intersecting lines 'net_fct': qng.interline }, sm.AffineSignature(2, 0, 1, affine_component_entry=1): { # empty (complex lines) 'net_fct': net.EmptyNet, 'net_args': {'coordinates': [0., 0.], 'name': 'ConjugateParallelLines'} }, # twice degenerate sm.AffineSignature(1, 0, 2, affine_component_entry=0): { # double line 'net_fct': qng.cline, 'net_args': {'name': 'DoubleLine'} }, sm.AffineSignature(1, 0, 2, affine_component_entry=1): { # empty (double line at infinity) 'net_fct': net.EmptyNet, 'net_args': {'coordinates': [0., 0.], 'name': 'DoubleLineInfty'} }, # fully degenerate sm.AffineSignature(0, 0, 3): { # empty 'net_fct': net.EmptyNet, 'net_args': {'coordinates': [0., 0.], 'name': 'FullyDegenerateConic'} }, # parabolic cases # non-degenerate sm.AffineSignature(2, 1, affine_component_entry='parabolic'): { # parabola 'net_fct': qng.parabola }, # degenerate sm.AffineSignature(1, 1, 1, affine_component_entry='parabolic'): { # one line (and one at infinity) 'net_fct': qng.cline, 'net_args': {'rot': True, 'name': 'OneLine'} }, ####################### # Quadrics in 3D space ####################### # non-parabolic cases # non-degenerate sm.AffineSignature(4, 0): { # complex quadric 'net_fct': net.EmptyNet, 'net_args': {'coordinates': [0., 0., 0.], 'name': 'ComplexQuadric'} }, sm.AffineSignature(3, 1, affine_component_entry=-1): { # sphere 'net_fct': qng.sphere }, sm.AffineSignature(3, 1, affine_component_entry=1): { # two-sheeted hyperboloid 'net_fct': qng.hyperboloid_two_sheeted, 'net_args': {'axis': 2} }, # one-sheeted hyperboloid sm.AffineSignature(2, 2, affine_component_entry=-1): { 'net_fct': qng.hyperboloid_one_sheeted, 'net_args': {'axis': 0} }, # once degenerate sm.AffineSignature(3, 0, 1, affine_component_entry=0): { # one point (complex cone with real vertex) 'net_fct': net.PointNet, 'net_args': {'value': [0., 0., 0.], 'name': 'ComplexCone'} }, sm.AffineSignature(2, 1, 1, affine_component_entry=0): { # cone 'net_fct': qng.cone }, sm.AffineSignature(3, 0, 1, affine_component_entry=1): { # empty (complex cylinder with vertex at infinity) 'net_fct': net.EmptyNet, 'net_args': {'coordinates': [0., 0., 0.], 'name': 'ComplexCylinder'} }, sm.AffineSignature(2, 1, 1, affine_component_entry=1): { # hyperbolic cylinder 'net_fct': qng.cylinder_hyperbolic, 'net_args': {'rot': True} }, sm.AffineSignature(2, 1, 1, affine_component_entry=-1): { # elliptic cylinder 'net_fct': qng.cylinder_elliptic }, # twice degenerate sm.AffineSignature(2, 0, 2, affine_component_entry=0): { # one line (two complex conjugate planes) 'net_fct': qng.line, 'net_args': {'name': 'ConjugatePlanes'} }, sm.AffineSignature(1, 1, 2, affine_component_entry=0): { # two intersecting planes 'net_fct': qng.planes_intersecting, 'net_args': {'name': 'Planes'} }, sm.AffineSignature(2, 0, 2, affine_component_entry=1): { # empty (two complex conjugate planes intersecting at infinity) 'net_fct': net.EmptyNet, 'net_args': { 'coordinates': [0., 0., 0.], 'name': 'ConjugateParallelPlanes' } }, sm.AffineSignature(1, 1, 2, affine_component_entry=1): { # two parallel planes 'net_fct': qng.planes_parallel, 'net_args': {'name': 'ParallelPlanes'} }, # thrice degenerate sm.AffineSignature(1, 0, 3, affine_component_entry=0): { # double plane 'net_fct': qng.plane, 'net_args': {'axis': 0, 'name': 'DoublePlane'} }, sm.AffineSignature(1, 0, 3, affine_component_entry=1): { # empty (double plane at infinity) 'net_fct': net.EmptyNet, 'net_args': {'coordinates': [0., 0., 0.], 'name': 'DoublePlaneInfty'} }, # fully degenerate sm.AffineSignature(0, 0, 4): { 'net_fct': net.EmptyNet, 'net_args': { 'coordinates': [0., 0., 0.], 'name': 'FullyDegenerateQuadric' } }, # parabolic cases # non-degenerate sm.AffineSignature(3, 1, affine_component_entry='parabolic'): { # elliptic paraboloid 'net_fct': qng.paraboloid_elliptic }, sm.AffineSignature(2, 2, affine_component_entry='parabolic'): { # hyperbolic paraboloid 'net_fct': qng.paraboloid_hyperbolic }, # once degenerate sm.AffineSignature(2, 1, 1, affine_component_entry='parabolic'): { # parabolic cylinder 'net_fct': qng.cylinder_parabolic }, # twice degenerate sm.AffineSignature(1, 1, 2, affine_component_entry='parabolic'): { # one plane (second plane at infinity) 'net_fct': qng.plane, 'net_args': {'axis': 2, 'name': 'OnePlane'} } } """ Dictionary mapping signature to parametrization of corresponding quadric in normal form. It has the following structure:: + ... | +--+ AffineSignature -> dict | | | +--+ 'net_fct' -> function that returns net | | | +--+ 'net_args' -> Optional dict of kwargs to be passed to net_fct | + ... It is assumed that affine_component of the signature is -1. """