Kreis durch 3 Punkte Berechnungsmethode?

Neue Frage »

LinusK Auf diesen Beitrag antworten »
Kreis durch 3 Punkte Berechnungsmethode?
Hallo,
bin ganz neu hier und hoffe niemanden hier mit dummen zu verägern.
Der Anlass meiner Anfrage ist die Beschreibung einer mathematischen Methosde zur Bestimmung des Kreises durch drei Punkte.
Meine Mathekenntnisse reicht nicht aus,um zu verstehen was genau in dieser Methode gemacht wird.
Mir würden ein paar Stichworte reichen, um selber weiter nach Antworten zu suchen.
Der Author des Artikels antwortet auf meine Anfragen leider nicht.

Üblicherweise macht man das über den Schnittpunkt der Mittelsenkrechten der Seiten aber es geht auch über die Eigenschaft, dass die Strecken von den jeweiligen Punkten zum gemeinsamen Mittelpunkt gleich sind.
Vielleicht wird das hier auch verwendet, nur sehe ich die Zusammenhänge und Regeln nicht.
Wie gesagt, nur ein paar Stichworte als Hilfe zur Selbsthilfe smile

An Verständnis mangelt es mir bereits am Anfang:

Zitat:
# Calculate distances between points:.

c, a und b sind doch keine Seitenlängen sondern die Quadrate der Seiten
Dieser Umstand wird zwar weiter unten auf der Webseite erwahnt, aber nirgends erklärt.

Richtig problematisch wird es in den Zeilen :
Zitat:
# Calculate the cross-product

Kreuzprodukt von 3 Flächen ???
Was soll "s" sein?
Semiperimeter ist es wohl nicht, vielleicht etwas von Herons Formel?

Was hier passiert ist mir völlig verschlossen:
Zitat:
# Calculate the central coordinate of the circle


Es ist zwar Pythoncode, aber so einfach, dass ich denke er kann als MAthematik akzeptiert werden.

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
import numpy as np
import matplotlib.pyplot as plt

p1 = np.array([3, 5])
p2 = np.array([5, 6])
p3 = np.array([8, 2])
pts = np.dstack([p1, p2, p3, p1])[0]

x1, y1 = p1[0], p1[1]
x2, y2 = p2[0], p2[1]
x3, y3 = p3[0], p3[1]

# Calculate distances between points
c = (x1 - x2)**2 + (y1 - y2)**2
a = (x2 - x3)**2 + (y2 - y3)**2
b = (x3 - x1)**2 + (y3 - y1)**2

# Calculate the cross-product
s = 2 * (a * b + b * c + c * a) - (a**2 + b**2 + c**2)

# Calculate the central coordinate of the circle
mx = (a * (b + c - a) * x1 + b * (c + a - b) * x2 + c * (a + b - c) * x3) / s
my = (a * (b + c - a) * y1 + b * (c + a - b) * y2 + c * (a + b - c) * y3) / s

# Calculate the radius of the circle
ar = a**0.5
br = b**0.5
cr = c**0.5
r = ar * br * cr / ((ar + br + cr) * (-ar + br + cr) * (ar - br + cr) * (ar + br - cr))**0.5


print("Central coordinate (x, y) and radius of the circle:")
print("cx={:>.3f}".format(mx), "cy={:>.3f}".format(my), "cr={:>.3f}".format(r)    )

# cx=5.227 cy=3.045 cr=2.963

Ich darf den link zur Quelle hier nicht angeben (?)
danke und Gruß
Linus

[attach]58047[/attach]

Der folgende code erzeugt eine Graphik.
code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
# draw
fig, axes = plt.subplots()
# draw points
plt.scatter(  pts[0], pts[1], color = 'red')

# connect the points
plt.plot(pts[0], pts[1])
plt.plot(pts[0], pts[1])

#draw centerpoint
plt.scatter(mx, my, color='green')

# connect centerpoint with outer points
x1 = np.array([mx, p1[0], mx, p2[0],mx,p3[0]])
y1 = np.array([my, p1[1], my, p2[1],my, p3[1]])
plt.plot(x1, y1, color='green')

# draw the circle
theta = np.linspace( 0 , 2 * np.pi , 150 )
a = r * np.cos( theta )+ mx
b = r * np.sin( theta )+ my

#draw Location vector:
x1 = np.array([0, mx ])
y1 = np.array([0, my ])
plt.plot(x1, y1, color='black')

# axes.plot( a, b )
axes.set_aspect( 1 )
plt.plot( a, b )
plt.xlim(-1, 10)
plt.ylim(-1, 10)
plt.grid()
plt.show()
HAL 9000 Auf diesen Beitrag antworten »

Das im Pythoncode entspricht gemäß der Heronschen Flächenformel dem Wert , wobei die Dreiecksfläche ist.

Ganz zum Schluss wird die Formel genutzt, was man nach den vorberechneten Werten auch kürzer mit

r = ar * br * cr / s**0.5

hätte erledigen können...


P.S.: Die Bezeichner im Python-Code sind beschissen gewählt:

Statt a,b,c wäre (der Quadrate wegen) a2,b2,c2 oder aq,bq,cq angemessen gewesen, dann hätte man auch nicht ar,br,cr für die eigentlichen Seitenlängen wählen müssen. Genauso ist obiges s total daneben, da im Kontext von Dreiecksberechnungen dieses Symbol nicht für , sondern üblicherweise für steht. Solche seltsamen Bezeichnerwahlen machen den Code nur unnötig schwer lesbar. unglücklich
LinusK Auf diesen Beitrag antworten »

Hallo HAL
vielen herzlichen Dank!
das muss ich erstmal 'verdauen',
aber die Antwort sieht aus wie ich sie mir erhofft habe.

Auch waren meine ersten Anluafstationen mit Semiperimeter
und Heron nicht völlig daneben

Du hast völlig Recht betreffs der Variablennamen.
Die haben mich auch gestört den Sachverhalt zu verstehen.

Traurig ist auch, dass die Quelle ein online Mathetutorial ist.
Der Pythoncode ist unverändert, sodass google die Seite
anhand einiger markanter Stichworte finden sollt
Gruß Linus
HAL 9000 Auf diesen Beitrag antworten »

Was die Mittelpunktkoordinaten betrifft: Ja, die kann man als Schnittpunkt zweier Mittelsenkrechten herleiten. Das wurde natürlich schon oft getan und die Ergebnisse abgelegt, z.B. hier:

Die dort angegebenen trilinearen Koordinaten bedeuten für den Umkreismittelpunkt über die baryzentrischen Koordinaten die Ortsvektordarstellung , eingesetzt

,

die man ja im Quellcode in den Zeilen 22/23 auch erkennen kann. Und tatsächlich ist via



der Zusammenhang zur Heronschen Formel da.
LinusK Auf diesen Beitrag antworten »

vielen Dank für Deine Mühe
Dies ist eine perfekte Antwort
HAL 9000 Auf diesen Beitrag antworten »

Als summarisches Ergebnis meiner Anmerkungen würde ich die Zeilen 14-29 ersetzen durch

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
aq = (x2 - x3)**2 + (y2 - y3)**2
bq = (x3 - x1)**2 + (y3 - y1)**2
cq = (x1 - x2)**2 + (y1 - y2)**2

# Calculate the barycentric coordinates of the circle center
bar_a = aq * (bq + cq - aq)
bar_b = bq * (cq + aq - bq)
bar_c = cq * (aq + bq - cq)
bar_sum = bar_a + bar_b + bar_c

# Calculate the central coordinate of the circle
mx = bar_a * x1 + bar_b * x2 + bar_c * x3) / bar_sum
my = bar_a * y1 + bar_b * y2 + bar_c * y3) / bar_sum

# Calculate the radius of the circle
r = (aq * bq * cq / bar_sum)**0.5
Ich weiß, in Python spielt es nicht so die Rolle, aber ich denke immer von C/C++ her, da würde die Reduzierung von vier auf nur eine Wurzelziehung einen ordentlichen Geschwindigkeitsgewinn bringen.

P.S.: Genau genommen muss noch eine Fehlerbehandlung rein für den Fall, dass die drei Punkte kollinear sind. Von numerischen Effekten mal abgesehen ist das genau dann der Fall, wenn bar_sum = 0 ist.
 
 
LinusK Auf diesen Beitrag antworten »

HAL,
kurz, übersichtlich und klar
"Baryzentrische Koordinaten" bei Wikipedia, prima Stichwort, danke


Von anderer Seite bekam ich noch folgenden Hinweis
(so wie er ist, ohne jegliche Anmerkung, vermutlich von einem Lehrer smile

Jetzt versuche ich mich in der 'Cramerschen Regel' & friends.
Falls ich damit ein brauchbares Ergebnis finde, berichte ich hier.
Falls es jemand schon weiss - sehr gerne

=
=0

In einer Zeile wäre schöner, aber ich kann auch nicht alles auf einmal lernen.
Gruß Linus
LinusK Auf diesen Beitrag antworten »

Die '117' in der vorangegangenen Matrix ist falsch, es muss heissen '68'

Dann habe ich folgendes mit der Matrix versucht:

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
#      3   5   1 |  34
#      5   6   1 |  61
#      8   2   1 |  68
# 

import numpy as np
from numpy import linalg as LA

x = np.array([ 3, 5, 8])
y = np.array([ 5, 6, 2])
z = np.array([ 1, 1, 1])
t = np.array([ 34, 61, 68])

# Cramersche Regel
M = np.stack( [x, y, z], axis=1)
Mx = np.stack( [t, y, z], axis=1)
My = np.stack( [x, t, z], axis=1)
Mz = np.stack( [x, y, t], axis=1)

D  = LA.det(M)      #  -11.000000000000002 
Dx = LA.det(Mx)     # -115.00000000000001
Dy = LA.det(My)     #  -66.99999999999997 
Dz = LA.det(Mz)     #  306.0 

x = Dx/D      #  10.454545454545455 
y = Dy/D      #   6.090909090909087 
z = Dz/D      # -27.818181818181813

print( x/2, y/2, z)
# 5.2272727272727275 3.0454545454545436 -27.818181818181813

print((np.sqrt(abs(z)/np.pi)))       # 2.9757019824548037


# other methods result, out:
# r=  2.9632738205466587 center_x=  5.2272727272727275 center_y= 3.0454545454545454
# cx=5.227 cy=3.045 cr=2.963


Die Ergebnisse für die Mittelpunktskoordinaten scheinen zu stimmen, obwohl ich nicht weiss woher die Halbierung in codezeile 29 kommt.

Der Wert für den Radius ist vermutlich falsch, aber nah dran.
Ausgegangen bin ich davon, dass es wegen der z Achse (Kreuzprodukt) zu einer Fläche gekommen ist und sich aus dieser Kreisfläche der Radius berechnen lässt.
Was ich da gemacht habe ist eher trial&error anstatt Mathematik, aber vielleicht hat jemand weiterführende Hinweise.
Gruß Linus
HAL 9000 Auf diesen Beitrag antworten »

Ich weiß nicht genau, was du mit den letzten Beiträgen bezweckst:

Gefällt dir dein ursprünglicher Code (bzw. mit meinen marginalen Vereinfachungen) nicht, oder warum sonst ziehst du das ganze nochmal neu auf? verwirrt
LinusK Auf diesen Beitrag antworten »

Hallo HAL,
es ist gut, dass Du Dich meldest, obwohl oder gerade weil mein Beitrag anscheinend nervt.
Dies war nicht meine Absicht, aber ich sehe den sachlichen Grund für Deinen Einwand nicht wirklich.

Ist es wirklich das Gleiche nochmal ?

Deine vorangegangenen 'marginalen Vereinfachungen' haben mir sehr gefallen und ich habe dies auch überschwenglich zum Ausdruck gebracht.

Noch besser hat mir aber mein ursprünglicher Ansatz gefallen, den ich hier gar nicht erwähnt habe, weil vermutlich bei allen hier geläufig.
Da habe ich einfach den Schnittpunkt der Mittelsenkrechten auf zwei Schenkeln des Dreiecks bestimmt - fertig.

Eine weitere Methode lief über den Satz vo Heron, was Du dann klarer dargestellt hast.

Noch einen aneren Ansatz habe ich in der Lösung der Matirx vermutet, aber es scheint die Sache mit den Mittelsenkrechten wie obnen zu sein - irgendwie (?).

HAL, ich bin in der komfortablen Situation, dass Matura und Studium (nicht Mathe) schon lange zurück liegen und ich mir leisten kann, derartigen Aufgaben auf den Grund zu gehen und nicht mehr nur die Lösung rezitieren muss.

Wie formuliert man das Problem und die Frage ?
Welche sind die Standardmethoden und welche alternativen gibt es ?
Mit welcher Art Überlegugngen nähere ich mich dem Problem ?
Diese Überlegungen und das ständige Dazulernen im Umfeld des Problems ist das was mir Freude macht, die Lösung ist dann nur das Sahnehäubchen.

Falls diese Vorgehen nicht zum Forum passt, dann löscht bitte meinen Beitrag.
Falls er sich mit Hochschulmathe/ Algebra in der falschen Rubrik befindet, dann bitte ich ihn entsprechend zu verschieben.

Wenn das Problem für Dich ein totgerittener Gaul ist, dann sei es so.
Solange ich nicht verstanden habe, was bei der Lösung der Matrix vor sich geht, lebt der Gaul für mich noch.

Wie gesagt, falls dies nicht der richtig Ort ist ... ich will mich micht aufdrängen.

Gruß Linus
HAL 9000 Auf diesen Beitrag antworten »

Ok, dann habe ich deine Intentionen missverstanden: Ich hatte gedacht, dass du nur deinen Python-Code zur Bestimmung von Umkreismittelpunkt und -radius verstehen willst. Stattdessen scheinst du eine Vielzahl alternativer Möglichkeiten zu deren Bestimmung durchtesten zu wollen. verwirrt


Seltsam ist deine Radiusberechnung np.sqrt(abs(z)/np.pi) - wo Konstante hier herkommt weiß der Himmel. Erstaunt1

Laut https://de.wikipedia.org/wiki/Umkreis#Koordinaten lautet die Formel stattdessen np.sqrt((x**2 + y**2)/4 + z).

Oder gleich so:

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
import numpy as np
from numpy import linalg as LA

x = np.array([ 3, 5, 8])
y = np.array([ 5, 6, 2])
z = np.array([ 1, 1, 1])
t = np.array([ x[0]**2+y[0]**2, x[1]**2+y[1]**2, x[2]**2+y[2]**2])

# Cramersche Regel
M = np.stack( [x, y, z], axis=1)
Mx = np.stack( [t, y, z], axis=1)
My = np.stack( [x, t, z], axis=1)
Mz = np.stack( [x, y, t], axis=1)

D  = LA.det(M)      #  -11.000000000000002 
Dx = LA.det(Mx)     # -115.00000000000001
Dy = LA.det(My)     #  -66.99999999999997 
Dz = LA.det(Mz)     #  306.0 

x = Dx/(2*D)
y = Dy/(2*D)
z = Dz/D      # -27.818181818181813
r = np.sqrt(x**2 + y**2 + z)

print( x, y, r)
# 5.2272727272727275 3.0454545454545436 2.9632738205466578
LinusK Auf diesen Beitrag antworten »

Hallo HAL,
freut mich, dass wir das klären konnten.
Zukünftig formuliere ich meine Intension gleich mit der Frage.

Der python code dient nur der klaren Darstellung solange ich noch kein Latex/ Markdown verwende.
Programmierprobleme diskutiere ich in anderen Foren. (StackExchange, GitHub & friends)
Ausserdem lassen sich so formale Fehler finden und Änderungen schnell austesten.

Longieren wir den Gaul auf dem Kreis noch eine Runde zum Auslaufen.

Ffolgende Überlegungen zur Matrix



Die Spalten 'x', 'y' enthalten die drei Punkte.
Die Spalte 'x²+ y²' sagen es handelt sich um einne Kreis.
Die Spalte 'z' ist für Orthogonalität erforderlich.
Das Ergebnis "0" deute auf Schnittpunkte hin.
Im Grunde alles dabei was nötig ist.

Die Lösung für x und y ist nach Halbierung der Mittelpunkt.
Es fehlt also nur noch der Radius.

Mein Gedanke war, 'z' könnte die fehlende Information zum Radius in From der Fläche des Kreises enthalten.

Falls dem so wäre ist:

Radius r = sqrt(A/pi), da r² * pi = A

Das 'abs' (Betrag()) brauche ich da mein z negativ ist und numpy somit beim Wurzelziehen meckert solange ich nicht in complex weiter machen möchte.

Alles nur Vermutungen und vermutlich auch falsch, aber eben sehr nahe dran.
Mit anderen Punkten hat sich schnell gezeigt, dass dieses 'nahe dran' nur zufällig und die ganze Vermutung falsch ist.

Jetzt kümmere ich mich um Deine Gleichungen, Codezeile[20-23]

x = Dx/(2*D)
y = Dy/(2*D)
z = Dz/D # -27.818181818181813
r = np.sqrt(x**2 + y**2 + z)

genau auf solche Impulse habe ich gehofft.
danke und Gruß Linus
Neue Frage »
Antworten »



Verwandte Themen

Die Beliebtesten »
Die Größten »
Die Neuesten »