Lösung für Problem der Kreisausgleichung gesucht

  • VB.NET

Es gibt 31 Antworten in diesem Thema. Der letzte Beitrag () ist von Yanbel.

    Lösung für Problem der Kreisausgleichung gesucht

    Moin!

    ich habe eine Vielzahl von 2D-Punkten und möchte einen bestfit Kreis durch diese legen.

    Das Ganze wird wohl unter dem Begriff der "Kreisausgleichung" geführt.

    people.inf.ethz.ch/arbenz/MatlabKurs/node79.html

    Da dort irgendwie mit Vektoren gearbeitet wird verlassen sie mich an dieser Stelle irgendwie.

    Kann mir jemand bei dem Problem weiterhelfen oder hat gar eine Lösung?

    Gruß Jan
    Kann sein dass ich nicht richtig liege... ich würde folgendes versuchen:

    - Alle Punkte erstmal in eine Liste.
    - In x und y richtung jeweils den kleinsten und größten Wert nehmen, diese voneinander abziehen, durch 2 teilen und das minimum als offset wieder aufaddieren um den mittelpunkt zu erhalten.
    - für jeden punkte den radius ausrechnen wie in der ersten formel aus Deinem Link gezeigt.

    Man könnte dann evtl die ganze Kreise mal zeichnen um zu sehen was da passiert...

    Gibt aber vermutlich noch hilfreichere Kommentare... bin gespannt!
    Der Beitrag wurde aus 100% wiederverwendbaren Elektronen erstellt!
    @jan99 Ich würde den Schwerpunkt der Koordinaten als Startpunkt der Iteration verwenden.
    Das setzt allerdings voraus, dass die Umfangs-Punkte gleichmäßig verteilt sind.
    Wenn nicht, kannst Du beliebige Sekanten bilden, und der gemittelte Schnittpunkt der
    Mittelsenkrechten davon wäre in diesem Fall der Startpunkt der Iteration.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    jan99 schrieb:

    kann man das irgendwie in ein vb.net-Projekt einbinden?
    Ja, ist aber eine Fleißarbeit.
    Gugst Du Austausch von Daten zwischen einer VB.NET-exe und einer C-DLL, 32 und 64 Bit
    Da Du die Quellen der DLL hast, kannst Du ein .NET-GUI-Projekt dazupacken, dieses als Startprojekt und los.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @jan99 OK, ich hab das Projekt versucht zu öffnen - lass es sein.
    Möglicherweise kann man den Code des Projekts best-fit nach C# übertragen und von dort nach VB.NET übersetzen, das wäre was für Sportler.
    ====
    Und Du brauchst noch den hier:
    boost.org/doc/libs/1_65_1/libs/numeric/ublas/doc/index.html
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @jan99 Du hast doch in Deinem Post #1 einen schnuckeligen Lösungsansatz.
    Musst Du nure in Code gießen und feddich. :thumbsup:
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Moin!

    das aus meiner Sicht als Vermesser nur als ein Näherungsverfahren zu betrachten.

    Das Verfahren würde schon nicht funktionieren, wenn die Punkte nicht regelmäßig auf dem Kreis verteilt sind.

    Betrachte hierzu nur einmal eine Anordnung, die einer Mondsichel beschreiben.

    Abschließend - sonst würde man nicht den Aufwand wie andere Bibliotheken machen.

    Jan

    jan99 schrieb:

    Das Verfahren würde schon nicht funktionieren, wenn die Punkte nicht regelmäßig auf dem Kreis verteilt sind.
    Doch, das funktioniert. mit dem in Post #3 beschriebenen Start-Betrachtungen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo @jan99

    Professor Nikolai Chernov hat im Jahre 2012 seinen KreisFitter veröffentlicht.
    people.cas.uab.edu/~mosya/cl/CPPcircle.html

    Ist halt in C++ geschrieben und müsse man umschreiben. Unteranderem gibt es auf dieser Homepage viele Vergleichstests mit anderen bekannten Kreisfit-Algos.

    Vielleicht mal reinschauen.

    Freundliche Grüsse

    exc-jdbi
    Moin!

    ich habe auch noch ein Beispiel gefunden unter people.inf.ethz.ch/arbenz/MatlabKurs/node79.html

    Dort ist sogar ein Beispielcode für Matlab.

    Vielleicht kennt sich jemand von Euch mit Matlab aus und kann mir sagen was dieser Code macht. Dann baue ich den in vb.net auch gerne nach.

    Gruß Jan
    @jan99 Das ist der Link aus Deinem Post #1.
    Mal ne ganz allgemeine Frage:
    Sollst Du das Problem auf Arbeit lösen, hast aber keine Ahnung wie?
    Sollen wir das Problem für Dich lösen, Du präsentierst Deinem Chef unsere Lösung als Deine und bekommst ne Gehaltserhöhung?
    Oder warum bist Du so heiß auf ne Lösung?
    ====
    Wenn Du den C++-Code verstehst und Du die fehlenden Matrizen-Operationen aus deren Namen generieren kannst, ist Dein Problem gelöst.
    Das ist sicherer als MatLab, wo ebendiese Prozeduren auch nicht untersetzt sind.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    RodFromGermany schrieb:


    Sollst Du das Problem auf Arbeit lösen, hast aber keine Ahnung wie?
    Sollen wir das Problem für Dich lösen, Du präsentierst Deinem Chef unsere Lösung als Deine und bekommst ne Gehaltserhöhung?


    Hallo Rod,

    das mit der Gehaltserhöhung wäre zum einen ausverschämt und nicht mein Character.

    Ich arbeite bei einem öffentlichen Entsorger und da ist das mit Gehaltserhöhungen nicht so einfach. Da muss man die Zeit abwarten oder einen sehr langen Weg gehen mit entsprechenden Dokumentationen.

    Ich bin gelernter Vermesser und weiß das es einen "genauen" Weg und den Näherungsweg. Hätte das gerne genauer gelöst um es auch anderweitig vielleicht Nutzen zu können.

    In den Formeln sind immer Vektoren angegeben. Das hatte ich einmal vor 30 Jahren im Studium. Schon lange die Anwendung vergessen.

    Habe sogar unsere Jungingenieure gefragt und die haben sich am Kopf gekratzt.

    Hatte gedacht, dass Vektorrechnung in anderen Gebieten verbreiteter sind und andere das vielleicht "mal eben" wissen anzuwenden.

    Dann werde ich den anderen Weg beschreiben.

    Dennoch Dank an Euch.

    Gruß Jan

    jan99 schrieb:

    ...und andere das vielleicht "mal eben" wissen anzuwenden...

    nein, ich glaub nicht, das man das mal eben weiss.
    Von den hier bisher aufgetretenen Postern jedenfalls wohl keiner (mich eingeschlossen).
    (Das kann man übrigens auch einfach mal ehrlich zugeben, findich)

    Wie dem auch sei - wenn ich an solche Probleme komme, denke ich an @Higlav - der schüttelte hin und wieder son Mathe-Kram aussm Ärmel.
    Aber der ist eine eher unstete Erscheinung hier bei VBP.
    Das mit der Gehaltserhöhung war ein Scherz. :D

    jan99 schrieb:

    Ich bin gelernter Vermesser und weiß das es einen "genauen" Weg und den Näherungsweg.
    Es gibt keinen "exakten" Weg wie bei Gerade, Parabel und Co.
    Beim Kreis weiß ich nur von einem Näherungsweg, und wenn man da ein paar Runden dreht, wird das Ergebnis beliebig genau, sofern die Startbedingungen hinreichend gut sind.
    Und für diesen Weg haben wir Dir gute Tipps gegeben.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hey,
    vielleicht etwas spät aber ich war im Urlaub. Probier das, vielleicht hilft es dir.

    Komplette Form

    VB.NET-Quellcode

    1. Option Strict On
    2. Imports System.Drawing.Drawing2D
    3. Public Class ShowRoom
    4. Private gPathPoints As New GraphicsPath
    5. Private gPathCircle As New GraphicsPath
    6. Private Sub ShowRoom_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    7. Dim Points As New List(Of Point)
    8. Points.Add(New Point(7, 10))
    9. Points.Add(New Point(33, 3))
    10. Points.Add(New Point(75, 37))
    11. Points.Add(New Point(64, 61))
    12. Points.Add(New Point(44, 80))
    13. Points.Add(New Point(3, 75))
    14. Points.Add(New Point(-11, 37))
    15. CalcCircle(Points)
    16. End Sub
    17. Private Sub ShowRoom_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    18. With e.Graphics
    19. .SmoothingMode = SmoothingMode.HighQuality
    20. .DrawPath(New Pen(Color.Red, 1), gPathPoints)
    21. .DrawPath(New Pen(Color.SteelBlue, 1), gPathCircle)
    22. End With
    23. End Sub
    24. Private Sub CalcCircle(Coords As List(Of Point))
    25. 'Ermittle Max- und Minwerte auf x- und y-Achse
    26. Dim xMin As Single = Coords.Select(Function(n) n.X).Min
    27. Dim xMax As Single = Coords.Select(Function(n) n.X).Max
    28. Dim yMin As Single = Coords.Select(Function(n) n.Y).Min
    29. Dim yMax As Single = Coords.Select(Function(n) n.Y).Max
    30. 'Ermittle Abstände
    31. Dim dx As Single = (xMax - xMin) / 10
    32. Dim dy As Single = (yMax - yMin) / 10
    33. 'Ermittle Randpunkte
    34. Dim AxisLeft As Single = xMin - dx
    35. Dim AxisRight As Single = xMax + dx
    36. Dim AxisTop As Single = xMin - dx
    37. Dim AxisBottom As Single = xMax + dx
    38. 'Anpassung der Randpunkte auf Form nach oben links
    39. AxisRight -= AxisLeft
    40. AxisBottom -= AxisTop
    41. For Each elem In Coords
    42. elem.X -= CInt(AxisLeft)
    43. elem.Y -= CInt(AxisTop)
    44. gPathPoints.AddArc(New Rectangle(elem.X - 1, elem.Y - 1, 2, 2), 0, 360)
    45. Next
    46. AxisLeft = 0
    47. AxisTop = 0
    48. 'Ermittle Mittelpunkt
    49. Dim MidX As Single = AxisRight / 2
    50. Dim MidY As Single = AxisBottom / 2 + dy
    51. 'Ermittle Radius
    52. Dim Radius As Double = Coords.Select(Function(n) Math.Sqrt(Math.Pow((n.X - MidX), 2) + Math.Pow((n.Y - MidY), 2))).Average
    53. 'Erstelle Kreis
    54. gPathCircle = New GraphicsPath
    55. gPathCircle.AddArc(New Rectangle(CInt(MidX - Radius), CInt(MidY - Radius), CInt(Radius * 2), CInt(Radius * 2)), 0, 360)
    56. 'Zeichne Form neu
    57. Invalidate()
    58. End Sub
    59. End Class
    Bilder
    • Kreisausgleichsproblem.PNG

      3,22 kB, 279×165, 337 mal angesehen


    Ein Computer wird das tun, was du programmierst - nicht das, was du willst.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Yanbel“ ()

    @Yanbel Wenn das das Bild Deiner Lösung ist:
    Allein vom Hinsehen sage ich: Das ist eine schlechte Lösung.
    5 Punkte liegen innerhalb, nur einer außerhalb.
    Das sollte bei einer ordentlichen Lösung gleich verteilt sein.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich habs auch bemerkt und arbeite nachher nochmal eine bessere Lösung aus. Das Problem ist hier die Mittelpunktbestimmung. Mein neuer Ansatz ist aus allen vorhandenen Punkten Dreierpaare bilden um dann aus den resultierenden Dreiecken die Umkreismittelpunkte zu errechnen. Aus allen Umkreismittelpunkten bilde ich dann einen Durchschnittsmittelpunkt und errechne aus diesem den Durchschnittsradius zu jedem Punkt. Die Berechnung sollte ein deutlich genaueres Ergbebnis liefern. Ich bin mir bei meiner Abbildung allerdings auch nicht sicher, ob dass nicht zum Teil auf Rundungsungenauigkeiten zurückzuführen ist. Für den neuen Ansatz dauert es noch ein wenig, bis ich die Berechnungen in Code gefasst habe. Muss ich machen sobald ich zuhause bin.


    Ein Computer wird das tun, was du programmierst - nicht das, was du willst.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Yanbel“ ()