Häufung von Punkten herausfinden.

  • hi
    ich habe xx verschiedene punkte gegeben und möchte herausfinden an welcher stelle die punkte am nähesten beieinander liegen und x und y coordinaten eines punktes in der mitte dieses haufens ausgeben.

    hier im beispiel wäre das natürlich im 4ten quadranten.
    [Blockierte Grafik: http://img12.imageshack.us/img12/1201/coord.jpg]

    die positionen der punkte liegen mir jeweils in arrays vor

    [autoit]

    Func bunch()
    Local $ArrayX[1]
    Local $ArrayY[1]
    Do
    _ArrayAdd ($ArrayX, GetXCoord())
    _ArrayAdd ($ArrayY, GetYCoord())
    Until Finish() == 1
    EndFunc

    [/autoit]

    UBound ($ArrayX) ist natürlich immer gleich UBound ($ArrayY)
    die arrays können bei jeder neuen ausführung der func unterschiedlich lang sein.

    im moment hab ich noch keine idee wie ich mein problem lösen könnte, ich hoffe man kann mir hier helfen :)

    mfg
    qwertz

    Einmal editiert, zuletzt von qwertz (20. August 2009 um 20:48)

  • Willst du nur den Quadranten herausbekommen wo die Punkte am engsten aneinander liegen oder eine ganz bestimmte Koordinate unabhängig vom Quadranten?
    Also wenn es nur der Quadrant sein soll dann teile deine Punkte in 4 Arrays (für jeden Quadranten eines).
    Dann berechnest du für jedes Quadrantenarray einen Schwerpunkt( Mittelung der X und Y-Koordinaten).
    Dann berechnest du für jeden Punkt in diesem Quadranten den Abstand zu diesem Mittelpunkt (Pythagoras) und aus den gesamten Abständen rechnest du die Standardabweichung für die Punkte des Quadranten.
    Das machst du mit jedem Quadranten und der Quadrant mit der geringsten Standardabweichung ist der gesuchte.
    Verfeinern könntest du das ganze dann noch in dem du grobe Ausreißer detektierst und eliminierst (z.B. über die 3-Sigma-Regel).

    Wenn es allerdings nicht um den Quadranten geht dann würde mir spontan eine RANSAC-ähnliche Vorgehensweise vorschweben.
    Das heißt allerdings du musst eine vorher definierte Streuweite eingeben.
    Also im einfachsten Falle würdest du alle Punkte durchgehen und für jeden Punkt ermitteln wieviele Punkte sich innerhalb dieser Streuweite des Punktes befinden (jeweils über Pythagoras den Abstand).
    Den Punkt mit der größten Anzahl an Punkten wird dann genommen und die Punkte innerhalb dieser Streuweite um diesen ermittelt und das ganze zu einem Schwerpunkt gemittelt.
    Allerdings musst du wie gesagt erstmal eine Streuweite definieren - sonst funktioniert das nicht.

    3. Möglichkeit:
    Du erstellst ein Array mit den Ausmaßen deines Definitions und Wertebereiches.
    Dann gehst du jeden Punkt durch und alle "Pixel" des erstellten Arrays mit einem gewissen Abstand um diesen Punkt werden in ihrem Wert um 1 erhöht.
    Am Ende wird das Pixel mit dem höchsten Wert als Ergebnis genommen.
    Um das mal bildlicher darzustellen:
    Jeder Punkt ist eine Lampe und beleuchtet seine Umgebung in einem gewissen Abstand.
    Sind viele Lampen in der Gegend machen sie Punkte die von beiden Lampen erreicht werden umso heller.
    Unser anfangs erstelltes Array ist demnach eine Art Bild wo für jeden Ort die Helligkeit angegeben wird.
    Besonders hell ist es dann dort wo die meisten Punkte eng aneinander liegen.
    Verfeinern könnte man das ganze dann auch wieder wenn man nicht einfach 1 addiert sondern in Abhängigkeit vom Abstand.

    Einmal editiert, zuletzt von AspirinJunkie (18. August 2009 um 17:58)

  • danke schonmal für die hilfe

    ich denk ich werds so machen wie in der 2. Möglichkeit von AspirinJunkie
    einfach um jeden punkt ein quadrat denken und schaun, in welchem viereck sich die meisten anderen punkte befinden

    [Blockierte Grafik: http://img10.imageshack.us/img10/6610/85448372.jpg]

    mein ergebnis kommt dann morgen weil ich heut keine zeit mehr habe

    mfg
    qwertz

    Einmal editiert, zuletzt von qwertz (18. August 2009 um 21:10)

  • @anno
    Ich glaube kaum das ihm das hier weiterhilft.
    Die Formeln dienen dazu einen Standort zwischen n Punkten so zu legen das die Summe der Entfernungen aller Punkte zu diesem minimal wird.
    Das funktioniert ja aber nur wenn alle Punkte welche zur Berechnung herangezogen werden auch relevant sind. Aber genau darum geht es ja - sie sind es eben nicht alle.
    Es sollen nur die Punkte genommen werden welche einer größeren Häufung angehören.
    Alle anderen Punkte sind demnach Ausreißer welche das Ergebnis verfälschen.
    Das mag bei einer geringen Anzahl von Ausreißern ausgeglichen werden aber sobald der Bruchpunkt zu hoch wird wars das.
    Die Ausreißer müssen also erst einmal eliminiert werden - das ist das eigentliche Problem hierbei - nicht die Berechnung des Mittels, Medians oder sonst irgendwas.
    Im übrigen bin ich der Meinung das hier ein Schwerpunkt anstatt einer entfernungsoptimierten Standortwahl vollkommen ausreichend ist.

    @quertz
    Das entspricht aber nicht meiner 3. Möglichkeit sondern eher der 2. ;)

  • Eigentlich ist das schon wichtig. Natürlich ist das nicht der komplette Ansatz, aber eine Kombination würde funktionieren. qwertz hat gefragt "an welcher stelle die punkte am nähesten beieinander liegen". Am einfachsten ist dann die 2. Lösung von dir. Allerdings bekommt er dann den Punkt, der am nächsten an den anderen liegt und nicht die Stelle im Haufen, von der alle Punkte am nächsten dran liegen. Ich hätte als allererstes mit dieser Methode den "Haufen" ausfindig gemacht und dann von den jetzt noch vorhandenen Punkten die Stelle gesucht, die am nächsten an allen Punkten liegt. Es kommt halt drauf an wie genau das sein muss.

    Außerdem ist in deinem Modell ein Denkfehler qwertz. Wenn du den Satz von Pythagoras benutzt, dann hast du einen Kreis um jeden Punkt, der abgesucht wird, und kein Quadrat.

  • Nein - mit "am engsten beieinander liegen" meint quertz den Bereich(!) wo eine starke Häufung der Punkte zu verzeichnen ist.
    Also die Abstände der Punkte untereinander sehr klein ist und nicht die Summe der Abstände zu einem direkten einzelnen Punkt.

    Den Haufen bekommst du mit dem Standortproblem nicht heraus - zumindestens nicht bei einem hohen Bruchpunkt.
    Dann zieht es den Standort mit den geringsten Summe der Entfernungen außerhalb des Haufens.
    Das Verfahren ist also alles andere als ein robustes Verfahren.
    Es geht hier also nicht lediglich um Genauigkeit sondern direkt um richtig oder falsch.
    Eine reine Standortsuche nach der Methode der geringsten Entfernungssumme kann hier durchaus zu falschen Ergebnissen führen.
    Hilfreich um sich das etwas klarer werden zu lassen ist ein Einlesen in die Thematik der robusten Schätzverfahren .
    Stell dir doch einfach vor der Haufen besteht nur aus 10 Punkten in der oberen linken Ecke.
    Im Rest des Systems sind 100 andere Punkte zufällig verteilt (das sind unsere Ausreißer).
    Den berechneten Standort zieht es Richtung Koordinatenursprung weit weg von unseren Haufen.
    Das Ergebnis ist also grob falsch.

    Glaub mir - die entfernungsoptimierte Standortwahl ist hier nicht das MIttel der Wahl.
    Aber wie gesagt - wie die Punkte dann gemittelt werden ist eh das geringste Problem hier.

  • Ich hab das Verstanden!
    Ich würde deine Methode benutzen, um den Haufen ausfindig zu machen, keine Frage. Aber um dann aus den Punkten die Stelle - und darum ging es ihm in dem ersten Post - zu finden, an der alle Punkte am nächsten liegen musst du irgendein solches Verfahren anwenden. Das man keinen Standort aus allen Punkten finden kann ist klar. Nur mit deiner Methode suchst du nur den Bereich. Er will aber auch eine Stelle, also X und Y Koordinate haben, von der aus die Punkte möglichst nah beieinander liegen. Das geht ja wohl nur damit.

  • Ja ich hab dich ja auch verstanden.
    Das Verfahren kannst du durchaus anwenden - wär auch durchaus das beste um den wirklich besten Schwerpunkt zu finden.
    Aber das ist ja erst der letzte Schritt.
    Dort ist das ja auch legitim.
    Ob der Aufwand im Vergleich zu einer einfachen Koordinatenmittelung, wozu der Unterschied eher gering ausfallen wird lohnt, ist eine andere Frage.
    Denn jede Mittelungsmethode im 2. Schritt wird sehr gut innerhalb des Haufens liegen.
    Und er will ja lediglich einen - Zitat: "coordinaten eines punktes in der mitte dieses haufens".
    Also benötigt er gar keine streckenoptimierte Methode.

    Du sagtest jedoch aber das du den Haufen über die entfernungsoptimierte Standortsuche identifizieren willst - darum geht es hier in Wirklichkeit.
    Eigentlich könnte die Aufgabe auch lauten: Finde alle Punkte welche die größte Häufung im Koordinatensystem darstellen.
    Dann brauch gar nicht mehr gemittelt werden - das ist der eher triviale Punkt welcher erst nach der Identifizierung des Haufens folgt - das ist ja aber, wie so oft schon gesagt, gar nicht das Problem.
    Die wirkliche Aufgabe - die Identifizierung der Häufung lässt sich nicht robust mit der entfernungsoptimierten Standortbestimmung bewerkstelligen.
    Aber genau das wolltest du ja damit machen - nur wie?

    Einmal editiert, zuletzt von AspirinJunkie (18. August 2009 um 23:24)

  • Hallo,
    ich würde nach der 3. Methode vorgehen. "Hellsten" Punkt suchen, alle anderen Punkte unterhalb einer bestimmten "Helligkeitsschwelle" eliminieren und vom Rest den Schwerpunkt nehmen. Bei nur einem Punkthaufen kein Problem, je nach Verfahren liegen die berechneten Zentren jedenfalls nicht weit auseinander.
    Die Geschichte wird dann verzwickt, wenn es mehrere weiter voneinander entfernt befindliche Wolken gibt. In den Quadranten I,II und III befinden sich in den äußeren Ecken Punktewolken mit ähnlicher "Helligkeit", der Rest der Sterne ist zufällig verteilt. Dann wären mehrere Zentren richtig. Es müsste also eine Funktion "_Haufen_erkennen" auf alle Punkte losgelassen werden, welche auch mehrere Haufen erkennt. Jedenfalls mal eine nette Aufgabe, mach doch ein µ-It drauss^^
    ciao
    Andy

  • Schluss mit der Theorie :D.
    Ich hab die 2. Methode umgesetzt, eigentlich ist das ja nicht besonders schwer. Nur bekommt man so halt nur den Punkt, von dem aus innerhalb der "Streuweite" die meisten anderen Punkte liegen.
    Aber eigentlich dürfte das ja so reichen...

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>
    #include <GUIConstantsEx.au3>

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

    Global $posx[100], $posy[100], $labarr[100]

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

    $koordinaten = GUICreate("Koordinatensystem", 390, 284, 419, 261)

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

    $hWnd = WinGetHandle($koordinaten)
    _GDIPlus_Startup()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)

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

    GUICtrlCreateLabel("", 0, 284 / 2 - 1, 390, 2) ; x-Achse
    GUICtrlSetBkColor(-1, 0x000000)
    GUICtrlCreateLabel("", 390 / 2 - 1, 0, 2, 284) ; y-Achse
    GUICtrlSetBkColor(-1, 0x000000)

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

    For $i = 0 To 99
    $posx[$i] = Random(0, 390, 1)
    $posy[$i] = Random(0, 284, 1)
    $labarr[$i] = GUICtrlCreateLabel("", $posx[$i], $posy[$i], 3, 3)
    GUICtrlSetBkColor(-1, 0xFF0000)
    Next

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

    GUISetState(@SW_SHOW)

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

    ;__________________________________________________________
    ;__________________________________________________________

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

    _getmostPoints(50) ; radius

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

    ;__________________________________________________________
    ;__________________________________________________________

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

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_Shutdown()
    Exit
    EndSwitch
    WEnd

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

    Func _getmostPoints($range)
    Local $rangearr[100], $highindex

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

    For $i = 0 To 99
    $rangearr[$i] = 0
    Next

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

    For $j = 0 To 99
    For $i = 0 To 99
    $diffx = $posx[$j] - $posx[$i]
    If $diffx < 0 Then $diffx = $diffx * (-1)

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

    $diffy = $posy[$j] - $posy[$i]
    If $diffy < 0 Then $diffy = $diffy * (-1)

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

    If Sqrt($diffx ^ 2 + $diffy ^ 2) <= $range Then $rangearr[$j] += 1
    Next
    Next
    $highindex = _gethighestvalue($rangearr)
    GUICtrlSetPos($labarr[$highindex], $posx[$highindex] - 2, $posy[$highindex] - 2, 5, 5)
    GUICtrlSetBkColor($labarr[$highindex], 0x0000FF)
    _GDIPlus_GraphicsDrawEllipse($hGraphic, $posx[$highindex] - $range, $posy[$highindex] - $range, $range * 2, $range * 2)
    EndFunc ;==>_getmostPoints

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

    Func _gethighestvalue($arr)
    Local $highval = 0, $index = 0

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

    For $i = 0 To UBound($arr) - 1
    If ($arr[$i] > $highval) Then
    $highval = $arr[$i]
    $index = $i
    EndIf
    Next
    Return $index
    EndFunc ;==>_gethighestvalue

    [/autoit]
  • danke anno, habs mir noch bisschen umgeschrieben, aber funktioniert super :)

    gibts noch ne möglichkeit gleiche werte aus dem array rauszuwerfen? :>

  • [autoit]

    _arrayunique()

    [/autoit]