I am trying to find the point of intersection of a circle and a line through its center. I want to put an arrow on the point actually, to make a directed graph. After some calculations, I found that the math that would go in is,

formula

The figure of reference is:
intersection

The code I am using to achieve this is:

private Point getArrow(Point center, Point line) {
        Point interesection;
        int a = line.x;
        int b = center.x;
        int c = line.y;
        int d = center.y;
        int x1 = 0, y1 = 0, x2 = 0, y2 = 0;

        if ((b - a) != 0) {
            try {
                x1 = (int) (b + ((20 * (a - b)) / Math.sqrt((Math.pow((a - b), 2)) + Math.pow(c - d, 2))));
                x2 = (int) (b - ((20 * (a - b)) / Math.sqrt((Math.pow((a - b), 2)) + Math.pow(c - d, 2))));

                y1 = (int) (((d - c) / (b - a)) * (x1 - a) + c);
                y2 = (int) (((d - c) / (b - a)) * (x2 - a) + c);
            } catch (ArithmeticException ex) {
                if ((a - b) == 0) {
                    y1 = y2 = 0;
                } else if ((a - b) == 0 && (c - d) == 0) {
                    x1 = x2 = y1 = y2 = 0;
                }
            }
        } else {
            return new Point(center.x+19, center.y - 5);
        }
        Point p1 = new Point(x1+19, y1+19);
        Point p2 = new Point(x2+19, y2+19);

        if (line.distanceSq(p2) < line.distanceSq(p1)) {
            interesection = new Point(p2);
        } else {
            interesection = new Point(p1);
        }


        return interesection;
    }

Can anyone tell me why my code is breaking for the math? I am trying to plot the point returned as a filled oval of width and height being 5. The radius of the original circle is 20.

Dani AI

Generated

You do not need the slope-based algebra here. For a circle centered at C(cx,cy) with radius r and any point P(px,py) defining the direction, the intersection on the circle in the direction of P is just:
C + r * normalize(P - C). That gives one unique point without special cases for vertical lines.

Here is a compact, numerically safe version using doubles (then round when drawing). It also handles the degenerate case P == C:

private static Point2D.Double pointOnCircle(Point2D center, Point2D toward, double r) {
    double dx = toward.getX() - center.getX();
    double dy = toward.getY() - center.getY();
    double len = Math.hypot(dx, dy);
    if (len == 0) { // no direction; pick a default or skip drawing
        return new Point2D.Double(center.getX() + r, center.getY());
    }
    double k = r / len;
    return new Point2D.Double(center.getX() + dx * k, center.getY() + dy * k);
}

When drawing the 5x5 dot, center it on the computed point (subtract half the width/height):
g.fillOval((int)Math.round(p.x) - 2, (int)Math.round(p.y) - 2, 5, 5);
No magic +19 offsets are needed; those usually indicate a coordinate mismatch elsewhere (eg, mixing component-local and world coordinates).

Why your code breaks:

  • (d - c) / (b - a) is integer division, so the slope truncates to 0 or the wrong value. Cast to double if you stick with that approach.
  • try/catch (ArithmeticException) will not help with 1.0/0.0; floating-point divide-by-zero yields Infinity/NaN, not an exception.
  • The conditional on (b - a) != 0 still allows the denominator sqrt((a-b)^2 + (c-d)^2) to be 0 when the two points coincide.

Also agree with : rename variables to match the diagram, compute the intersection first, then draw.

This is very confusing because the variable names in your code look like the ones in the diagram/formulae, but are used completely differently -eg in the diagram x2,y2 is the centre of the circle, but in your code they are one of the intersection points. So my advice is
1. Make yur variables names match exactly the reference diagram/formulae
2. Forget about the filled oval for now and just get it returning the intersection point correctly
and by the way...
3. Don't use try/catch for predictable arithmetic exceptions; exceptions should be used for exceptional events that you can't predict - test the data so that the exception won't be thrown in the first place

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.