コード例 #1
0
ファイル: Intersect2d.cs プロジェクト: ventor3000/guppy2
        public static Point2d[] EllipseEllipse(Ellipse2d el1, Ellipse2d el2)
        {
            //reduce this problem to a circle-ellipse problem by
            //rotating ellipse 1 down, scaling it to circle and then
            //rotate ellipse2 down.
            Transform2d tr = Transform2d.Rotate(-el1.Rotation) * Transform2d.Stretch(1.0, 1.0 / el1.Ratio);

            //dont modify originals:
            el1 = new Ellipse2d(el1);
            el2 = new Ellipse2d(el2);
            el1.Transform(tr);
            el2.Transform(tr);

            Point2d[] res = EllipseCircle(el2, new Circle2d(el1.X, el1.Y, el1.MajorRadius));

            if (res == null)
            {
                return(null);
            }

            Transform2d trinv = (tr).Inversed;

            for (int l = 0; l < res.Length; l++)
            {
                res[l] = res[l].GetTransformed(trinv);
            }

            return(res);
        }
コード例 #2
0
ファイル: Parabola2d.cs プロジェクト: ventor3000/guppy2
        public override GeneralConic2d ToGeneralConic()
        {
            Transform2d    tr  = Transform2d.Rotate(rotation) * Transform2d.Translate(vertex.X, vertex.Y);
            GeneralConic2d res = new GeneralConic2d(a, 0, 0, 0, -1, 0); //y=ax^2

            res.Transform(tr);
            return(res); //TODO: optimize this function
        }
コード例 #3
0
        public override GeneralConic2d ToGeneralConic()
        {
            Transform2d    tr    = Transform2d.Scale(MajorRadius) * Transform2d.Rotate(Rotation) * Transform2d.Translate(center.X, center.Y);
            GeneralConic2d elcon = new GeneralConic2d(1, 0, 1.0 / (sigratio * sigratio), 0, 0, -1); //x^2+(1/b)^2-1=0 => unit ellipse

            elcon.Transform(tr);                                                                    //transform conic to position of ellipse
            return(elcon);                                                                          //TODO: optimize this function
        }
コード例 #4
0
ファイル: Parabola2d.cs プロジェクト: ventor3000/guppy2
        public override Point2d PointAt(double t)
        {
            double  f   = FocalDistance;
            Point2d res = new Point2d(t, a * t * t);

            //TODO: need to be optimized!!
            return(res.GetTransformed(Transform2d.Rotate(rotation) * Transform2d.Translate(vertex.X, vertex.Y)));
        }
コード例 #5
0
ファイル: Hyperbola2d.cs プロジェクト: ventor3000/guppy2
        public override GeneralConic2d ToGeneralConic()
        {
            //TODO: test this function

            Transform2d    tr     = Transform2d.Scale(majoraxis.Length) * Transform2d.Rotate(Rotation) * Transform2d.Translate(center.X, center.Y);
            GeneralConic2d hypcon = new GeneralConic2d(1, 0, -1.0 / (ratio * ratio), 0, 0, -1); //x^2-(y/b)^2-1=0 => unit

            hypcon.Transform(tr);

            return(hypcon); //TODO: optimize this function
        }
コード例 #6
0
ファイル: Parabola2d.cs プロジェクト: ventor3000/guppy2
        public override Vector2d Tangent(Point2d where)
        {
            Transform2d tr = Transform2d.Rotate(-rotation); // ToStandardPosition;

            where = where.GetTransformed(tr);
            Point2d stdvertex = vertex.GetTransformed(tr);

            double slope = 2 * a * (where.X - stdvertex.X); ///(4*FocalDistance); //from diffrentiation

            //TODO: reverse vector if wrong direction
            return(Vector2d.FromSlope(slope).GetTransformed(tr.Inversed));
        }
コード例 #7
0
ファイル: Intersect2d.cs プロジェクト: ventor3000/guppy2
        /// <summary>
        /// Intersects a line with a conic that is in standard position, that is, not rotated and
        /// centered at 0,0
        /// </summary>
        /// <param name="con"></param>
        /// <param name="lin"></param>
        /// <returns>A list of parameters on line that is intersection points, or null if no intersections</returns>
        private static double[] ConicLineParametric(GeneralConic2d con, Line2d lin)
        {
            //We construct a matrix so that: conic is unrotated (B term=0) and line starts at origo and has length=1.0
            //This is to improve stabillity of the equation

            double invlen = 1.0 / lin.Length;

            if (double.IsInfinity(invlen))
            {
                return(null);    //zero length line does not intersect
            }
            Transform2d tr = Transform2d.Translate(-lin.X1, -lin.Y1) * Transform2d.Rotate(-con.Rotation) * Transform2d.Scale(invlen);

            GeneralConic2d c = new GeneralConic2d(con);  //copy for modification
            double         x1 = lin.X2, y1 = lin.Y2;

            c.Transform(tr);
            tr.Apply(x1, y1, out x1, out y1, true); //transformed line end


            double t2 = y1 * y1 * c.C + x1 * x1 * c.A;
            double t1 = y1 * c.E + x1 * c.D;
            double t0 = c.F;

            double[] ts = RealPolynomial.SolveQuadric(t2, t1, t0);

            return(ts);

            /*double dx=lin.DX;
             * double dy=lin.DY;
             * double x0=lin.X1;
             * double y0=lin.Y1;
             *
             * double t2=con.C*dy*dy+con.A*dx*dx;
             * double t1=2*con.C*dy*y0+2*con.A*dx*x0+dy*con.E+con.D*dx;
             * double t0=con.C*y0*y0+con.E*y0+con.A*x0*x0+con.D*x0+con.F;
             *
             * return RealPolynomial.SolveQuadric(t2, t1, t0, 1e-9);*/
        }
コード例 #8
0
        public static Circle2d[] LinePointPoint(Line2d li, Point2d pt1, Point2d pt2)
        {
            // max two solutions
            // solution created by Robert.P. 2013-02-07

            List <Circle2d> res = null;

            // transform problem so that we have a vertical line thru origo which simplifies stuff a lot
            Transform2d toorg = Transform2d.Translate(-li.X1, -li.Y1) * Transform2d.Rotate(-li.Angle + MathUtil.Deg90);
            Transform2d fromorg = toorg.Inversed;
            double      i, j, k, l;

            toorg.Apply(pt1.X, pt1.Y, out i, out j, true);
            toorg.Apply(pt2.X, pt2.Y, out k, out l, true);


            double y2 = 2 * k - 2 * i;
            double y1 = 4 * i * l - 4 * j * k;
            double y0 = -2 * i * l * l - 2 * i * k * k + (2 * j * j + 2 * i * i) * k;

            double[] ys = RealPolynomial.SolveQuadric(y2, y1, y0);
            if (ys == null)
            {
                return(null); //no solutions
            }
            foreach (double y in ys)
            {
                double xx = (y * y - 2 * j * y + j * j + i * i) / (2 * i), yy = y; //TODO: what if vertical line
                double rad = Math.Abs(xx);

                fromorg.Apply(xx, yy, out xx, out yy, true);
                AddResult(ref res, xx, yy, rad);
            }


            return(MakeResult(res));
        }
コード例 #9
0
        public static Circle2d[] CircleCircleCircle(Circle2d ci1, Circle2d ci2, Circle2d ci3)
        {
            // see http://www.arcenciel.co.uk/geometry/ for explanation

            List <Circle2d> result = null;
            double          r1, r2, r3, a, b, c, t, A, B, C;
            double          fRadius, xc, yc, distc1c2;

            double[] roots;

            // if all circles concentric, there are no solutions
            distc1c2 = ci1.Center.Distance(ci2.Center);
            if (MathUtil.IsZero(distc1c2) && MathUtil.IsZero(ci2.Center.Distance(ci3.Center)))
            {
                return(null);
            }

            // make sure first 2 circles are not concentric
            // if so swap ci2,ci3
            if (MathUtil.IsZero(distc1c2))
            {
                var tmp = ci2; ci2 = ci3; ci3 = ci2;
            }


            // transform input so that ci1 is at origo and ci2 is on xaxis
            Transform2d trans = Transform2d.Translate(Point2d.Origo - ci1.Center) * Transform2d.Rotate(-ci1.Center.Angle(ci2.Center));

            ci1 = new Circle2d(ci1);
            ci1.Transform(trans);
            ci2 = new Circle2d(ci2);
            ci2.Transform(trans);
            ci3 = new Circle2d(ci3);
            ci3.Transform(trans);



            // Negate the radii to get all combinations

            for (int iCase = 0; iCase < 8; ++iCase)
            {
                r1 = ((iCase & 1) == 0) ? ci1.Radius : -ci1.Radius;
                r2 = ((iCase & 2) == 0) ? ci2.Radius : -ci2.Radius;
                r3 = ((iCase & 4) == 0) ? ci3.Radius : -ci3.Radius;

                // special case where radii of first 2 circles are equal
                if (MathUtil.Equals(r1, r2))
                {
                    // Calculate x-cordinate of centre
                    xc = ci2.X / 2.0;

                    // if all radii are equal, there will be only one solution
                    if (MathUtil.Equals(r1, r3))
                    {
                        if (MathUtil.IsZero(ci3.Y))
                        {
                            continue;
                        }

                        // get y-coordinate of centre
                        yc = (ci3.X * ci3.X - 2.0 * xc * ci3.X + ci3.Y * ci3.Y) / (ci3.Y + ci3.Y);

                        // compute radius
                        A     = 1;
                        B     = 2 * r1;
                        C     = r1 * r1 - xc * xc - yc * yc;
                        roots = RealPolynomial.SolveQuadric(A, B, C);

                        if (roots.Length > 0)
                        {
                            fRadius = roots[0];
                            if (fRadius <= 0.0)
                            { //then try other root
                                if (roots.Length > 1)
                                {
                                    fRadius = roots[1];
                                    if (fRadius <= 0.0)
                                    {
                                        continue; //no posetive roots
                                    }
                                }
                            }
                            AddResult(ref result, xc, yc, fRadius);
                        }
                    }
                    else
                    {
                        // compute constants
                        double k = r1 * r1 - r3 * r3 + ci3.X * ci3.X + ci3.Y * ci3.Y - 2 * xc * ci3.X;
                        A = 4 * ((r1 - r3) * (r1 - r3) - ci3.Y * ci3.Y);
                        B = 4 * (k * (r1 - r3) - 2 * ci3.Y * ci3.Y * r1);
                        C = 4 * xc * xc * ci3.Y * ci3.Y + k * k - 4 * ci3.Y * ci3.Y * r1 * r1;

                        if (!MathUtil.IsZero(A))
                        {
                            roots = RealPolynomial.SolveQuadric(A, B, C);

                            foreach (double radius in roots)
                            {
                                yc = (2 * radius * (r1 - r3) + k) / (2 * ci3.Y);
                                AddResult(ref result, xc, yc, radius);
                            }
                        }
                    }
                    continue;
                } //end special case of r1==r2



                // Get constants
                a = 2 * (ci2.X * (r3 - r1) - ci3.X * (r2 - r1));
                b = 2 * ci3.Y * (r1 - r2);
                c = (r2 - r1) * (ci3.X * ci3.X + ci3.Y * ci3.Y - (r3 - r1) * (r3 - r1)) - (r3 - r1) * (ci2.X * ci2.X - (r2 - r1) * (r2 - r1));
                t = (ci2.X * ci2.X + r1 * r1 - r2 * r2) / 2.0;
                A = (r1 - r2) * (r1 - r2) * (a * a + b * b) - (ci2.X * ci2.X * b * b);
                B = 2 * (t * (r1 - r2) * (a * a + b * b) + a * c * ci2.X * (r1 - r2) - (r1 * ci2.X * ci2.X * b * b));
                C = t * t * (a * a + b * b) + (2 * a * c * ci2.X * t) + (c * c * ci2.X * ci2.X) - (r1 * r1 * ci2.X * ci2.X * b * b);

                // Calculate radius
                roots = RealPolynomial.SolveQuadric(A, B, C);
                if (roots == null)
                {
                    continue;
                }

                foreach (double radius in roots)
                {
                    if (radius < minradius || radius > maxradius)
                    {
                        continue;
                    }
                    // get x coordinate of centre (x2 may not be zero)
                    xc = (radius * (r1 - r2) + t) / ci2.X;

                    // get y coordinate of centre. b should never be 0, as
                    // r1=r2 is special case and y3 may not be zero
                    yc = (-a * xc - c) / b;
                    AddResult(ref result, xc, yc, radius);
                }
            }

            //convert back to original coordinate system by using the inverse
            //of the original matrix
            if (result != null)
            {
                trans = trans.Inversed;
                for (int l = 0; l < result.Count; l++)
                {
                    result[l].Transform(trans);
                }
                return(result.ToArray());
            }

            return(null);
        }
コード例 #10
0
        public static Circle2d[] CircleCircleLine(Circle2d ci1, Circle2d ci2, Line2d li)
        {
            // see http://www.arcenciel.co.uk/geometry/ for explanation

            List <Circle2d> result = null;
            double          a1, b1, c1, t, r2, r3, a, b, c, u, s;
            double          A, B, C, xc, yc;

            //transform input so that c1 is at origo and c2 is on xaxis
            Transform2d trans = Transform2d.Translate(Point2d.Origo - ci1.Center) * Transform2d.Rotate(-ci1.Center.Angle(ci2.Center));

            ci1 = new Circle2d(ci1);
            ci1.Transform(trans);
            ci2 = new Circle2d(ci2);
            ci2.Transform(trans);
            li = new Line2d(li);
            li.Transform(trans);


            if (!li.ToEquation(out a1, out b1, out c1))
            {
                return(null); //degenerate line
            }
            for (int signcase = 0; signcase < 8; ++signcase)
            {
                t = ((signcase & 1) == 0) ? 1 : -1;

                r2 = ((signcase & 2) == 0) ? ci1.Radius : -ci1.Radius;

                r3 = ((signcase & 4) == 0) ? ci2.Radius : -ci2.Radius;



                // Get constants
                a = 2 * (a1 * (r2 - r3) - ci2.X * t);
                b = 2 * b1 * (r2 - r3);
                c = 2 * c1 * (r2 - r3) + t * (r2 * r2 - r3 * r3 + ci2.X * ci2.X);

                if (!MathUtil.IsZero(b))
                {
                    u = b1 * c - b * c1;
                    s = a1 * b - a * b1;
                    A = t * t * b * b * (a * a + b * b) - b * b * s * s;
                    B = 2 * (u * t * b * (a * a + b * b) + a * c * s * t * b - b * b * s * s * r2);
                    C = u * u * (a * a + b * b) + 2 * a * c * s * u + c * c * s * s - b * b * s * s * r2 * r2;
                }
                else
                {
                    u = a1 * c - a * c1;
                    s = a * b1;
                    A = a * a * (t * t * a * a - s * s);
                    B = 2 * a * a * (u * t * a - s * s * r2);
                    C = u * u * a * a + c * c * s * s - a * a * s * s * r2 * r2;
                }



                // Calculate radius
                double[] roots = RealPolynomial.SolveQuadric(A, B, C);
                if (roots != null)
                {
                    foreach (double radius in roots)
                    {
                        if (radius < minradius || radius > maxradius)
                        {
                            continue;
                        }

                        // compute x coordinates of centers
                        List <double> xsols = new List <double>();

                        if (!MathUtil.IsZero(ci2.X)) //circles are not concentric
                        {
                            xc = ((r2 + radius) * (r2 + radius) - (r3 + radius) * (r3 + radius) + ci2.X * ci2.X) / (2 * ci2.X);
                            xsols.Add(xc);
                        }
                        else // If circles are concentric there can be 2 solutions for x
                        {
                            A = (a1 * a1 + b1 * b1);
                            B = -2 * a1 * (radius * t - c1);
                            C = (radius * t - c1) * (radius * t - c1) - b1 * b1 * (r2 + radius) * (r2 + radius);

                            double[] roots2 = RealPolynomial.SolveQuadric(A, B, C);
                            if (roots2 != null)
                            {
                                foreach (double x in roots2)
                                {
                                    xsols.Add(x);
                                }
                            }
                        }



                        // now compute y coordinates from the calculated x:es
                        // and input the final solution
                        foreach (double x in xsols)
                        {
                            if (!MathUtil.IsZero(b1))
                            {
                                yc = (-a1 * x - c1 + radius * t) / b1;
                            }
                            else
                            {
                                double ycSquare = (r2 + radius) * (r2 + radius) - (x * x);
                                if (ycSquare < 0.0)
                                {
                                    continue;
                                }
                                yc = Math.Sqrt(ycSquare);
                            }

                            AddResult(ref result, x, yc, radius);
                            if (MathUtil.IsZero(b1))
                            {
                                AddResult(ref result, x, -yc, radius);
                            }
                        }
                    }
                }
            }


            //convert back to original coordinate system by using the inverse
            //of the original matrix
            if (result != null)
            {
                trans = trans.Inversed;
                for (int l = 0; l < result.Count; l++)
                {
                    result[l].Transform(trans);
                }
                return(result.ToArray());
            }

            return(null);
        }
コード例 #11
0
ファイル: GeneralConic2d.cs プロジェクト: ventor3000/guppy2
        /// <summary>
        /// Gets the line geometries, one or two lines. The type of the conic has to be
        /// Intersecting lines (2 results), Paralell lines (2 results) or Coincident lienes (1 result),
        /// otherwise the result is null.
        /// </summary>
        /// <returns></returns>
        public Line2d[] ToLines()
        {
            // Inspired by line extraction conmat.c from book Graphics Gems V

            double         xx, yy;
            ConicType      type = Type;
            Line2d         tmplin;
            Transform2d    tr;
            GeneralConic2d cpy;


            List <Line2d> res = null;



            double de = B * B * 0.25 - A * C;

            if (MathUtil.IsZero(A) && MathUtil.IsZero(B) && MathUtil.IsZero(C))
            { //single line
                // compute endpoints of the line, avoiding division by zero
                res = new List <Line2d>();
                if (Math.Abs(d) > Math.Abs(e))
                {
                    res.Add(new Line2d(-f / (d), 0.0, -(e + f) / (d), 1.0));
                }
                else
                {
                    res.Add(new Line2d(0.0, -f / (e), 1.0, -(d + f) / (e)));
                }
            }
            else
            {                                                                                              // two lines
                cpy = new GeneralConic2d(this);
                double a = cpy.a, b = cpy.b * 0.5, c = cpy.c, d = cpy.d * 0.5, e = cpy.e * 0.5, f = cpy.f; //get matrix coefficient

                // use the expression for phi that takes atan of the smallest argument
                double phi = (Math.Abs(b + b) < Math.Abs(a - c) ?
                              Math.Atan((b + b) / (a - c)) :
                              MathUtil.Deg360 - Math.Atan((a - c) / (b + b))) / 2.0;

                //phi = cpy.Rotation;

                if (MathUtil.IsZero(de))
                { //parallel lines
                    tr = Transform2d.Rotate(-phi);
                    cpy.Transform(tr);
                    a = cpy.A; b = cpy.B * 0.5; c = cpy.c; d = cpy.d * 0.5; e = cpy.e * 0.5; f = cpy.f; //get matrix coefficient

                    if (Math.Abs(c) < Math.Abs(a))                                                      // vertical
                    {
                        double[] xs = RealPolynomial.SolveQuadric(a, d, f);
                        if (xs != null)
                        {
                            res = new List <Line2d>();
                            foreach (double x in xs)
                            {
                                tmplin = new Line2d(x, -1, x, 1);
                                tmplin.Transform(tr.Inversed);  //back to original spacxe
                                res.Add(tmplin);
                            }
                        }
                    }
                    else //horizontal
                    {
                        double[] ys = RealPolynomial.SolveQuadric(c, e, f, 0.0);
                        if (ys != null)
                        {
                            res = new List <Line2d>();
                            foreach (double y in ys)
                            {
                                tmplin = new Line2d(-1, y, 1, y);
                                tmplin.Transform(tr.Inversed);
                                res.Add(tmplin);
                            }
                        }
                    }
                } //end parallel lines case
                else
                { //crossing lines
                    Point2d center = Center;
                    double  rot    = this.Rotation;
                    tr = Transform2d.Translate(-center.X, -center.Y) * Transform2d.Rotate(-rot);
                    cpy.Transform(tr);
                    a = cpy.A; b = cpy.B * 0.5; c = cpy.c; d = cpy.c * 0.5; e = cpy.e * 0.5; f = cpy.f;

                    res = new List <Line2d>();

                    xx     = Math.Sqrt(Math.Abs(1.0 / a));
                    yy     = Math.Sqrt(Math.Abs(1.0 / c));
                    tr     = tr.Inversed;
                    tmplin = new Line2d(-xx, -yy, xx, yy);
                    tmplin.Transform(tr);
                    res.Add(tmplin);
                    tmplin = new Line2d(new Line2d(-xx, yy, xx, -yy));
                    tmplin.Transform(tr);
                    res.Add(tmplin);
                } //end crossing lines case
            }   //end two lines



            if (res == null || res.Count == 0)
            {
                return(null);
            }

            return(res.ToArray());
        }
コード例 #12
0
ファイル: GeneralConic2d.cs プロジェクト: ventor3000/guppy2
        public Conic2d Reduce()
        {
            //double a = A, b = B, c = C, d = D, e = E, f = F;

            double na, nb, nc, nd, ne, nf;  //coefficients in virtual coordinate system
            double tilt = 0.0;

            if (B != 0.0)
            { //rotated, adjust factors to work in virtual coordinate system
                tilt = Rotation;

                double cs   = Math.Cos(-tilt);
                double si   = Math.Sin(-tilt);
                double cs2  = cs * cs;
                double cssi = cs * si;

                //create coefficients of unrotated conic (in virtual coordinate system)
                na = -b * cssi + (a - c) * cs2 + c;
                nb = -(2 * c - 2 * a) * cssi + 2 * b * cs2 - b;
                nc = b * cssi + (c - a) * cs2 + a;
                nd = d * cs - e * si;
                ne = d * si + e * cs;
                nf = f;

                if (!MathUtil.IsZero(nb))
                {
                    return(null);    //conic is still rotated => irreducable, this should not happen in normal cases
                }
            }
            else //conic is not rotated
            {
                na = a;
                nb = b;
                nc = c;
                nd = d;
                ne = e;
                nf = f;
            }


            double ztol = 1e-9;

            if (MathUtil.IsZero(na, ztol) && MathUtil.IsZero(nc, ztol))
            {
                //lines => not supported for now. TODO: fix this!
                return(null);
            }
            else if (MathUtil.IsZero(na, ztol))
            {
                //horizontal parabola.

                if (MathUtil.IsZero(nd, ztol))
                {
                    return(null);    //TODO: return degenerate conic lines
                }
                // compute reduced coefficients
                double c2 = -nc / nd;
                double e2 = -ne / nd;
                double f2 = -nf / nd;

                // vertex of the parabola
                Point2d vertex = new Point2d(
                    -(e2 * e2 - 4 * c2 * f2) / (4 * c2),
                    -e2 * .5 / c2).GetTransformed(Transform2d.Rotate(tilt));

                // create and return result
                double focdist = 1.0 / (4.0 * c2);
                if (focdist < 0.0)
                { //try to keep posetive focal distance by altering rotation
                    focdist = -focdist;
                    tilt   -= MathUtil.Deg180;
                }
                return(new Parabola2d(vertex, MathUtil.NormalizeAngle(tilt - MathUtil.Deg90), focdist));
            }
            else if (MathUtil.IsZero(nc, ztol))
            {
                // vertical parabola
                if (MathUtil.IsZero(ne, ztol))
                {
                    return(null);    //TODO: return degenerate conic lines
                }
                // compute reduced coefficients:
                double a2 = -na / ne;
                double d2 = -nd / ne;
                double f2 = -nf / ne;

                // vertex of parabola
                Point2d vertex = new Point2d(                                                      //vertex in unrotated sysem of conic...
                    -d2 * 0.5 / a2,
                    -(d2 * d2 - 4 * a2 * f2) / (4 * a2)).GetTransformed(Transform2d.Rotate(tilt)); //...rotated to conic system

                // create and return result
                double focdist = 1.0 / (4.0 * a2);
                if (focdist < 0.0)
                { //try to keep posetive focal distance
                    focdist = -focdist;
                    tilt   -= MathUtil.Deg180;
                }

                return(new Parabola2d(vertex, MathUtil.NormalizeAngle(tilt), focdist));
            }
            else
            {
                //ellipse or hyperbola

                // get length of major and minor axis
                double num     = (nc * nd * nd + na * ne * ne - 4 * na * nc * nf) / (4 * na * nc);
                double sqmajax = num / na;   //axes, squared length with sign
                double sqminax = num / nc;

                if (MathUtil.IsZero(sqmajax, ztol) || MathUtil.IsZero(sqminax, ztol))
                {
                    return(null);    //dont allow zero axes
                }
                if (sqmajax <= 0.0 && sqminax <= 0.0)
                {
                    return(null);    //both axes cannot be negative
                }
                if (sqmajax > 0.0 && sqminax > 0.0)
                {
                    //ellipse => constructor fixes bt>at by rotating ellipse
                    return(new Ellipse2d(Center, Math.Sqrt(sqmajax), Math.Sqrt(sqminax), tilt));
                }
                else
                {
                    if (sqmajax > 0.0) //vertical line of symetry => as we define hyperbola
                    {
                        return(new Hyperbola2d(Center, Math.Sqrt(Math.Abs(sqmajax)), Math.Sqrt(Math.Abs(sqminax)), tilt));
                    }
                    else //horizontal line of symetry => we have to rotate to fit our hyperbola definition
                    {
                        return(new Hyperbola2d(Center, Math.Sqrt(Math.Abs(sqminax)), Math.Sqrt(Math.Abs(sqmajax)), tilt + MathUtil.Deg90));
                    }
                }
            }
        }