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

import ddg
import ddg.conversion.nets.geometry._quadrics_parametrizations as qng
import ddg.geometry.signatures as sg
import ddg.nets as net
from ddg.nets import compose


[docs]def quadric_to_smooth_net(quadric, affine=True): """Convert a quadric to a smooth net. Currently supported are all quadrics contained in lines, planes or 3D subspaces. Parameters ---------- quadric : ddg.geometry.Quadric affine : bool (default=True) Whether the resulting net should return affine or homogeneous coordinates. Returns ------- SmoothNet, SmoothCurve, EmptyNet, PointNet or NetCollection Resulting smooth net. """ sgn = quadric.signature(affine=True) Q = quadric.normalize(affine=True) 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 s = ddg.nets.homogenize(s) # Final parametrization in the ambient space s = compose(B, s) if affine: s = ddg.nets.dehomogenize(s) return s
_SGN_DICT = { ######################### # Conics (?) in 0D space ######################### sg.AffineSignature(1, 0): { "net_fct": net.EmptyNet, "net_args": {"coordinates": [], "name": "EmptyQuadric"}, }, sg.AffineSignature(0, 0, 1): { "net_fct": net.PointNet, "net_args": {"value": [], "name": "OnePoint"}, }, ######################### # Conics (?) in 1D space ######################### sg.AffineSignature(2, 0): { # complex quadric "net_fct": net.EmptyNet, "net_args": {"coordinates": [0.0], "name": "ComplexQuadric"}, }, sg.AffineSignature(1, 1, last_entry=-1): { # two points "net_fct": qng.two_points }, sg.AffineSignature(1, 0, 1, last_entry=0): { # double point (?) "net_fct": net.PointNet, "net_args": {"value": [0.0], "name": "DoublePoint"}, }, sg.AffineSignature(1, 0, 1, last_entry=1): { # point at infinity "net_fct": net.EmptyNet, "net_args": {"coordinates": [0.0], "name": "PointAtInfinity"}, }, sg.AffineSignature(0, 0, 2): { # fully degenerate "net_fct": net.EmptyNet, "net_args": {"coordinates": [0.0], "name": "FullyDegenerateQuadric"}, }, sg.AffineSignature(1, 1, last_entry="parabolic"): { # one point (and one at infinity) "net_fct": net.PointNet, "net_args": {"value": [0.0], "name": "OnePoint"}, }, ##################### # Conics in 2D space ##################### # non-parabolic cases # non-degenerate sg.AffineSignature(3, 0): { # complex conic "net_fct": net.EmptyNet, "net_args": {"coordinates": [0.0, 0.0], "name": "ComplexConic"}, }, sg.AffineSignature(2, 1, last_entry=-1): { # ellipse "net_fct": qng.circle }, sg.AffineSignature(2, 1, last_entry=1): { # hyperbola "net_fct": qng.hyperbola }, # once degenerate sg.AffineSignature(2, 0, 1, last_entry=0): { # single point (two intersecting complex lines) "net_fct": net.PointNet, "net_args": {"value": [0.0, 0.0], "name": "ConjugateLines"}, }, sg.AffineSignature(1, 1, 1, last_entry=-1): { # pair of parallel lines "net_fct": qng.linepair }, sg.AffineSignature(1, 1, 1, last_entry=0): { # pair of intersecting lines "net_fct": qng.interline }, sg.AffineSignature(2, 0, 1, last_entry=1): { # empty (complex lines) "net_fct": net.EmptyNet, "net_args": {"coordinates": [0.0, 0.0], "name": "ConjugateParallelLines"}, }, # twice degenerate sg.AffineSignature(1, 0, 2, last_entry=0): { # double line "net_fct": qng.cline, "net_args": {"name": "DoubleLine"}, }, sg.AffineSignature(1, 0, 2, last_entry=1): { # empty (double line at infinity) "net_fct": net.EmptyNet, "net_args": {"coordinates": [0.0, 0.0], "name": "DoubleLineInfty"}, }, # fully degenerate sg.AffineSignature(0, 0, 3): { # empty "net_fct": net.EmptyNet, "net_args": {"coordinates": [0.0, 0.0], "name": "FullyDegenerateConic"}, }, # parabolic cases # non-degenerate sg.AffineSignature(2, 1, last_entry="parabolic"): { # parabola "net_fct": qng.parabola }, # degenerate sg.AffineSignature(1, 1, 1, last_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 sg.AffineSignature(4, 0): { # complex quadric "net_fct": net.EmptyNet, "net_args": {"coordinates": [0.0, 0.0, 0.0], "name": "ComplexQuadric"}, }, sg.AffineSignature(3, 1, last_entry=-1): { # sphere "net_fct": qng.sphere }, sg.AffineSignature(3, 1, last_entry=1): { # two-sheeted hyperboloid "net_fct": qng.hyperboloid_two_sheeted, "net_args": {"axis": 2}, }, # one-sheeted hyperboloid sg.AffineSignature(2, 2, last_entry=-1): { "net_fct": qng.hyperboloid_one_sheeted, "net_args": {"axis": 0}, }, # once degenerate sg.AffineSignature(3, 0, 1, last_entry=0): { # one point (complex cone with real vertex) "net_fct": net.PointNet, "net_args": {"value": [0.0, 0.0, 0.0], "name": "ComplexCone"}, }, sg.AffineSignature(2, 1, 1, last_entry=0): { # cone "net_fct": qng.cone }, sg.AffineSignature(3, 0, 1, last_entry=1): { # empty (complex cylinder with vertex at infinity) "net_fct": net.EmptyNet, "net_args": {"coordinates": [0.0, 0.0, 0.0], "name": "ComplexCylinder"}, }, sg.AffineSignature(2, 1, 1, last_entry=1): { # hyperbolic cylinder "net_fct": qng.cylinder_hyperbolic, "net_args": {"rot": True}, }, sg.AffineSignature(2, 1, 1, last_entry=-1): { # elliptic cylinder "net_fct": qng.cylinder_elliptic }, # twice degenerate sg.AffineSignature(2, 0, 2, last_entry=0): { # one line (two complex conjugate planes) "net_fct": qng.line, "net_args": {"name": "ConjugatePlanes"}, }, sg.AffineSignature(1, 1, 2, last_entry=0): { # two intersecting planes "net_fct": qng.planes_intersecting, "net_args": {"name": "Planes"}, }, sg.AffineSignature(2, 0, 2, last_entry=1): { # empty (two complex conjugate planes intersecting at infinity) "net_fct": net.EmptyNet, "net_args": {"coordinates": [0.0, 0.0, 0.0], "name": "ConjugateParallelPlanes"}, }, sg.AffineSignature(1, 1, 2, last_entry=1): { # two parallel planes "net_fct": qng.planes_parallel, "net_args": {"name": "ParallelPlanes"}, }, # thrice degenerate sg.AffineSignature(1, 0, 3, last_entry=0): { # double plane "net_fct": qng.plane, "net_args": {"axis": 0, "name": "DoublePlane"}, }, sg.AffineSignature(1, 0, 3, last_entry=1): { # empty (double plane at infinity) "net_fct": net.EmptyNet, "net_args": {"coordinates": [0.0, 0.0, 0.0], "name": "DoublePlaneInfty"}, }, # fully degenerate sg.AffineSignature(0, 0, 4): { "net_fct": net.EmptyNet, "net_args": {"coordinates": [0.0, 0.0, 0.0], "name": "FullyDegenerateQuadric"}, }, # parabolic cases # non-degenerate sg.AffineSignature(3, 1, last_entry="parabolic"): { # elliptic paraboloid "net_fct": qng.paraboloid_elliptic }, sg.AffineSignature(2, 2, last_entry="parabolic"): { # hyperbolic paraboloid "net_fct": qng.paraboloid_hyperbolic }, # once degenerate sg.AffineSignature(2, 1, 1, last_entry="parabolic"): { # parabolic cylinder "net_fct": qng.cylinder_parabolic }, # twice degenerate sg.AffineSignature(1, 1, 2, last_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 | + ... """