public bool Contains(Point p)
            {
                Euler   euler = new Euler();
                Point3D spt   = new Point3D();

                euler.phi     = -psi;
                euler.theta   = -theta;
                euler.psi     = -phi;
                euler.psi_a   = Euler.AXIS_Z;
                euler.theta_a = Euler.AXIS_X;
                euler.phi_a   = Euler.AXIS_Z;
                euler.transform(spt, new Point3D(p));
                Point sp = spt.toSpherePoint();

                return(FP.zero(sp.dec) && FP.ge(sp.ra, 0.0) && FP.le(sp.ra, length));
            }
            public Line(Point beg, Point end)
            {
                double l = beg.Distance(end);

                if (FP.eq(l, Math.PI))
                {
                    Debug.Assert(FP.eq(beg.ra, end.ra));
                    phi    = -Math.PI / 2;
                    theta  = Math.PI / 2;
                    psi    = beg.ra < 0.0 ? Math.PI * 2 + beg.ra : beg.ra;
                    length = Math.PI;
                    return;
                }
                if (beg.Equals(end))
                {
                    phi    = Math.PI / 2;
                    theta  = beg.dec;
                    psi    = beg.ra - Math.PI / 2;
                    length = 0.0;
                }
                else
                {
                    Point3D beg3d = new Point3D(beg);
                    Point3D end3d = new Point3D(end);
                    Point3D tp    = new Point3D();
                    Point   spt   = beg3d.cross(end3d).toSpherePoint();
                    Euler   euler = new Euler();
                    euler.phi     = -spt.ra - Math.PI / 2;
                    euler.theta   = spt.dec - Math.PI / 2;
                    euler.psi     = 0.0;
                    euler.psi_a   = Euler.AXIS_Z;
                    euler.theta_a = Euler.AXIS_X;
                    euler.phi_a   = Euler.AXIS_Z;
                    euler.transform(tp, beg3d);
                    spt = tp.toSpherePoint();

                    // invert
                    phi    = spt.ra;
                    theta  = -euler.theta;
                    psi    = -euler.phi;
                    length = l;
                }
            }
         public Line(Point beg, Point end) { 
             double l = beg.Distance(end);
             if (FP.eq(l, Math.PI)) {
                 Debug.Assert(FP.eq(beg.ra, end.ra));
                 phi = -Math.PI/2;
                 theta = Math.PI/2;
                 psi = beg.ra < 0.0 ? Math.PI*2 + beg.ra : beg.ra;
                 length = Math.PI;
                 return;
             }
             if (beg.Equals(end)) { 
                 phi    = Math.PI/2;
                 theta  = beg.dec;
                 psi    = beg.ra - Math.PI/2;
                 length = 0.0;
             } else { 
                 Point3D beg3d = new Point3D(beg);
                 Point3D end3d = new Point3D(end);
                 Point3D tp = new Point3D();
                 Point spt = beg3d.cross(end3d).toSpherePoint();
                 Euler euler = new Euler();
                 euler.phi     = - spt.ra - Math.PI/2;
                 euler.theta   =   spt.dec - Math.PI/2;
                 euler.psi     =   0.0 ;
                 euler.psi_a   = Euler.AXIS_Z;
                 euler.theta_a = Euler.AXIS_X;
                 euler.phi_a   = Euler.AXIS_Z;
                 euler.transform(tp, beg3d);
                 spt = tp.toSpherePoint();
 
                 // invert
                 phi = spt.ra;
                 theta = -euler.theta;
                 psi = -euler.phi;
                 length = l;
             }
         }
 public bool Contains(Point p) { 
     Euler euler = new Euler();
     Point3D spt = new Point3D();
     euler.phi     = -psi;
     euler.theta   = -theta;
     euler.psi     = -phi;
     euler.psi_a   = Euler.AXIS_Z;
     euler.theta_a = Euler.AXIS_X;
     euler.phi_a   = Euler.AXIS_Z;
     euler.transform(spt, new Point3D(p));
     Point sp = spt.toSpherePoint();
     return FP.zero(sp.dec) && FP.ge(sp.ra, 0.0) && FP.le(sp.ra, length);
 }