Formule voor berekenen snijpunten van 2 cirkels

Nu is mijn wiskunde kennis wel redelijk in orde,  maar om een formule te vinden die de 2 snijpunten van 2 cirkels berekend had ik toch wat problemen. Op internet vond ik helaas ook geen kant en klare formules.

Uiteindelijk heb ik de volgende een oplossing gevonden.

Mochten er simpelere oplossingen zijn dan hoor ik dat graag!

Hieronder de 2 cirkels met de 2 snijpunten. Ik heb in deze tekening 2 hulp driehoeken getekend.

bereken raaklijnen 2 cirkels (1).png

gegeven.png

Dan kun je een driehoek maken tussen de 2 middelpunten van de cirkels en punt P en Q met zijde a,b en c.
De lengte van de 3 zijdes kun je berekenen op de volgende manier.:

abc.png

Met de cosinus regel kunnen we nu hoek α berekenen.
Ook kunnen we hoek λ berekenen.
Met deze 2 hoeken kunnen we β en γ berekenen.

hoeken.png

Met de β kunnen we voor punt P de delta-x en delta-y ten opzichte van het middelpunt van cirkel A berekenen.

deltap.png

Met de γ kunnen we voor punt Q de delta-x en delta-y ten opzichte van het middelpunt van cirkel A berekenen.

deltaq.png

Uiteindelijk kunnen hiermee we punt P en Q berekenen.

p.png

q.png

In java code zou dat zou opgelost kunnen worden:

private Optional<PointSet> berekenSnijpunten(Cirkel cirkel1, Cirkel cirkel2) {
    double a = cirkel2.r;
    double b = cirkel1.r;
    double c = Math.sqrt(Math.pow(cirkel2.x - cirkel1.x, 2) + Math.pow(cirkel2.y - cirkel1.y, 2));

    // hoek alpha
    double alpha = Math.toDegrees(Math.acos((b * b + c * c - a * a) / (2 * b * c)));

    if (Double.isNaN(alpha)) return Optional.empty();

    // --- 1e punt
    // hoek z
    double z = Math.toDegrees(Math.atan((cirkel2.y - cirkel1.y) / (cirkel2.x - cirkel1.x)));

    // hoek w
    double w = 180 - alpha - z;

    // delta x en y
    double deltaX = Math.cos(Math.toRadians(w)) * cirkel1.r;
    double deltaY = Math.sin(Math.toRadians(w)) * cirkel1.r;

    if (cirkel1.x > cirkel2.x) {
        deltaX = deltaX * -1;
        deltaY = deltaY * -1;
    }

    // snijpunt
    double p1x = cirkel1.x - deltaX;
    double p1y = cirkel1.y + deltaY;
    Point p1 = new Point(p1x, p1y);

    // --- 2e punt
    // hoek u
    double u = 180 + alpha - z;

    // delta x en y
    double deltaP2x = Math.cos(Math.toRadians(u)) * cirkel1.r;
    double deltaP2y = Math.sin(Math.toRadians(u)) * cirkel1.r;
    if (cirkel1.x > cirkel2.x) {
        deltaP2x = deltaP2x * -1;
        deltaP2y = deltaP2y * -1;
    }

    // snijpunt
    double p2x = cirkel1.x - deltaP2x;
    double p2y = cirkel1.y + deltaP2y;
    Point p2 = new Point(p2x, p2y);
    
    return Optional.of(new PointSet(p1, p2));
}

class Point {
    double x = 0;
    double y = 0;
}

class Cirkel {
    double x = 0;
    double y = 0;
    double r = 0;
}