Exemple #1
0
        /*private static Point2d[] ConicStandardPosLine(GeneralConic2d con, Line2d lin)
         * {
         *  return LineParamsToPoints(ConicStandardPosLineParametric(con, lin), lin, double.NegativeInfinity, double.PositiveInfinity);
         * }*/

        public static Point2d[] ConicLine(GeneralConic2d con, Line2d lin)
        {
            return(LineParamsToPoints(ConicLineParametric(con, lin), lin, double.NegativeInfinity, double.PositiveInfinity));


            /*
             * Transform2d tr = con.ToStandardPosition;
             *
             * GeneralConic2d stdcon=new GeneralConic2d(con);
             * Line2d stdlin=new Line2d(lin);
             * stdcon.Transform(tr);
             * stdlin.Transform(tr);
             *
             * double[] ts=ConicStandardPosLineParametric(stdcon,stdlin);
             *
             * return LineParamsToPoints(ts, lin, double.NegativeInfinity, double.PositiveInfinity);*/
        }
Exemple #2
0
        static public bool LineLineParametric(Line2d l1, Line2d l2, out double line1_param, out double line2_param)
        {
            double denom = l1.X1 * (l2.Y2 - l2.Y1) + l1.X2 * (l2.Y1 - l2.Y2) + l2.X2 * (l1.Y2 - l1.Y1) + l2.X1 * (l1.Y1 - l1.Y2);

            if (Math.Abs(denom) > 0.0)
            { //not parallel
                //s is intersection parameter on l1
                double s = (l1.X1 * (l2.Y2 - l2.Y1) + l2.X1 * (l1.Y1 - l2.Y2) + l2.X2 * (l2.Y1 - l1.Y1)) / denom;
                //t is intersection parameter on l2
                double t = -(l1.X1 * (l2.Y1 - l1.Y2) + l1.X2 * (l1.Y1 - l2.Y1) + l2.X1 * (l1.Y2 - l1.Y1)) / denom;
                line1_param = s;
                line2_param = t;
                return(true);
            }
            line1_param = 0.0;
            line2_param = 0.0;
            return(false);
        }
Exemple #3
0
        public static Circle2d[] CirclePointPoint(Circle2d ci, Point2d pt1, Point2d pt2)
        {
            // Solution by Robert.P. 2013-02-10
            // solved by intersecting the line which has equal distance to pt1 and pt2 at every point,
            // with the hyperbola that has equal distance to ci and pt1 at every point.


            List <Circle2d> res = null;

            //get squared constants of hyperbola
            double c2 = ci.Center.SquaredDistance(pt1) / 4.0; //center->focus distance squared

            double a = 0.5 * ci.Radius;
            double b = Math.Sqrt(c2 - a * a);

            if (double.IsNaN(b))
            {
                return(null);    //negative square root, no such hyperbola
            }
            // this hyperbola has equal distance to ci and pt1 at every point.
            // it also has focus at ci.Center and pt1
            Hyperbola2d hyper = new Hyperbola2d(new Point2d((ci.X + pt1.X) * 0.5, (ci.Y + pt1.Y) * 0.5), a, b, ci.Center.Angle(pt1));

            //get constants of line dx+ey+f=0, which is equal distance from p1,p2 on every point
            double dx = pt2.X - pt1.X, dy = pt2.Y - pt1.Y;
            double mx   = pt1.X + dx * 0.5;
            double my   = pt1.Y + dy * 0.5;
            Line2d perp = new Line2d(mx, my, mx - dy, my + dx);    //starts from mipoint pt1-pt2 and is perpendicular to that line

            var intpts = Intersect2d.HyperbolaLine(hyper, perp);

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

            foreach (Point2d intpt in intpts)
            {
                AddResult(ref res, intpt.X, intpt.Y, intpt.Distance(pt1));
            }

            return(MakeResult(res));
        }
Exemple #4
0
        public static double[] ParabolaLineParamteric(Parabola2d pab, Line2d lin) //tested ok
        {
            double x1, y1, x2, y2;                                                //line points in parabola standard position

            Transform2d tr = pab.ToStandardPosition;                              //intersect line with y=x^2 => easier

            tr.Apply(lin.X1, lin.Y1, out x1, out y1, true);
            tr.Apply(lin.X2, lin.Y2, out x2, out y2, true);

            double dx = x2 - x1;
            double dy = y2 - y1;
            double c2 = -dx * dx;
            double c1 = dy - 2 * dx * x1;
            double c0 = y1 - x1 * x1;

            //y1-x1^2+t*(dy-2*dx*x1)-dx^2*t^2=0

            double[] ts = RealPolynomial.SolveQuadric(c2, c1, c0);

            return(ts);
        }
Exemple #5
0
        /// <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);*/
        }
Exemple #6
0
        public static double[] HyperbolaLineParametric(Hyperbola2d hyp, Line2d lin)
        {
            // Computes intersection points with a hyperbola and a line
            // solved and created by Robert.P. 2013-02-11
            //
            // solution is created by transforming system to hyperbola standard position,
            // and then solving the system x^2/a^2-y^2/b^2-1=0 , x=x0+t*dx and y=y0+t*dy (note that a is 1 in std. pos.)

            Transform2d tr = hyp.ToStandardPosition;

            //extract standard spaced line
            double x0, y0, x1, y1, dx, dy, b = hyp.Ratio;

            tr.Apply(lin.X1, lin.Y1, out x0, out y0, true);
            tr.Apply(lin.X2, lin.Y2, out x1, out y1, true);
            dx = x1 - x0; dy = y1 - y0;

            double t2 = -dy * dy + b * b * dx * dx;
            double t1 = -2 * dy * y0 + 2 * b * b * dx * x0;
            double t0 = -y0 * y0 + b * b * x0 * x0 - b * b;

            return(RealPolynomial.SolveQuadric(t2, t1, t0, 0.0));
        }
Exemple #7
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));
        }
Exemple #8
0
        const double seg_maxparam = 1.0;    //used as max limit for parameters beeing on a segment

        #region PRIVATE_UTILS

        /// <summary>
        /// Converts an array of line parameters to an array of points, limited
        /// by a minimum and maximum parameter. On emty result, null is returned,
        /// otherwise a list of points along the line.
        /// </summary>
        private static Point2d[] LineParamsToPoints(double[] ts, Line2d l, double mint, double maxt)
        {
            if (ts == null)
            {
                return(null);
            }
            int n = ts.Length;

            if (n <= 0)
            {
                return(null);
            }

            Point2d[] res = new Point2d[n];
            int       idx = 0;

            for (int q = 0; q < n; q++)
            {
                double t = ts[q];
                if (t >= mint && t <= maxt)
                {
                    res[idx++] = l.PointAt(ts[q]);
                }
            }

            if (idx == 0)
            {
                return(null);    //all params out of range
            }
            if (idx != n)
            {
                Array.Resize(ref res, idx);
            }

            return(res);
        }
Exemple #9
0
 public static Point2d[] HyperbolaSeg(Hyperbola2d hyp, Line2d seg)
 {
     return(LineParamsToPoints(HyperbolaLineParametric(hyp, seg), seg, seg_minparam, seg_maxparam));
 }
Exemple #10
0
        /// <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());
        }
Exemple #11
0
        public static Circle2d[] LineLineLine(Line2d li1, Line2d li2, Line2d li3)
        {
            // see http://www.arcenciel.co.uk/geometry/ for explanation
            List <Circle2d> result = null;
            double          a1, b1, c1, a2, b2, c2, a3, b3, c3, rad, u, v, xcenter, ycenter, denom;
            double          t1 = 1.0, t2 = 1.0, t3 = 1.0;

            if (!li1.ToEquation(out a1, out b1, out c1))
            {
                return(null);
            }
            if (!li2.ToEquation(out a2, out b2, out c2))
            {
                return(null);
            }
            if (!li3.ToEquation(out a3, out b3, out c3))
            {
                return(null);
            }

            //line 2 must not be vertical for this solver, if so, exchange lines
            if (MathUtil.IsZero(b2))
            {
                MathUtil.Swap(ref a1, ref a2);
                MathUtil.Swap(ref b1, ref b2);
                MathUtil.Swap(ref c1, ref c2);
            }

            u = a2 * b1 - a1 * b2;
            v = a3 * b2 - a2 * b3;

            //loop for all 8 possible solutions (only 4 can actually be real solutions)
            for (int signcase = 0; signcase < 8; signcase++)
            {
                t1 = ((signcase & 1) == 0) ? -1 : 1;
                t2 = ((signcase & 2) == 0) ? -1 : 1;
                t3 = ((signcase & 4) == 0) ? -1 : 1;

                //compute radius
                denom = (v * (b1 * t2 - b2 * t1) - u * (b2 * t3 - b3 * t2));
                if (MathUtil.IsZero(denom))
                {
                    continue;
                }
                rad = (u * (b3 * c2 - b2 * c3) - v * (b2 * c1 - b1 * c2)) / denom;
                if (rad < minradius || rad > maxradius)
                {
                    continue;
                }

                //compute center x
                if (!MathUtil.IsZero(u))
                {
                    xcenter = (b2 * c1 - b2 * rad * t1 - b1 * c2 + b1 * rad * t2) / u;
                }
                else if (!MathUtil.IsZero(v))
                {
                    xcenter = (b3 * c2 + b3 * rad * t2 - b2 * c3 + b2 * rad * t3) / v;
                }
                else
                {
                    continue;
                }

                //compute center y
                if (b1 != 0.0)
                {
                    ycenter = (-a1 * xcenter - c1 + rad * t1) / b1;
                }
                else if (b2 != 0.0)
                {
                    ycenter = (-a2 * xcenter - c2 + rad * t2) / b2;
                }
                else
                {
                    ycenter = (-a3 * xcenter - c3 + rad * t3) / b3;
                }

                AddResult(ref result, xcenter, ycenter, rad);
            } //end loop signcase

            if (result == null)
            {
                return(null);
            }
            return(result.ToArray());
        }
Exemple #12
0
        public static Circle2d[] LineLinePoint(Line2d lin1, Line2d lin2, Point2d pnt)
        {
            // Compute the 2 circles (or 1 in special cases) that tangents two lines and a point.
            // Solving for parameter t on the bisector vector between lines that have the same
            // distance to point as the radius for that t (given using radfac computed below)
            // Solution by Robert.P. 2013-02-14

            List <Circle2d> res = null;

            Vector2d v1 = lin1.Direction;
            Vector2d v2 = lin2.Direction;
            Vector2d midvec;
            Point2d  linint;

            double[] ts;



            linint = Intersect2d.LineLineAsPoint(lin1, lin2); //basepoint for midline vector

            if (linint == null)                               //special case for parallel lines
            {
                //use vector and base point on midpoint of radical line of circles
                midvec = v1;
                Line2d radlin = new Line2d(lin1.ClosestPoint(pnt), lin2.ClosestPoint(pnt));
                linint = radlin.MidPoint;
                double r = radlin.Length * 0.5, i = pnt.X, j = pnt.Y, x0 = linint.X, y0 = linint.Y, dx = midvec.X, dy = midvec.Y;

                double tp2 = 1; //squared length of midlin => assume normalized
                double tp1 = 2 * (dy * y0 + dx * x0 - dy * j - dx * i);
                double tp0 = y0 * y0 - 2 * j * y0 - r * r + j * j + i * i + x0 * x0 - 2 * i * x0;

                ts = RealPolynomial.SolveQuadric(tp2, tp1, tp0, 0.0);
                if (ts == null)
                {
                    return(null);
                }

                foreach (double t in ts)
                {
                    Point2d center = linint + midvec * t;
                    AddResult(ref res, center.X, center.Y, r);
                }
            }
            else //normal case with non-parallel lines
            {
                if (pnt.Location(lin1.Start, lin1.End) == pnt.Location(lin2.Start, lin2.End))
                {
                    v2 = -v2;   //select correct bisector out of two (actually 4 but it does not matter if we solve for negative t)
                }
                midvec = v1.Bisect(v2);
                double radfac = Math.Sin(v1.AngleTo(v2) / 2.0); //multiplied with midvector t this gives radius of circle at that t

                //solve problem in space where pnt=origo
                Point2d org = new Point2d(linint.X - pnt.X, linint.Y - pnt.Y);
                double  t2  = -radfac * radfac + 1; //// 1 for squared length of midlin => assume normalized
                double  t1  = 2 * (midvec.Y * org.Y + midvec.X * org.X);
                double  t0  = org.X * org.X + org.Y * org.Y;
                ts = RealPolynomial.SolveQuadric(t2, t1, t0, 0.0);

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

                foreach (double t in ts)
                {
                    Point2d center = linint + midvec * t;
                    AddResult(ref res, center.X, center.Y, Math.Abs(t * radfac));
                }
            }

            return(MakeResult(res));
        }
Exemple #13
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);
        }
Exemple #14
0
        public static Circle2d[] CircleLineLine(Circle2d ci, Line2d l1, Line2d l2)
        {
            // see http://www.arcenciel.co.uk/geometry/ for explanation

            List <Circle2d> result = null;

            //translate everyting so circle center at origo
            double dx = ci.X, dy = ci.Y;

            ci = new Circle2d(0, 0, ci.Radius);
            l1 = new Line2d(l1.X1 - dx, l1.Y1 - dy, l1.X2 - dx, l1.Y2 - dy);
            l2 = new Line2d(l2.X1 - dx, l2.Y1 - dy, l2.X2 - dx, l2.Y2 - dy);

            //if first line vertical, swap lines...
            if (MathUtil.Equals(l1.X1, l1.X2))
            {
                var tmp = l1; l1 = l2; l2 = tmp;
            }

            //if first line still vertical, special case:
            if (MathUtil.Equals(l1.X1, l1.X2))
            {
                double rad     = (l1.X1 - l2.X1) / 2.0;
                double xcenter = (l1.X1 + l2.X1) / 2.0;

                double yc = Math.Sqrt((rad + ci.Radius) * (rad + ci.Radius) - xcenter * xcenter);

                AddResult(ref result, xcenter, ci.Y + yc, rad);
                AddResult(ref result, xcenter, ci.Y - yc, rad);
            }
            else
            {
                //now we know that first line is not vertical, and circle is centered at origo
                double a1, b1, c1, a2, b2, c2, u, w, s, a, b, c, xcenter, ycenter, t1, t2, r3;

                if (!l1.ToEquation(out a1, out b1, out c1))
                {
                    return(null);
                }
                if (!l2.ToEquation(out a2, out b2, out c2))
                {
                    return(null);
                }

                for (int signcase = 0; signcase < 8; signcase++)
                {
                    t1 = ((signcase & 1) == 0) ? -1 : 1;
                    t2 = ((signcase & 2) == 0) ? -1 : 1;
                    r3 = ((signcase & 4) == 0) ? -ci.Radius : ci.Radius;

                    u = (t1 * b2) - (t2 * b1);
                    w = (b1 * c2) - (b2 * c1);
                    s = (a1 * b2) - (a2 * b1);
                    a = (u * u) - (2 * a1 * s * u * t1) + (t1 * t1 * s * s) - (b1 * b1 * s * s);
                    b = 2.0 * ((u * w) + (c1 * a1 * s * u) - (a1 * s * t1 * w) - (c1 * t1 * s * s) - (r3 * b1 * b1 * s * s));
                    c = (w * w) + (2 * a1 * s * c1 * w) + (c1 * c1 * s * s) - (b1 * b1 * r3 * r3 * s * s);
                    double[] roots = RealPolynomial.SolveQuadric(a, b, c);
                    if (roots != null)
                    {
                        foreach (double radius in roots)
                        {
                            if (radius < minradius || radius > maxradius)
                            {
                                continue;
                            }

                            if (!MathUtil.IsZero(s))
                            { //non parallel lines, one center per root
                                xcenter = (radius * u + w) / s;
                                ycenter = ((-a1 * xcenter) - c1 + (radius * t1)) / b1;
                                AddResult(ref result, xcenter, ycenter, radius);
                            }
                            else  //parallel lines, two centers per root
                            {
                                a = t1 * t1;
                                b = 2.0 * a1 * (c1 - (radius * t1));
                                c = ((radius * t1) - c1) * ((radius * t1) - c1) - (b1 * b2 * (r3 + radius) * (r3 + radius));
                                double[] roots2 = RealPolynomial.SolveQuadric(a, b, c);
                                if (roots2 != null)
                                {
                                    foreach (double x in roots2)
                                    {
                                        ycenter = (-a1 * x - c1 + radius * t1) / b1;
                                        AddResult(ref result, x, ycenter, radius);
                                    }
                                }
                            }
                        }
                    }
                }
            }


            //translate results back to original position
            if (result != null)
            {
                foreach (Circle2d c in result)
                {
                    c.X += dx;
                    c.Y += dy;
                }
                return(result.ToArray());
            }

            return(null);
        }
Exemple #15
0
 public static Point2d[] HyperbolaLine(Hyperbola2d hyp, Line2d lin)
 {
     return(LineParamsToPoints(HyperbolaLineParametric(hyp, lin), lin, double.NegativeInfinity, double.PositiveInfinity));
 }
Exemple #16
0
 public static Point2d[] HyperbolaRay(Hyperbola2d hyp, Line2d ray)
 {
     return(LineParamsToPoints(HyperbolaLineParametric(hyp, ray), ray, seg_minparam, double.PositiveInfinity));
 }
Exemple #17
0
 public static Point2d[] CircleSeg(Circle2d c, Line2d l)
 {
     return(LineParamsToPoints(CircleLineParametric(c, l), l, seg_minparam, seg_maxparam));
 }
Exemple #18
0
 public static Point2d[] CircleLine(Circle2d c, Line2d l)
 {
     return(LineParamsToPoints(CircleLineParametric(c, l), l, double.NegativeInfinity, double.PositiveInfinity));
 }
Exemple #19
0
 public static Point2d[] CircleRay(Circle2d c, Line2d l)
 {
     return(LineParamsToPoints(CircleLineParametric(c, l), l, seg_minparam, double.PositiveInfinity));
 }
Exemple #20
0
 public static Point2d[] ParabolaLine(Parabola2d pab, Line2d lin)
 {
     return(LineParamsToPoints(ParabolaLineParamteric(pab, lin), lin, double.NegativeInfinity, double.PositiveInfinity));
 }
Exemple #21
0
 public Line2d(Line2d tocopy)
 {
     start = tocopy.start;
     end   = tocopy.end;
 }