Schittpunkt von Kreis und Grade

  • Hallo,

    ich verzweifle grade an einem eigentlich einfachen und tausendfach dokumentierten Probelm.

    Ich habe einen Kreis (Radius: 200 xM: 0 yM: 600) und eine Grade die durch den Mittelpunkt des Kreises läuft.
    Die Steigung und der y-Achsen-Abschnitt ist vaiabel.
    Ich würde jetzt gerne die Schittpunktkoordinaten der Grade mit der Kreislinie wissen.

    Zu dem Thema gibt es wie gesagt ~1.000.000.000 Google Ergebnisse, aber ich wurd daraus nicht schlau
    (meine Versuche waren alle falsch) :(:( .

    Bitte um Hilfe...

    • Offizieller Beitrag

    Hallo,

    zeig doch einfach deine Versuche, dann kann dir evtl. auch sagen was falsch ist!

  • Hi,
    also ich würde mal die althergebrachte Variante mit dem Gleichsetzen beider Funktionen empfehlen.
    Kreisfunktion (aus dem Kopf, ist schon etwas länger her^^): x²+y²=1 bzw (x-xm)²+(y-ym)²=r²
    Geradengleichung: y=m*x+b
    m ist die Geradensteigung = (y2-y1)/(x2-x1)
    Gleichsetzen/Einsetzen der Funktionen führt zu einer quadratischen Gleichung, ergo 2 Ergebnisse. Eigentlich logisch, die Gerade schneidet den Kreis in 2 Punkten

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    2 Mal editiert, zuletzt von Andy (28. Dezember 2010 um 20:41)


  • und eine Grade die durch den Mittelpunkt des Kreises läuft.


    Dann sind die Fallunterscheidungen von Aspirinjunkie nicht nötig.

    Rechnet man das von hand aus ergibt sich dies aus der Lösung der Gleichung, fürs Skript hilft es aber vielleicht ( :?: ) wenn man die Fallunterscheidung dann weglassen kann.

    Einmal editiert, zuletzt von nuts (28. Dezember 2010 um 22:07)

  • Oh danke - hab ich überlesen dann ist richtig so - mein Fehler.
    Wenn es aber tatsächlich durch den Mittelpunkt des Kreises geht braucht man aber nicht so umständlich gleichsetzen sondern hat dort einen Spezialfall den man mit dem Satz des Pythagoras lösen kann (Hypothenuse = Radius in diesem Fall).
    Einfach mal aufzeichnen und 2 Dreieck reinmalen dann sieht man wie man es einfacher lösen kann.

  • Da diskutieren die Spezialisten hier im Forum über Spezialfälle, anstatt mal eine ne universelle
    _Schnittpunkt_Kreis_Gerade()-Funktion zu erstellen!
    Habt ihr heute noch keinem den Arm aus der Sonne gelegt? 8o

  • Hilfe zur Selbsthilfe ;)
    Nach Bernds berechtigter Anfrage kam bisher nix und solange will ich da nun auch noch warten da ich sonst halt immer zu schnell Code raushaue statt dem User wirklich zu helfen in dem er es nachher selbst erstellen kann anstatt fertige Kost zu kauen.

  • Hi,

    Zitat

    Nach Bernds berechtigter Anfrage kam bisher nix und solange will ich da nun auch noch warten da ich sonst halt immer zu schnell Code raushaue statt dem User wirklich zu helfen in dem er es nachher selbst erstellen kann anstatt fertige Kost zu kauen.

    genau wie du, hab ich natürlich auch schon eine Funktion gebastelt :thumbup: *man kennt doch seine Pappenheimer*
    UEZ müsste nur noch ne schöne grafische Anwendung hinstellen :whistling:

    [autoit]

    ;liefert in @extended die Anzahl der schnittpunkte und im array die koordinaten+schnittpunkte
    Func _Schnittpunkt_Kreis_Gerade($gx1, $gy1, $gx2, $gy2, $xm, $ym, $r) ;2 Punkte auf gerade, mittelpunkt, radius
    Dim $a[5] ;rückgabe x1,y1,x2,y2,anzahl schnittpunkte

    [/autoit]

    Rest gibts später :rofl:

  • So jetzt bin ich auch wieder da ;)

    Ich habe mir (so unglaublich das scheint) schon selbst vorher Gedanken gemacht und bin auf
    fast alles hier schon gekommen. Ich hab dann gedacht, ich machs mal mit dem Satz von Pytagoras;

    [autoit]


    $EndPunktX = 300
    $EndPunktY = 300
    $Radius = 200

    [/autoit][autoit][/autoit][autoit]

    $longc1 = Sqrt($EndPunktX^2 -$EndPunktY ^2)
    $longc1 = $longc1 - $Radius
    $alpha1 = Tan($m1)^-1
    $a1 = Cos($alpha1) * $longc1
    $b1 = Sin($alpha1) * $longc1
    $a1 = $EndPunktX - $a1
    $b1 = $EndPunktY - $b1

    [/autoit][autoit][/autoit][autoit]

    $SchittpunktX = $a1
    $SchnittpunktY = $b1

    [/autoit]

    Leider kriege ich komische Ergebnisse, vorallem wenn ich die Endpunkte verändere.

    • Was ist $EndPunkt? - der Mittelpunkt des Kreises?
    • Falls nicht - wo ist der Mittelpunkt?
    • Wo sind die Parameter für die Gerade? (Anstieg/Schnittpunkt mit Y-Achse etc.)


    Es sind defnitiv zu wenig Parameter um einen Kreis UND eine Gerade zu beschreiben.

  • AspirinJunkie

    $EndpunktX / Y ist der Enpunkt der Strecke (Der Startpunkt ist (0|$Height) $Height = 600) (Ich bin von einer Geraden ausgegangen die durch diese beiden Punkte läuft).
    Der Mittelpunkt der Kreises ist ebenfalls (0|$Height).
    Die Parameter der Strecke/ Geraden sind eigentlich unwichtig wenn man 2 Punkte auf der Geraden/Strecke kennt. Aber an anderer Stelle berechne ich sie so:

    [autoit]


    $x1=0
    $y1=$Height

    [/autoit][autoit][/autoit][autoit]

    $m1=($EndPunktY-$y1)/($EndPunktX-$x1)
    $b1=$EndPunktY-$m1*$EndPunktX

    [/autoit]

    Ich will ja auch garkeinen Kreis beschreiben. Der existiert nur theoretisch;

    Ich brauch nur Punkte die auf einer Kreisbahn liegen und eine Grade/Strecke schneiden.

  • Du brauchst als Basisdaten für den Vorhaben mindestens:

    1. Kreisradius
    2. Mittelpunkt des Kreises
    3. beliebiger zweiter Punkt auf der Geraden

    1 & 2 definieren den Kreis
    und über 2 & 3 lässt sich die Geradengleichung aufstellen (Punktsteigungsformel usw.)

  • Hi

    im Prinzip bräuchtest du nur alle Punkte des Kreises (mir klar dass es unendlich viele sind) bis auf eine gewisse Genauigkeit, dann hätteste ja alles was du für die Gerade brauchst.

    So gehts:

    Kreisformel:

    (x - mx)² + (y - my)² = r²

    jetzt nimmste eine Sekante die du vom untersten Punkt des Kreises (my - r) und die verschiebst du je nach dem wie genau du das haben willst Pixel für Pixel nach oben und rechnest dir einen der beiden Schnittpunkte aus (also z.B bei der pq-Formel immer nur + Wurzel und nicht - Wurzel) das machste solange bis du zum obersten Punkt des Kreises kommst (my + r). Und fertig biste... ^^

    mfg Redclaw

  • Wenn also Kreismittelpunkt = Geradenpunkt = (0;600) und $EndPunkt = 2. Geradenpunkt dann sind die Schnittpunkte aus einer Verhältnisgleichung zu berechnnen:

    Verhältnisrechnung
    [autoit]

    ;Geradenpunkt
    $EndX = 300
    $EndY = 300

    [/autoit] [autoit][/autoit] [autoit]

    ;Kreis
    $Radius = 200
    $Mx = 0
    $My = 600

    [/autoit] [autoit][/autoit] [autoit]

    ; Distanz zwischen Mitelpunkt und Endpunkt berechnen
    $sDist = Sqrt(($Mx - $EndX) ^ 2 + ($My - $EndY) ^ 2)

    [/autoit] [autoit][/autoit] [autoit]

    ; Koordinatendifferenz zum Mittelpunkt berechnen durch Verhältnis zwischen Distanz und Radius
    $dX = $Radius * (($EndX - $Mx) / $sDist)
    $dY = $Radius * (($EndY - $My) / $sDist)

    [/autoit] [autoit][/autoit] [autoit]

    ; Neue Koordinaten durch hinzuaddieren der Mittelpunktskoordinaten berechnen
    $SX1 = $Mx + $dX
    $SY1 = $My + $dY
    $SX2 = $Mx - $dX
    $SY2 = $My - $dY

    [/autoit] [autoit][/autoit] [autoit]

    ConsoleWrite("X1: " & $SX1 & @TAB & "Y1: " & $SY1 & @CRLF & "X2: " & $SX2 & @TAB & "Y2: " & $SY2 & @CRLF)

    [/autoit]

    Andy
    Nun können wir doch sicher auch unsere allgemeinen Lösungen posten - oder? ;) :

    Meine allgemeine Berechnung der Schnittpunkte
    [autoit]

    #include <Array.au3>

    [/autoit] [autoit][/autoit] [autoit]

    #region Sekantenfall
    ; Kreisparameter:
    Const $XM = 5
    Const $YM = 1
    Const $R = 3

    [/autoit] [autoit][/autoit] [autoit]

    ; Geradenparameter:
    Const $m = 0.75
    Const $n = 1
    #endregion Sekantenfall

    [/autoit] [autoit][/autoit] [autoit]

    $aT = Schnitt_Kreis_Gerade($XM, $YM, $R, $m, $n)
    MsgBox(0, "", "Es existiert " & $aT[0] & " Schnittpunkt[e].")
    _ArrayDisplay($aT)

    [/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION# ======================================================================================
    ; Name ..........: Schnitt_Kreis_Gerade()
    ; Description ...: Gibt ein Array mit der Anzahl und den Koordinaten der Schnittpunkte zwischen Kreis und Gerade zurück
    ; Syntax ........: Schnitt_Kreis_Gerade(Const $XM, Const $YM, Const $R, Const $m, Const $n [, Const $FLT_EPSILON])
    ; Parameters ....: $XM - X-Koordinate Kreismittelpunkt
    ; $YM - Y-Koordinate Kreismittelpunkt
    ; $R - Radius Kreis
    ; $m - Anstieg der Gerade
    ; $n - Schnittpunkt der Y-Achse mit der Geraden
    ; $FLT_EPSILON - optionale Toleranz um eventuelle binäre Rundungsfehler auszugleichen damit Sekantenfall erreicht werden kann
    ; Return values .: Success: Array[0]=Anzahl Schnittpunkte, dann [Xs1,Ys1 [,Xs2,Ys2]]
    ; Failure: Ich mache keine Fehler
    ; Author ........: AspirinJunkie
    ; Related .......: Distance_Point_Line
    ; Example .......: Yes
    ; #include <Array.au3>
    ; ; Kreisparameter:
    ; Const $XM = 4
    ; Const $YM = 3
    ; Const $R = 5
    ; ; Geradenparameter:
    ; Const $m = -1.3
    ; Const $n = 10
    ; $aT = Schnitt_Kreis_Gerade($XM, $YM, $R, $m, $n)
    ; _ArrayDisplay($aT)
    ; =================================================================================================
    Func Schnitt_Kreis_Gerade(Const $XM, Const $YM, Const $R, Const $m, Const $n, Const $FLT_EPSILON = 1e-16)
    Local Const $iD = Distance_Point_Line($XM, $YM, $m, $n) ; Abstand Mittelpunkt-Gerade

    [/autoit] [autoit][/autoit] [autoit]

    If Abs($iD - $R) <= $FLT_EPSILON Then ; Tangente: 1 Schnittpunkt da Gerade Kreis nur berührt
    Local Const $x = (Sqrt(($R ^ 2 - $XM ^ 2) * $m ^ 2 - 2 * $XM * (-$YM + $n) * $m + ($n - $YM + $R) * (-$n + $YM + $R)) + ($YM - $n) * $m + $XM) / (1 + $m ^ 2)

    [/autoit] [autoit][/autoit] [autoit]

    Local $aRet[3] = [1, _
    $x, $m * $x + $n]

    [/autoit] [autoit][/autoit] [autoit]

    Return $aRet

    [/autoit] [autoit][/autoit] [autoit]

    ElseIf $iD < $R Then ; Sekante: 2 Schnittpunkte da Gerade durch Kreis
    Local Const $fTemp1 = Sqrt(($R ^ 2 - $XM ^ 2) * $m ^ 2 - 2 * $XM * (-$YM + $n) * $m + ($n - $YM + $R) * (-$n + $YM + $R))
    Local Const $fTemp2 = ($YM - $n) * $m + $XM

    [/autoit] [autoit][/autoit] [autoit]

    Local Const $x1 = ($fTemp1 + $fTemp2) / (1 + $m ^ 2)
    Local Const $x2 = (-$fTemp1 + $fTemp2) / (1 + $m ^ 2)

    [/autoit] [autoit][/autoit] [autoit]

    Local $aRet[5] = [2, _
    $x1, $m * $x1 + $n, _
    $x2, $m * $x2 + $n]

    [/autoit] [autoit][/autoit] [autoit]

    Return $aRet

    [/autoit] [autoit][/autoit] [autoit]

    Else ; Passante: Kein Schnittpunkt da Gerade an Kreis vorbei geht
    Local $aRet[1] = [0]
    Return $aRet
    EndIf
    EndFunc ;==>Schnitt_Kreis_Gerade

    [/autoit] [autoit][/autoit] [autoit]

    ; #FUNCTION# ======================================================================================
    ; Name ..........: Distance_Point_Line()
    ; Description ...: Gibt den Abstand zwischen einem Punkt und einer Geraden an
    ; Syntax ........: Distance_Point_Line(Const $Xp, Const $Yp, Const $m, Const $n)
    ; Parameters ....: $Xp - X-Koordinate Punkt
    ; $Yp - Y-Koordinate Punkt
    ; $m - Anstieg der Gerade
    ; $n - Schnittpunkt der Y-Achse mit der Geraden
    ; Return values .: Success: Gibt Abstand zurück
    ; Failure: ?
    ; Author ........: AspirinJunkie
    ; =================================================================================================
    Func Distance_Point_Line(Const $Xp, Const $Yp, Const $m, Const $n)
    Return Abs(($Yp - $m * $Xp - $n) / Sqrt(1 + $m ^ 2))
    EndFunc ;==>Distance_Point_Line

    [/autoit]
  • abber sischäärr^^

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>
    $a = _Schnittpunkt_Kreis_Gerade(0, 6, 18, 12, 9, 7, 5)
    ConsoleWrite("Schnittpunkte = " & @extended & @CRLF) ;### Debug Console
    _ArrayDisplay($a)

    [/autoit] [autoit][/autoit] [autoit]

    $a = _Schnittpunkt_Kreis_Gerade(4, 0, 4, 12, 9, 7, 5) ;senkrecht, tangente
    ConsoleWrite("Schnittpunkte = " & @extended & @CRLF) ;### Debug Console
    _ArrayDisplay($a)

    [/autoit] [autoit][/autoit] [autoit]

    $a = _Schnittpunkt_Kreis_Gerade(3, 0, 3, 12, 9, 7, 5) ;kein schnittpunkt
    ConsoleWrite("Schnittpunkte = " & @extended & @CRLF) ;### Debug Console
    _ArrayDisplay($a)

    [/autoit] [autoit][/autoit] [autoit]

    $a = _Schnittpunkt_Kreis_Gerade(1, 0, 3, 0, 9, 7, 5) ;kein schnittpunkt
    ConsoleWrite("Schnittpunkte = " & @extended & @CRLF) ;### Debug Console
    _ArrayDisplay($a)

    [/autoit] [autoit][/autoit] [autoit]

    $a = _Schnittpunkt_Kreis_Gerade(0, 2, 18, 2, 9, 7, 5) ;waagrecht, tangente
    ConsoleWrite("Schnittpunkte = " & @extended & @CRLF) ;### Debug Console
    _ArrayDisplay($a)

    [/autoit] [autoit][/autoit] [autoit]

    $a = _Schnittpunkt_Kreis_Gerade(9, 0, 9, 12, 9, 7, 5) ;senkrecht
    ConsoleWrite("Schnittpunkte = " & @extended & @CRLF) ;### Debug Console
    _ArrayDisplay($a)

    [/autoit] [autoit][/autoit] [autoit]

    $a = _Schnittpunkt_Kreis_Gerade(0, 7, 18, 7, 9, 7, 5) ;waagrecht
    ConsoleWrite("Schnittpunkte = " & @extended & @CRLF) ;### Debug Console
    _ArrayDisplay($a)

    [/autoit] [autoit][/autoit] [autoit]

    $a = _Schnittpunkt_Kreis_Gerade(0, 0, 1, 1, 0, 0, 1) ;einheitskreis, 45°gerade
    ConsoleWrite("Schnittpunkte = " & @extended & @CRLF) ;### Debug Console
    _ArrayDisplay($a)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ;liefert in @extended die Anzahl der schnittpunkte und im array die koordinaten+schnittpunkte
    ;wenn kein schnittpunkt, sind die Koordinaten LEER!
    Func _Schnittpunkt_Kreis_Gerade($gx1, $gy1, $gx2, $gy2, $xm, $ym, $r) ;2 Punkte auf gerade, mittelpunkt, radius
    Dim $a[5] ;x1,y1,x2,y2,schnittpunkte
    If ($gx2 - $gx1) = 0 Then ;senkrechte gerade, sonderfall da steigung unendlich
    $p = -2 * $ym ;pq-formel: y²+py+q=0
    $q = ($ym ^ 2 + ($gx1 - $xm) ^ 2 - $r ^ 2) ;Lösungen y1/2=-p/2+-sqrt(p^2/4-q)
    $s = $p ^ 2 / 4 - $q ;steht unter der wurzel
    If $s >= 0 Then ;wurzel >=0 reell
    $a[0] = $gx1 ;x1
    $a[2] = $gx1 ;x2=x1
    $a[1] = -$p / 2 + Sqrt($s) ;pq-formel liefert y1
    $a[3] = -$p / 2 - Sqrt($s) ;pq-formel liefert y2
    $a[4] = 2 ;angenommen 2 schnittpunkte
    If $a[1] = $a[2] Then $a[4] = 1 ;ein schnittpunkt, tangente
    Else ;wurzel<0
    $a[4] = 0 ;kein schnittpunkt
    EndIf
    Else ;steigung gerade nicht unendlich
    $m = ($gy2 - $gy1) / ($gx2 - $gx1) ;steigung
    $b = $gy1 - $m * $gx1 ;y-achsenabschitt
    $p = (2 * $m * ($b - $ym) - 2 * $xm) / (1 + $m ^ 2)
    $q = (($b - $ym) ^ 2 - $r ^ 2 + $xm ^ 2) / (1 + $m ^ 2)
    $s = $p ^ 2 / 4 - $q ;$x12=-$p/2+-sqrt($s)

    [/autoit] [autoit][/autoit] [autoit]

    If $s >= 0 Then ;wurzel >0 = reell
    $a[0] = -$p / 2 + Sqrt($s) ;pq-formel liefert x1
    $a[2] = -$p / 2 - Sqrt($s) ;pq-formel liefert x2
    $a[1] = $m * $a[0] + $b ;y1=m*x1+b
    $a[3] = $m * $a[2] + $b ;y2=m*x2+b
    $a[4] = 2 ;angenommen 2 schnittpunkte
    If $a[0] = $a[2] Then $a[4] = 1 ;ein schnittpunkt, tangente
    Else ;wurzel <0
    $a[4] = 0 ;kein schnittpunkt
    EndIf
    EndIf
    Return SetError(0, $a[4], $a) ;@error, @extended, array
    EndFunc ;==>_Schnittpunkt_Kreis_Gerade

    [/autoit]


    Du Fuchs! :thumbup:
    Lässt den Fall m=unendlich => Gerade parallel zur y-Achse einfach wegfallen ^^
    Aber dein udf-Header ist wirklich viel schöner als meiner ;(

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    Einmal editiert, zuletzt von Andy (30. Dezember 2010 um 15:05)

  • Lässt den Fall m=unendlich => Gerade parallel zur y-Achse einfach wegfallen ^^


    Wenn du es hinbekommst diesen Fall in der analytischen Form y=mx+n numerisch (!) auszudrücken kannst du diesen Fall auch mit meiner Funktion behandeln.... ;)
    Ernsthaft: Meine Eingabeparameter basieren auf der Linearen Funktionsform (y=mx+n). Dort gibt es den Fall das m = unendlich ist nicht da in dem Fall einem x mehrere Funktionswerte zugewiesen werden was der Definition einer Funktion widerspricht.
    Bei dir jedoch ist dieser Fall möglich da du ja als Parameter die 2-Punkt-Form verwendest.
    Also brauch ich den Fall gar nicht abfangen da er durch die Auswahl meiner Parameter gar nicht auftreten kann :P

    Aber dein udf-Header ist wirklich viel schöner als meiner

    Hab ich mit >>DescribeIt<< von Seuobou (oder so ähnlich - komme mit der Vokalfolge nicht klar ;) ) gemacht.
    Schönes Tool