Пример #1
0
        public static List <Point> LineCircleIntersect(Line line, Circle circle)
        {
            Vector2 linePointA, linePointB;
            float   xA = -1;
            float   yA = line.fX(xA);
            float   xB, yB;

            if (!float.IsNaN(yA))
            {
                xB = 1;
                yB = line.fX(xB);
            }
            else
            {
                yA = -1;
                xA = line.fY(yA);
                yB = 1;
                xB = line.fY(yB);
            }
            linePointA = new Vector2(xA, yA);
            linePointB = new Vector2(xB, yB);
            //circle is at 0, 0 for this...
            var localPA = linePointA - circle.center;
            var localPB = linePointB - circle.center;
            //http://mathworld.wolfram.com/Circle-LineIntersection.html
            float r               = circle.radius;
            float x1              = localPA.x;
            float x2              = localPB.x;
            float y1              = localPA.y;
            float y2              = localPB.y;
            float dx              = x2 - x1;
            float dy              = y2 - y1;
            float dr              = Mathf.Sqrt((dx * dx) + (dy * dy));
            float bigD            = x1 * y2 - x2 * y1;
            var   localIntersects = new List <Point>();
            float discriminant    = (r * r) * (dr * dr) - (bigD * bigD);

            if (!(discriminant < 0))
            {
                float xNumeratorSummand1 = bigD * dy;
                float xNumeratorSummand2 = sgn(dy) * dx * Mathf.Sqrt(discriminant);
                float xQuotient          = dr * dr;
                float yNumeratorSummand1 = -bigD * dx;
                float yNumeratorSummand2 = Mathf.Abs(dy) * Mathf.Sqrt(discriminant);
                float yQuotient          = dr * dr;
                localIntersects.Add(new Point(
                                        (xNumeratorSummand1 + xNumeratorSummand2) / xQuotient,
                                        (yNumeratorSummand1 + yNumeratorSummand2) / yQuotient)
                                    );
                if (discriminant > 0)
                {
                    localIntersects.Add(new Point(
                                            (xNumeratorSummand1 - xNumeratorSummand2) / xQuotient,
                                            (yNumeratorSummand1 - yNumeratorSummand2) / yQuotient)
                                        );
                }
            }
            var output = new List <Point>();

            //revert transformation into local space of circle
            foreach (var intersect in localIntersects)
            {
                output.Add((Vector2)intersect + circle.center);
            }
            return(output);

            //since regular sign function returns 0 at input 0
            float sgn(float inputValue)
            {
                return(inputValue < 0 ? -1 : 1);
            }
        }