Ejemplo n.º 1
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));
        }