Schnittpunkt zweier Kreise berechnen



  • Hallo!

    Ich habe ein Programm geschrieben, um die Schnittpunkte von 2 Kreisen zu berechnen. Das Problem: Es kommt nicht das richtige Ergebnis raus 😞
    Ich finde leider keinen Fehler in meiner Rechnung, hab sie mir schon so oft durchgeschaut. Vll hab ich ja auch einfach einen Programmierfehler drin oder so.

    Ich benutze den QtCreator als Entwicklungsumgebung.

    Zu meiner Rechnung: Ich bin von folgenden Gleichungen ausgegangen:
    (x-x1)^2 + (z-z1)^2 = r1^2
    (x-x2)^2 + (z-z2)^2 = r2^2

    Gleichsetzen, nach x Auflösen, Variablen setzen, um Schreibarbeit zu sparen, in 1.Gleichung einsetzen, nach y umstellen und mit Mitternachtsformel auflösen.

    Wenn ihr meine komplette Rechnung sehen wollt, kann ich sie auch einscannen...

    Hoffentlich könnt ihr mir helfen.

    lg

    #include <QtCore/QCoreApplication>
    #include <QtGui/QApplication>
    #include <QDebug>
    #include <QtCore/QCoreApplication>
    #include <QVector>
    #include <cmath>
    #include <QDebug>
    #include <iostream>
    #include <fstream>
    #include <string>
    using std::string;
    
    double powxy(double base, int exponent)
    {
        double result = base;
        for(int i = 1; i<exponent; i++)
        {
            result *= base;
        }
        return result;
    }
    
    QVector<double> circlesCut(double x1, double z1, double r1, double x2, double z2, double r2)
    {
        /*x1, z1 & x2, z2 are center coordinates of the two circles with radii r1 & r2
        *calculus oriented on the following equation:
        *********************************************************
        *(x-x1)^2 + (z-z1)^2 - r1^2 = (x-x2)^2 + (z-z2)^2 - r2^2*
        *********************************************************
        */
    
        double resultX1=0,resultX2=0,resultZ1=0,resultZ2=0; //results
        double c1,c2,a,b,c; //temps
        QVector<double> results;
    
        if(x1==x2 && z1==z2)
        {
            qDebug()<<"The centers are equal...";
        }
        else if(x1==x2 && z1!=z2)
        {
            resultZ1 = (z2*z2 - z1*z1 + r1*r1 - r2*r2) / (2.0*z2 - 2.0*z1);
            resultZ2 = resultZ1;
    
            a = 1.0;
            b = -2.0*x1;
            c = resultZ1*resultZ1 -2.0*resultZ1*z1 + z1*z1 - r1*r1;
    
            resultX1 = (-b + sqrt(b*b - 4.0*a*c)) / (2.0*a);            //Mitternachtsformel
            resultX2 = (-b - sqrt(b*b - 4.0*a*c)) / (2.0*a);
        }
        else if(x1!=x2 && z1==z2)
        {
            resultX1 = (x2*x2 - x1*x1 + r1*r1 - r2*r2) / (2.0*x2 - 2.0*x1);
            resultX2 = resultX1;
    
            a = 1.0;
            b = -2.0*z1;
            c = resultX1*resultX1 - 2.0*resultX1*x1 + x1*x1 - r1*r1;
    
            resultZ1 = (-b + sqrt(b*b - 4.0*a*c)) / (2.0*a);            //Mitternachtsformel
            resultZ2 = (-b - sqrt(b*b - 4.0*a*c)) / (2.0*a);
        }
        else //default case: (x1!=x2 && z1!=z2)
        {
            //temps to make calculus easier to write, derived of: x = c1*z + c2
            c1 = (z1 - z2) / (x2 - x1);
            c2 = (x2*x2 - x1*x1 + z2*z2 - z1*z1 + r1*r1 - r2*r2) / (2.0*x2 - 2.0*x1);
    
            a = c1*c1 + 1.0;
            b = 2.0*c1*c2 - 2.0*c1*x1 - 2.0*z1;
            c = c2*c2 - 2.0*c2*x1 + x1*x1 + z1*z1 - c1*c1;
    
            resultZ1 = (-b + sqrt(b*b - 4.0*a*c)) / (2.0*a);            //Mitternachtsformel
            resultZ2 = (-b - sqrt(b*b - 4.0*a*c)) / (2.0*a);
    
            resultX1 = c1*resultZ1 + c2;
            resultX2 = c1*resultZ2 + c2;
        }
    
        results << resultX1 << resultZ1 << resultX2 << resultZ2;
    
        return results;
    }
    
    int main(int argc, char *argv[])
    {
        double x1,z1,x2,z2,r1,r2;
        //Test:
        x1 = 7.0;
        z1 = 6.0;
        r1 = 5.0;
        x2 = 7.5;
        z2 = 9.5;
        r2 = sqrt(12.5);
    
        /*was rauskommen müsste: (11,9), (4,10)
         *was tatsächlich rauskommt: (14.8421, 9.53571), (-0.842112, 9.53571)
        */
       qDebug()<<x1<<z1<<r1<<x2<<z2<<r2;
        QVector<double> result;
        result = circlesCut(x1,z1,r1,x1,z2,r2);
    
        qDebug()<<result;
    
        return 0;
    }
    


  • Hallo pfeimi,

    willkommen im C++-Forum.

    Ein Fehler ist in dieser Zeile (102)

    pfeimi schrieb:

    result = circlesCut(x1,z1,r1,  x1  ,z2,r2);
    

    aber es ist nicht der einzige!

    :xmas2: Werner



  • x1==x2
    ist auch nicht so klug.

    bau dir eine double_gleich(x1,x2) Funktion.



  • danke für die schnellen antworten 🙂

    @Werner: oups 😮 das hätte mir echt auffallen können... (das erg ist trotzdem noch nicht richtig... sind die anderen fehler auch so trivial? ^^')

    @Lukas: wieso ist das besser? und was würde dann anderes in der funktion stehen?

    lg


  • Mod

    pfeimi schrieb:

    @Lukas: wieso ist das besser? und was würde dann anderes in der funktion stehen?

    Das ist hier durchaus in Ordnung, so wie du das gemacht hast. Sei dir aber im Klaren, dass das Vergleichen von Fließkommazahlen mittels absoluter Gleichheit durchaus überraschend sein kann, besonders wenn sie das Ergebnis einer Rechnung sind. So ist z.B. 10* 0.1 != 1.0

    @Werner: oups 😮 das hätte mir echt auffallen können... (das erg ist trotzdem noch nicht richtig... sind die anderen fehler auch so trivial? ^^')

    Vor allem mal, kommt mir das auf den ersten Blick viel zu kompliziert vor. Viel zu viele Fälle, die sich eigentlich gar nicht unterscheiden. Im Prinzip gibt es nur zwei bis vier Fälle:
    1. Abstand 0, Radius1 == Radius2 ➡ unendlich viele Lösungen
    2. Andernfalls ➡ Zwei Lösungen, eventuell entartet, eventuell komplex
    (3. Zwei entartete Lösungen heißt, die Kreise berühren sich gerade. Rechnung ist wie in 2.)
    (4. Zwei komplexe Lösungen heißt, die Kreise schneiden sich nicht. Rechnung ist wie in 2.)

    Also wenn du so willst 1 bis 3 Abfragen und eine Rechnung für alle Fälle.



  • ok, ich habe den code nochmal verkürzt... trotzdem muss wohl an der Rechnung irgend etwas falsch sein... das Ergebnis ist noch nicht richtig. Habe ich einen falschen Ansatz gewählt oder mich irgendwo verrechnet?

    (ich hab c1 und c2 mit t1 und t2 umbenannt)

    #include <QtCore/QCoreApplication>
    #include <QtGui/QApplication>
    #include <QDebug>
    #include <QtCore/QCoreApplication>
    #include <QVector>
    #include <cmath>
    #include <QDebug>
    #include <iostream>
    #include <fstream>
    #include <string>
    using std::string;
    
    double powxy(double base, int exponent)
    {
        double result = base;
        for(int i = 1; i<exponent; i++)
        {
            result *= base;
        }
        return result;
    }
    
    QVector<double> circlesCut(double x1, double z1, double r1, double x2, double z2, double r2)
    {
        /*x1, z1 & x2, z2 are center coordinates of the two circles with radii r1 & r2
        *calculus oriented on the following equation:
        *********************************************************
        *(x-x1)^2 + (z-z1)^2 - r1^2 = (x-x2)^2 + (z-z2)^2 - r2^2*
        *********************************************************
        */
    
        double resultX1=0,resultX2=0,resultZ1=0,resultZ2=0; //results
        double t1,t2,a,b,c, distance; //temps
        QVector<double> results;
    
        distance = sqrt(powxy(x1-x2, 2) + powxy(z1-z2,2));
    
        if(distance < 0.01)
        {
            qDebug()<<"The centers are equal...";
        }
        else //default case: (x1!=x2 && z1!=z2) || (x1==x2 && z1!=z2) || (x1!=x2 && z1==z2)
        {
            //temps to make calculus easier to write, derived of: x = t1*z + t2
            t1 = (z1 - z2) / (x2 - x1);
            t2 = (x2*x2 - x1*x1 + z2*z2 - z1*z1 + r1*r1 - r2*r2) / (2.0*x2 - 2.0*x1);
    
            a = t1*t1 + 1.0;
            b = 2.0*t1*t2 - 2.0*t1*x1 - 2.0*z1;
            c = t2*t2 - 2.0*t2*x1 + x1*x1 + z1*z1 - t1*t1;
    
            resultZ1 = (-b + sqrt(b*b - 4.0*a*c)) / (2.0*a);            //Mitternachtsformel
            resultZ2 = (-b - sqrt(b*b - 4.0*a*c)) / (2.0*a);
    
            resultX1 = t1*resultZ1 + t2;
            resultX2 = t1*resultZ2 + t2;
        }
    
        results << resultX1 << resultZ1 << resultX2 << resultZ2;
    
        return results;
    }
    
    int main(int argc, char *argv[])
    {
        double x1,z1,x2,z2,r1,r2;
        //Test:
        x1 = 7.0;
        z1 = 6.0;
        r1 = 5.0;
        x2 = 7.5;
        z2 = 9.5;
        r2 = sqrt(12.5);
    
        /*was rauskommen müsste: (11,9), (4,10)
         *was tatsächlich rauskommt: (1.5192, 10.3544), (13.4808, 8.6456)
         */
    
       qDebug()<<x1<<z1<<r1<<x2<<z2<<r2;
        QVector<double> result;
        result = circlesCut(x1,z1,r1,x2,z2,r2);
    
        qDebug()<<result;
    
        return 0;
    }
    

    meine Rechnung:

    http://s7.directupload.net/images/111216/temp/yxepr6yg.jpg



  • In Zeile 50 muss hinten r1*r1 statt c1*c1 stehen.
    Bei Deinem ersten Posting in Zeile 72 .. dort müsste es heißen

    c = c2*c2 - 2.0*c2*x1 + x1*x1 + z1*z1 - r1*r1; // - c1*c1; war falsch
    

    dann kommt auch das richtige raus. 🙂
    Und genau diese Stelle fehlt auf Deinem Bild!

    :xmas2: Werner



  • oooooooooooh.......... man bin ich blöd. saß so lang dran, dass ich die Fehler gar net mehr gesehen hab 😃

    danke 👍

    aber eins interessiert mich noch: wieso ist 10*.01 != 1.0 ?? werden beim zusammenrechnen noch mehr Nachkommastellen angehängt, weshalb 1.00000000 != 1.0?
    Und wie kann man, wenn nicht mit dem Vergleichsoperator, denn sonst 2 Zahlen miteinander vergleichen? Kenne mich noch nicht so gut aus in C...

    lg



  • manche Zahlen sind nicht als Gleitkommazahl darstellbar. 1/3 zB
    http://realtimecollisiondetection.net/blog/?p=89

    greetz KN4CK3R



  • ok, danke 🙂 das leuchtet mir ein.

    allerdings "sagt" mein Compiler, dass (10*0.1 == 1.0) wahr ist... 😃


  • Mod

    Ja, das kann schon sein. Aber probier mal, Zehnmal 0.1 zu addieren in einer Schleife:

    double x;
       for(int i = 0; i < 10; ++i)
        x += 0.1;
      if (x == 1.0)
        cout << "True\n";
      else
        cout << "False\n";
    

Anmelden zum Antworten