Task: Line circle intersection

C: #include <math.h>
#include <stdbool.h>
#include <stdio.h>

const double eps = 1e-14;

typedef struct point_t {
    double x, y;
} point;

point make_point(double x, double y) {
    point p = { x, y };
    return p;
}

void print_point(point p) {
    double x = p.x;
    double y = p.y;
    if (x == 0) {
        x = 0;
    }
    if (y == 0) {
        y = 0;
    }
    printf("(%g, %g)", x, y);
}

double sq(double x) {
    return x * x;
}

bool within(double x1, double y1, double x2, double y2, double x, double y) {
    double d1 = sqrt(sq(x2 - x1) + sq(y2 - y1));    
    double d2 = sqrt(sq(x - x1) + sq(y - y1));      
    double d3 = sqrt(sq(x2 - x) + sq(y2 - y));      
    double delta = d1 - d2 - d3;
    return fabs(delta) < eps;   
}

int rxy(double x1, double y1, double x2, double y2, double x, double y, bool segment) {
    if (!segment || within(x1, y1, x2, y2, x, y)) {
        print_point(make_point(x, y));
        return 1;
    } else {
        return 0;
    }
}

double fx(double A, double B, double C, double x) {
    return -(A * x + C) / B;
}

double fy(double A, double B, double C, double y) {
    return -(B * y + C) / A;
}




void intersects(point p1, point p2, point cp, double r, bool segment) {
    double x0 = cp.x, y0 = cp.y;
    double x1 = p1.x, y1 = p1.y;
    double x2 = p2.x, y2 = p2.y;
    double A = y2 - y1;
    double B = x1 - x2;
    double C = x2 * y1 - x1 * y2;
    double a = sq(A) + sq(B);
    double b, c, d;
    bool bnz = true;
    int cnt = 0;

    if (fabs(B) >= eps) {
        
        b = 2 * (A * C + A * B * y0 - sq(B) * x0);
        c = sq(C) + 2 * B * C * y0 - sq(B) * (sq(r) - sq(x0) - sq(y0));
    } else {
        b = 2 * (B * C + A * B * x0 - sq(A) * y0);
        c = sq(C) + 2 * A * C * x0 - sq(A) * (sq(r) - sq(x0) - sq(y0));
        bnz = false;
    }
    d = sq(b) - 4 * a * c; 
    if (d < 0) {
        
        printf("[]\n");
        return;
    }

    if (d == 0) {
        
        if (bnz) {
            double x = -b / (2 * a);
            double y = fx(A, B, C, x);
            cnt = rxy(x1, y1, x2, y2, x, y, segment);
        } else {
            double y = -b / (2 * a);
            double x = fy(A, B, C, y);
            cnt = rxy(x1, y1, x2, y2, x, y, segment);
        }
    } else {
        
        d = sqrt(d);
        if (bnz) {
            double x = (-b + d) / (2 * a);
            double y = fx(A, B, C, x);
            cnt = rxy(x1, y1, x2, y2, x, y, segment);

            x = (-b - d) / (2 * a);
            y = fx(A, B, C, x);
            cnt += rxy(x1, y1, x2, y2, x, y, segment);
        } else {
            double y = (-b + d) / (2 * a);
            double x = fy(A, B, C, y);
            cnt = rxy(x1, y1, x2, y2, x, y, segment);

            y = (-b - d) / (2 * a);
            x = fy(A, B, C, y);
            cnt += rxy(x1, y1, x2, y2, x, y, segment);
        }
    }

    if (cnt <= 0) {
        printf("[]");
    }
}

int main() {
    point cp = make_point(3, -5);
    double r = 3.0;
    printf("The intersection points (if any) between:\n");
    printf("  A circle, center (3, -5) with radius 3, and:\n");
    printf("    a line containing the points (-10, 11) and (10, -9) is/are:\n");
    printf("      ");
    intersects(make_point(-10, 11), make_point(10, -9), cp, r, false);
    printf("\n    a segment starting at (-10, 11) and ending at (-11, 12) is/are\n");
    printf("      ");
    intersects(make_point(-10, 11), make_point(-11, 12), cp, r, true);
    printf("\n    a horizontal line containing the points (3, -2) and (7, -2) is/are:\n");
    printf("      ");
    intersects(make_point(3, -2), make_point(7, -2), cp, r, false);
    printf("\n");

    cp = make_point(0, 0);
    r = 4.0;
    printf("  A circle, center (0, 0) with radius 4, and:\n");
    printf("    a vertical line containing the points (0, -3) and (0, 6) is/are:\n");
    printf("      ");
    intersects(make_point(0, -3), make_point(0, 6), cp, r, false);
    printf("\n    a vertical segment starting at (0, -3) and ending at (0, 6) is/are:\n");
    printf("      ");
    intersects(make_point(0, -3), make_point(0, 6), cp, r, true);
    printf("\n");

    cp = make_point(4,2);
    r = 5.0;
    printf("  A circle, center (4, 2) with radius 5, and:\n");
    printf("    a line containing the points (6, 3) and (10, 7) is/are:\n");
    printf("      ");
    intersects(make_point(6, 3), make_point(10, 7), cp, r, false);
    printf("\n    a segment starting at (7, 4) and ending at (11, 8) is/are:\n");
    printf("      ");
    intersects(make_point(7, 4), make_point(11, 8), cp, r, true);
    printf("\n");

    return 0;
}





Java: import java.util.*;
import java.awt.geom.*;

public class LineCircleIntersection {
    public static void main(String[] args) {
        try {
            demo();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void demo() throws NoninvertibleTransformException {
        Point2D center = makePoint(3, -5);
        double radius = 3.0;
        System.out.println("The intersection points (if any) between:");
        System.out.println("\n  A circle, center (3, -5) with radius 3, and:");
        System.out.println("\n    a line containing the points (-10, 11) and (10, -9) is/are:");
        System.out.println("     " + toString(intersection(makePoint(-10, 11), makePoint(10, -9),
                            center, radius, false)));
        System.out.println("\n    a segment starting at (-10, 11) and ending at (-11, 12) is/are");
        System.out.println("     " + toString(intersection(makePoint(-10, 11), makePoint(-11, 12),
                            center, radius, true)));
        System.out.println("\n    a horizontal line containing the points (3, -2) and (7, -2) is/are:");
        System.out.println("     " + toString(intersection(makePoint(3, -2), makePoint(7, -2), center, radius, false)));
        center.setLocation(0, 0);
        radius = 4.0;
        System.out.println("\n  A circle, center (0, 0) with radius 4, and:");
        System.out.println("\n    a vertical line containing the points (0, -3) and (0, 6) is/are:");
        System.out.println("     " + toString(intersection(makePoint(0, -3), makePoint(0, 6),
                            center, radius, false)));
        System.out.println("\n    a vertical segment starting at (0, -3) and ending at (0, 6) is/are:");
        System.out.println("     " + toString(intersection(makePoint(0, -3), makePoint(0, 6),
                            center, radius, true)));
        center.setLocation(4, 2);
        radius = 5.0;
        System.out.println("\n  A circle, center (4, 2) with radius 5, and:");
        System.out.println("\n    a line containing the points (6, 3) and (10, 7) is/are:");
        System.out.println("     " + toString(intersection(makePoint(6, 3), makePoint(10, 7),
                            center, radius, false)));
        System.out.println("\n    a segment starting at (7, 4) and ending at (11, 8) is/are:");
        System.out.println("     " + toString(intersection(makePoint(7, 4), makePoint(11, 8),
                            center, radius, true)));
    }

    private static Point2D makePoint(double x, double y) {
        return new Point2D.Double(x, y);
    }

    
    
    
    
    
    
    
    
    public static List<Point2D> intersection(Point2D p1, Point2D p2, Point2D center,
            double radius, boolean isSegment) throws NoninvertibleTransformException {
        List<Point2D> result = new ArrayList<>();
        double dx = p2.getX() - p1.getX();
        double dy = p2.getY() - p1.getY();
        AffineTransform trans = AffineTransform.getRotateInstance(dx, dy);
        trans.invert();
        trans.translate(-center.getX(), -center.getY());
        Point2D p1a = trans.transform(p1, null);
        Point2D p2a = trans.transform(p2, null);
        double y = p1a.getY();
        double minX = Math.min(p1a.getX(), p2a.getX());
        double maxX = Math.max(p1a.getX(), p2a.getX());
        if (y == radius || y == -radius) {
            if (!isSegment || (0 <= maxX && 0 >= minX)) {
                p1a.setLocation(0, y);
                trans.inverseTransform(p1a, p1a);
                result.add(p1a);
            }
        } else if (y < radius && y > -radius) {
            double x = Math.sqrt(radius * radius - y * y);
            if (!isSegment || (-x <= maxX && -x >= minX)) {
                p1a.setLocation(-x, y);
                trans.inverseTransform(p1a, p1a);
                result.add(p1a);
            }
            if (!isSegment || (x <= maxX && x >= minX)) {
                p2a.setLocation(x, y);
                trans.inverseTransform(p2a, p2a);
                result.add(p2a);
            }
        }
        return result;
    }

    public static String toString(Point2D point) {
        return String.format("(%g, %g)", point.getX(), point.getY());
    }

    public static String toString(List<Point2D> points) {
        StringBuilder str = new StringBuilder("[");
        for (int i = 0, n = points.size(); i < n; ++i) {
            if (i > 0)
                str.append(", ");
            str.append(toString(points.get(i)));
        }
        str.append("]");
        return str.toString();
    }
}