Suche eine (schnelle) IsInRect Funktion...

  • Hallo
    Ich suche eine Möglichst schnelle IsInRect Funktion.

    Hab selbst schon etwas daran gebastelt, aber leider werdens bei mir immer ziemlich viele If Abfragen.
    Ich Suche eine Lösung am Besten OHNE If Abfragen.
    Wer jetzt kommt: Man kann das alles zusammenfassen und mit And verbinden. Das weiß ich schon. Das ist der Übersicht halber so gemacht.

    Variablen sind 2 Arrays.
    [0] = X1
    [1] = Y1
    [2] = Breite1
    [3] = Hoehe2
    und beim Zweiten genauso.

    Es sieht so aus, dass das eine Rechteck wesentlich größer ist als das andere.

    Zurzeit hab ich Folgendes

    [autoit]

    Opt('GUIOnEventMode', 1)
    Global $hGUI = GUICreate('Test', 600, 600)
    GUISetOnEvent(-3, '_Exit')
    GUICtrlCreateLabel('', 100, 100, 300, 400)
    GUICtrlSetBkColor(-1, 0x555555)
    $hLabel = GUICtrlCreateLabel('', 0,0, 20, 40)
    GUICtrlSetBkColor(-1, 0xFF5555)

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

    Global $aPos = MouseGetPos()

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

    Local $Rect1[4] = [100,100,300,400]
    Local $Rect2[4] = [$aPos[0],$aPos[1],20,40]
    Local $Timer

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

    GUISetState(@SW_SHOW, $hGUI)

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

    While Sleep(10)
    $aPos = GUIGetCursorInfo($hGUI)
    GUICtrlSetPos($hLabel, $aPos[0], $aPos[1])
    $Rect2[0] = $aPos[0]
    $Rect2[1] = $aPos[1]

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

    $Timer = TimerInit()
    _IsInRect($Rect1, $Rect2)
    ToolTip(TimerDiff($Timer))
    $Timer = TimerInit()

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

    WEnd

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

    Func _IsInRect($R1, $R2)
    If $R2[0] + $R2[2] > $R1[0] Then
    If $R2[1] + $R2[3] > $R1[1] Then
    If $R2[0] < $R1[0] + $R1[2] Then
    If $R2[1] < $R1[1] + $R1[3] Then
    Return 1
    EndIf
    EndIf
    EndIf
    EndIf
    EndFunc

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

    Func _Exit()
    Exit
    EndFunc

    [/autoit]


    Viel Spaß beim Knobeln
    Mars(i)


    //Edit:. Danke für Jede Minute Mühe die Investiert wurde um das Problem zu Lösen. So Wie es aussieht funktioniert es mit der ReturnVariante2 (die mit den beiden Arrays) am besten. .://

  • Wenn 0,025 Millisekunden schnell genug für dich sind, hier eine Func von Faweyr:

    Spoiler anzeigen
    [autoit]

    Func _RectCollision($iX1, $iY1, $iWidth1, $iHeight1, $iX2, $iY2, $iWidth2, $iHeight2)
    ;Author: Faweyr
    Return $iX1 + $iWidth1 > $iX2 And $iX1 < $iX2 + $iWidth2 And $iY1 + $iHeight1 > $iY2 And $iY1 < $iY2 + $iHeight2
    EndFunc ;==>_RectCollision

    [/autoit]
  • beides gleichschnell

    deine If anfrgae und die Returnfunktion

    die abweichung sind im milisecbereich

    [autoit]

    Func _IsInRect($R1, $R2)
    Return (($R2[0] + $R2[2] > $R1[0]) And ($R2[1] + $R2[3] > $R1[1]) And ($R2[0] < $R1[0] + $R1[2]) And ($R2[1] < $R1[1] + $R1[3]))
    EndFunc ;==>_IsInRect

    [/autoit]
  • Das mit der Returnfunktion hab ich gesucht. Danke !

    Habs jetzt mal so gemacht, dass die IsInRect Funktion 10000 Mal ausgeführt wird. Dann hat man bessere Werte für den Vergleich,

    Mit 4x If -> 10.000 Mal = 113 ms => 0.013ms pro Durchlauf.
    Die Return Methode 10.000 Mal = 91ms => 0.009ms pro Durchlauf.

    die Return Methode braucht nur 70% Der Zeit.

    vllt gehts ja noch schneller :P

    Aber Das sollte schonmal Reichen.
    Danke :D


    mfg
    Mars(i)

    • Offizieller Beitrag

    Ich verwende für solche Checks Rectangle-Strukturen ($tagRECT). Kannst ja mal testen, wie da die Performance ist. Nachfolgende Funktionen sind hilfreich:
    Die RECT-Struktur erstellt man mit

    [autoit]

    $tRECT = DllStructCreate("int Left;int Top;int Right;int Bottom")
    ; oder
    $tRECT = DllStructCreate($tagRECT) ; erfordert: #include <StructureConstants.au3>

    [/autoit]
    RECT-Struktur mit Daten füllen
    [autoit]

    ;===============================================================================
    ; Function Name: _WinAPI_SetRect(ByRef $tRECT, $X1, $Y1, $X2, $Y2)
    ; Description: Befüllt eine RECT-Struktur in einem Aufruf mit Werten
    ; Parameter(s): $tRECT RECT-Struktur
    ; $X1, $Y1, $X2, $Y2 Werte des Rectangle
    ; Return Value(s): Erfolg <> 0
    ; Fehler 0 set @error 1-keine Struktur übergeben
    ; Author(s): BugFix ([email='bugfix@autoit.de'][/email])
    ;===============================================================================
    Func _WinAPI_SetRect(ByRef $tRECT, $X1, $Y1, $X2, $Y2)
    If Not IsDllStruct($tRECT) Then Return SetError(1,0,0)
    Local $ret = DllCall("user32", 'long', 'SetRect', 'ptr', DllStructGetPtr($tRECT), 'long', $X1, 'long', $Y1, 'long', $X2, 'long', $Y2)
    If @error > 0 Then Return SetError(1,@error,0)
    Return $ret[0]
    EndFunc ;==>_WinAPI_SetRect

    [/autoit]
    Koordinaten im RECT ?
    [autoit]

    ;===============================================================================
    ; Function Name: _WinAPI_CoordInRect(ByRef $tRECT, $X, $Y)
    ; Description: Ermittelt ob eine übergebene Koordinate innerhalb einer RECT-Struktur ist
    ; Analog zu _WinAPI_PtInRect, aber statt $tagPOINT werden Einzelkoordinaten übergeben
    ; Parameter(s): $tRECT RECT-Struktur
    ; $X X-Koordinate
    ; $Y Y-Koordinate
    ; Return Value(s): Erfolg True/False Punkt in/nicht in RECT
    ; Fehler 0 set @error 1-keine Struktur übergeben
    ; 2-Dll-Fehler (s. @extended)
    ; Author(s): BugFix ([email='bugfix@autoit.de'][/email])
    ;===============================================================================
    Func _WinAPI_CoordInRect(ByRef $tRECT, $X, $Y)
    If Not IsDllStruct($tRECT) Then Return SetError(1,0,0)
    Local $ret = DllCall("user32", "long", "PtInRect", "ptr", DllStructGetPtr($tRECT), "long", $X, "long", $Y)
    If @error > 0 Then Return SetError(2,@error,0)
    If $ret[0] Then
    Return True
    Else
    Return False
    EndIf
    EndFunc ;==>_WinAPI_CoordInRect

    [/autoit]
  • BugFix ,
    Faweyr´s Einzeiler ist (auf meinem Rechner zumindest) ungeschlagen. Der Overhead des DllCalls frisst evtl. Performancegewinne sofort auf.
    3xAND und 4x Addition ist auch in AutoIt "sauschnell"^^
    Sehr interessant auch, dass die Sequenz

    [autoit]

    if erstervergleich then
    if zweiterverglech then
    if drittervergleich then
    if viertervergleich then

    [/autoit]

    LANGSAMER ist als der Einzeiler, der IMMER ALLE Vergleiche durchführen muss...


  • Sehr interessant auch, dass die Sequenz

    [autoit]

    if erstervergleich then
    if zweiterverglech then
    if drittervergleich then
    if viertervergleich then

    [/autoit]

    LANGSAMER ist als der Einzeiler, der IMMER ALLE Vergleiche durchführen muss...

    Nein, die Vergleiche werden von links nach rechts durchgeführt und nicht weitergemacht, sobald eine Bedingung nicht zutrifft.
    Das ist sehr praktisch, wenn man z.B. in der ersten Bedingung auf IsArray prüft und in der zweiten gleich einen Arraywert hernimmt:

    [autoit]

    Global $Var = "abc"
    If IsArray($Var) And $Var[0] = True Then ... ; <- geht
    If $Var[0] = True And IsArray($Var) Then ... ; <- Subscript used with non-Array variable

    [/autoit]


    Und einzeilige IF sind grundsätzlich schneller als IF..EndIf