Linie schneidet Rechteck ?

  • Ich komm einfach nicht weiter :(
    Ich will überprüfen ob eine Linie von der ich Anfangs - und Endpunkt habe , ein Rechteck schneidet (Quadrat).

    Einmal editiert, zuletzt von nof@ker2 (4. August 2010 um 23:26)

  • Hey, vorhin hatte ich mal Zeit.

    Spoiler anzeigen
    [autoit]

    #include <GuiConstantsEx.au3>
    #include <GDIPlus.au3>
    #include <array.au3>

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

    $hGUI = GUICreate("GDI+", 400, 300, 100)
    GUISetState()

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

    _GDIPlus_Startup()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hGUI)

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

    ;#################### EXAMPLE 1
    _GDIPlus_GraphicsDrawLine($hGraphic, 10, 75, 100, 80)
    _GDIPlus_GraphicsDrawRect($hGraphic, 30, 20, 50, 50)

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

    $Koords1 = _GetPixelOfLineRectIntercept(10, 75, 100, 80, 30, 20, 50, 50)

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

    If $Koords1[0][0] = True Then
    $hBrushRed = _GDIPlus_BrushCreateSolid(0xFFFF0000)
    _GDIPlus_GraphicsDrawEllipse($hGraphic, $Koords1[1][0] - 2, $Koords1[1][1] - 2, 4, 4)
    _GDIPlus_GraphicsFillPie($hGraphic, $Koords1[1][0] - 2, $Koords1[1][1] - 2, 4, 4, 0, 360, $hBrushRed)

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

    _GDIPlus_GraphicsDrawEllipse($hGraphic, $Koords1[2][0] - 2, $Koords1[2][1] - 2, 4, 4)
    _GDIPlus_GraphicsFillPie($hGraphic, $Koords1[2][0] - 2, $Koords1[2][1] - 2, 4, 4, 0, 360, $hBrushRed)
    EndIf
    _ArrayDisplay($Koords1)
    ;####################

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

    ;#################### EXAMPLE 2
    _GDIPlus_GraphicsDrawLine($hGraphic, 260, 100, 300, 50)
    _GDIPlus_GraphicsDrawRect($hGraphic, 250, 20, 30, 70)

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

    $Koords2 = _GetPixelOfLineRectIntercept(260, 100, 300, 50, 250, 20, 30, 70)

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

    If $Koords2[0][0] = True Then
    $hBrushRed = _GDIPlus_BrushCreateSolid(0xFFFF0000)
    _GDIPlus_GraphicsDrawEllipse($hGraphic, $Koords2[1][0] - 2, $Koords2[1][1] - 2, 4, 4)
    _GDIPlus_GraphicsFillPie($hGraphic, $Koords2[1][0] - 2, $Koords2[1][1] - 2, 4, 4, 0, 360, $hBrushRed)

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

    _GDIPlus_GraphicsDrawEllipse($hGraphic, $Koords2[2][0] - 2, $Koords2[2][1] - 2, 4, 4)
    _GDIPlus_GraphicsFillPie($hGraphic, $Koords2[2][0] - 2, $Koords2[2][1] - 2, 4, 4, 0, 360, $hBrushRed)
    EndIf
    _ArrayDisplay($Koords2)
    ;####################

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

    ;#################### EXAMPLE 3
    _GDIPlus_GraphicsDrawLine($hGraphic, 210, 180, 270, 260)
    _GDIPlus_GraphicsDrawRect($hGraphic, 150, 190, 150, 50)

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

    $Koords3 = _GetPixelOfLineRectIntercept(210, 180, 270, 260, 150, 190, 150, 50)

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

    If $Koords3[0][0] = True Then
    $hBrushRed = _GDIPlus_BrushCreateSolid(0xFFFF0000)
    _GDIPlus_GraphicsDrawEllipse($hGraphic, $Koords3[1][0] - 2, $Koords3[1][1] - 2, 4, 4)
    _GDIPlus_GraphicsFillPie($hGraphic, $Koords3[1][0] - 2, $Koords3[1][1] - 2, 4, 4, 0, 360, $hBrushRed)

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

    _GDIPlus_GraphicsDrawEllipse($hGraphic, $Koords3[2][0] - 2, $Koords3[2][1] - 2, 4, 4)
    _GDIPlus_GraphicsFillPie($hGraphic, $Koords3[2][0] - 2, $Koords3[2][1] - 2, 4, 4, 0, 360, $hBrushRed)
    EndIf
    _ArrayDisplay($Koords3)

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

    _GDIPlus_GraphicsDrawLine($hGraphic, 120, 210, 320, 220)

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

    $Koords4 = _GetPixelOfLineRectIntercept(120, 210, 320, 220, 150, 190, 150, 50)

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

    If $Koords4[0][0] = True Then
    $hBrushRed = _GDIPlus_BrushCreateSolid(0xFFFF0000)
    _GDIPlus_GraphicsDrawEllipse($hGraphic, $Koords4[1][0] - 2, $Koords4[1][1] - 2, 4, 4)
    _GDIPlus_GraphicsFillPie($hGraphic, $Koords4[1][0] - 2, $Koords4[1][1] - 2, 4, 4, 0, 360, $hBrushRed)

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

    _GDIPlus_GraphicsDrawEllipse($hGraphic, $Koords4[2][0] - 2, $Koords4[2][1] - 2, 4, 4)
    _GDIPlus_GraphicsFillPie($hGraphic, $Koords4[2][0] - 2, $Koords4[2][1] - 2, 4, 4, 0, 360, $hBrushRed)
    EndIf
    _ArrayDisplay($Koords4)
    ;####################

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

    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

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

    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_Shutdown()

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

    Func _GetPixelOfLineRectIntercept($iLineX1, $iLineY1, $iLineX2, $iLineY2, $iRectX, $IRectY, $IRectW, $iRectH)
    Local $iVals[16] = [$iRectX, $iRectX + $IRectW, $IRectY, 0, $IRectY, $IRectY + $iRectH, $iRectX, 1, $iRectX, $iRectX + $IRectW, $IRectY + $iRectH, 0, $IRectY, $IRectY + $iRectH, $iRectX + $IRectW, 1]
    Dim $aArray[2], $aFoundArray[3][2]
    If $iLineX1 >= $iLineX2 And $iLineY1 >= $iLineY2 Then ; RECHTS UNTEN
    $xAbstand = $iLineX1 - $iLineX2
    $yAbstand = $iLineY1 - $iLineY2
    If $yAbstand > $xAbstand Then
    For $j = 1 To $yAbstand Step +1
    ReDim $aArray[$yAbstand + 1]
    $aArray[$j] = ($iLineY1) - $j & ";" & Round(($iLineX1) - $j * ($xAbstand / $yAbstand))
    Next
    Else
    For $j = 1 To $xAbstand Step +1
    ReDim $aArray[$xAbstand + 1]
    $aArray[$j] = ($iLineX1) - $j & ";" & Round(($iLineY1) - $j * ($yAbstand / $xAbstand))
    Next
    EndIf
    ElseIf $iLineX1 < $iLineX2 And $iLineY1 > $iLineY2 Then ; LINKS UNTEN
    $xAbstand = $iLineX2 - $iLineX1
    $yAbstand = $iLineY1 - $iLineY2
    If $yAbstand > $xAbstand Then
    For $j = 1 To $yAbstand Step +1
    ReDim $aArray[$yAbstand + 1]
    $aArray[$j] = Round(($iLineX1) + $j * ($xAbstand / $yAbstand)) & ";" & ($iLineY1) - $j
    Next
    Else
    For $j = 1 To $xAbstand Step +1
    ReDim $aArray[$xAbstand + 1]
    $aArray[$j] = ($iLineX1) + $j & ";" & Round(($iLineY1) - $j * ($yAbstand / $xAbstand))
    Next
    EndIf
    ElseIf $iLineX1 > $iLineX2 And $iLineY1 < $iLineY2 Then ; RECHTS OBEN
    $xAbstand = $iLineX1 - $iLineX2
    $yAbstand = $iLineY2 - $iLineY1
    If $yAbstand > $xAbstand Then
    For $j = 1 To $yAbstand Step +1
    ReDim $aArray[$yAbstand + 1]
    $aArray[$j] = Round(($iLineX1) - $j * ($xAbstand / $yAbstand)) & ";" & ($iLineY1) + $j
    Next
    Else
    For $j = 1 To $xAbstand Step +1
    ReDim $aArray[$xAbstand + 1]
    $aArray[$j] = ($iLineX1) - $j & ";" & Round(($iLineY1) + $j * ($yAbstand / $xAbstand))
    Next
    EndIf
    ElseIf $iLineX1 <= $iLineX2 And $iLineY1 <= $iLineY2 Then ; LINKS OBEN
    $xAbstand = $iLineX2 - $iLineX1
    $yAbstand = $iLineY2 - $iLineY1
    If $yAbstand > $xAbstand Then
    For $j = 1 To $yAbstand Step +1
    ReDim $aArray[$yAbstand + 1]
    $aArray[$j] = Round(($iLineX1) + $j * ($xAbstand / $yAbstand)) & ";" & ($iLineY1) + $j
    Next
    Else
    For $j = 1 To $xAbstand Step +1
    ReDim $aArray[$xAbstand + 1]
    $aArray[$j] = ($iLineX1) + $j & ";" & Round(($iLineY1) + $j * ($yAbstand / $xAbstand))
    Next
    EndIf
    EndIf
    $aFoundArray[0][0] = False
    For $k = 0 To 15 Step +4
    Local $Val
    $Val = _CalcRect($iVals[$k], $iVals[$k + 1], $iVals[$k + 2], $iVals[$k + 3], $aArray)
    If $aFoundArray[1][0] = '' And $Val <> '' Then
    $aFoundArray[1][0] = $Val[0]
    $aFoundArray[1][1] = $Val[1]
    ElseIf $aFoundArray[2][0] = '' And $Val <> '' Then
    $aFoundArray[2][0] = $Val[0]
    $aFoundArray[2][1] = $Val[1]
    EndIf
    Next
    If $aFoundArray[1][0] <> "" And $aFoundArray[2][0] <> "" Then $aFoundArray[0][0] = True
    Return $aFoundArray
    EndFunc ;==>_GetPixelOfLineRectIntercept

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

    Func _CalcRect($iVar1, $iVar2, $iVar3, $iMode, $aArray)
    Local $aCalcArray[2]
    For $i = $iVar1 To $iVar2
    For $j = 1 To UBound($aArray) - 1
    If $iMode = 0 Then
    If $aArray[$j] = $i & ";" & $iVar3 Then
    Local $aCalcArray[2] = [$i, $iVar3]
    Return $aCalcArray
    EndIf
    ElseIf $iMode = 1 Then
    If $aArray[$j] = $iVar3 & ";" & $i Then
    Local $aCalcArray[2] = [$iVar3, $i]
    Return $aCalcArray
    EndIf
    EndIf
    Next
    Next
    Return ''
    EndFunc ;==>_CalcRect

    [/autoit]
    • Offizieller Beitrag

    Versuche es mit der folgenden Funktion. Verwende RECT-Strukturen für das Quadrat und die Gerade (Höhe 1).

    [autoit]

    ;===============================================================================
    ; Function Name: _WinAPI_IntersectRect(ByRef $Src1Rect, ByRef $Src2Rect)
    ; Description: Ermittelt Schnittmengen zweier RECT-Strukturen
    ; Parameter(s): $Src1Rect, $Src2Rect RECT-Strukturen aus denen Schnittmengen festgestellt werden sollen
    ; Return Value(s): Erfolg RECT-Struktur der Schnittmenge
    ; Fehler 0 set @error 1-keine Struktur(en) übergeben
    ; 2-Dll-Fehler (s. @extended)
    ; 3-keine Schnittmenge
    ; Author(s): BugFix ([email='bugfix@autoit.de'][/email])
    ;===============================================================================
    Func _WinAPI_IntersectRect(ByRef $Src1Rect, ByRef $Src2Rect)
    If (Not IsDllStruct($Src1Rect)) Or (Not IsDllStruct($Src2Rect)) Then Return SetError(1,0,0)
    Local $DestRect = DllStructCreate("int Left;int Top;int Right;int Bottom")
    Local $ret = DllCall("user32", "int", "IntersectRect", "ptr", DllStructGetPtr($DestRect), "ptr", DllStructGetPtr($Src1Rect), "ptr", DllStructGetPtr($Src2Rect))
    If @error > 0 Then Return SetError(2,@error,0)
    If $ret[0] > 0 Then
    Return $DestRect
    Else
    Return SetError(3,0,0)
    EndIf
    EndFunc ;==>_WinAPI_IntersectRect

    [/autoit]
  • BugFix : Könntest du mir schnell noch sagen wie ich die RECT Struktur für die Gerade erstelle ? (Quadrat hab ich hinbekommen ;))

  • Die Funktion schneidet 2 Rechtecke, nicht Rechteck und Linie. Da braucht man etwas Mathe ;)

    • Offizieller Beitrag

    Da die Linie Höhe 1 hat ergibt das also ein RECT mit Höhe 1. Somit kann die Schnittfunktion genutzt werden. ;)

    Für die Gerade:

    Spoiler anzeigen
    [autoit]

    ; Bsp-Daten:

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

    Local $lineX = 50
    Local $lineLen = 120
    Local $lineY = 20
    Local $lineRECT = DllStructCreate("int Left;int Top;int Right;int Bottom")

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

    _WinAPI_SetRect($lineRECT, $lineX, $lineY, $lineX + $lineLen, $lineY +1)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [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]
  • Das sollte funktionieren, ich habs nicht getestet.
    Benötigt werden:
    oberer linker Punkt der Linie,
    unterer rechter Punkt der Linie
    oberer linker Punkt des Rechtecks,
    unterer rechter Punkt des Rechtecks.

    Spoiler anzeigen
    [autoit]

    Func _IntersectLineRect($iLineX1, $iLineY1, $iLineX2, $iLineY2, $iRectX1, $iRectY1, $iRectX2, $iRectY2)
    ; Author: ProgAndy; Geradengleichung aus 2 Punkten y = mx + c:
    Local $tmp
    If $iLineX1 > $iLineX2 Then
    $tmp = $iLineX1
    $iLineX1 = $iLineX2
    $iLineX2 = $tmp
    EndIf
    If $iLineY1 > $iLineY2 Then
    $tmp = $iLineX1
    $iLineY1 = $iLineY2
    $iLineY2 = $tmp
    EndIf
    If $iRectX1 > $iRectX2 Then
    $tmp = $iRectX1
    $iRectX1 = $iRectX2
    $iRectX2 = $tmp
    EndIf
    If $iRectY1 > $iRectY2 Then
    $tmp = $iRectX1
    $iRectY1 = $iRectY2
    $iRectY2 = $tmp
    EndIf

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

    ; Geradengleichung aus 2 Punkten y = mx + c:
    Local $tmp = ($iLineX2 - $iLineX1), $m = 0
    If Not ($tmp = 0) Then $m = ($iLineY2 - $iLineY1)/$tmp ; Wenn nicht senkrecht, Steigung berechnen
    If $m = 0 Then ; Gerade waagrecht oder senkrecht
    If $iLineY1 >= $iRectY1 And $iLineY1 <= $iRectY2 And $iLineX1 <= $iRectX2 And $iLineX2 >= $iRectX1 Then
    Return True
    EndIf
    Return False
    EndIf

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

    Local $c = $iLineY1 - ($m*$iLineX1), $x

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

    ; schnitt mit waagrechten
    ; x-Wert für $iRectY1
    $x = ($iRectY1 -$c)/$m
    If $x >= $iRectX1 And $x <= $iRectX2 Then Return True
    ; x-Wert für $iRectY2
    $x = ($iRectY2 -$c)/$m
    If $x >= $iRectX1 And $x <= $iRectX2 Then Return True

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

    ; schnitt mit Snkerechten
    ; y-Wert für $iRectX1
    $x = $m * $iRectX1 + $c
    If $x >= $iRectY1 And $x <= $iRectY2 Then Return True
    ; y-Wert für $iRectX2
    $x = $m * $iRectX2 + $c
    If $x >= $iRectY1 And $x <= $iRectY2 Then Return True

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

    Return False
    EndFunc

    [/autoit]

    PS: Die Schnittpunkte werden nicht berechnet.

  • Ich habe dann doch nochmal ein kleines Problem ^^
    Ist es auch noch möglich die Schnittpunkte herauszufinden ?

  • Klar ;) Eine Frage hätte ich noch. Suchst du Schnittpunkte auf der ganzen Geraden durch die zwei Punkte oder nur in dem Segment wischen den zwei Punkten?

    PS: Die bisherige Funktion berechnet nicht korrekt. Bei schiefen Segmenten wird auch ein Schnitt erkannt, wenn sich die Gerade durch die beiden Punkte schneidet. Das ist wohl nicht so gewollt, oder?

  • Ich suche die Schnittpunkte nur in dem Segment zwischen den beiden Punkten ;)

    PS: Nein das ist nicht so gewollt.

    Einmal editiert, zuletzt von nof@ker2 (5. August 2010 um 17:28)

  • Also verwende sie besser nicht. Hab inzwischen noch mehr Bugs gefunden ... War wohl zu spät.

    Edit: Also warte lieber nicht auf die Funktion, das ist echt einiges zum Rechnen, lauter Sonderfälle, wenn man die Koordinaten bestimmen will. (oder denke ich nur zu kompliziert?)

    Einmal editiert, zuletzt von progandy (5. August 2010 um 18:06)

  • Zitat

    (oder denke ich nur zu kompliziert?)


    Diese Frage habe ich mir auch schon gestellt. Eigentlich hört sich das ganze ja nicht schwer an , aber die Umsetzung ist mehr als kompliziert.

  • Den Schnitt grundsätzlich hab ich schon zusammen, nur gibt es noch Probleme mit dem berechnen der Schnitpunkte Schnittsegmente.
    Wenn nur die Punkte auf den Rechteckkanten gesucht sind, wird es einfacher, das hätte ich jetzt innerhalb von 5 Minuten fertig. ;)

    Edit: Das ist mein aktueller Stand, bitte teste mal mit möglichst vielen unterschiedlichen Kombinationen, die dir einfallen. Ich hoffe, dass ich alles berücksichtigt habe.

    Spoiler anzeigen
    [autoit]

    Func _IntersectLineSegmentRect($iLineX1, $iLineY1, $iLineX2, $iLineY2, $iRectX1, $iRectY1, $iRectX2, $iRectY2)
    ; Author: ProgAndy
    Local $tmp, $aResult[2][2]
    ;==================================================================================================
    ; Vorbereitung: Punkt sortieren, falls nicht richtig angegeben
    ;--------------------------------------------------------------------------------------------------
    If $iLineX1 > $iLineX2 Then
    $tmp = $iLineX1
    $iLineX1 = $iLineX2
    $iLineX2 = $tmp
    $tmp = $iLineY1
    $iLineY1 = $iLineY2
    $iLineY2 = $tmp
    EndIf
    If $iRectX1 > $iRectX2 Then
    $tmp = $iRectX1
    $iRectX1 = $iRectX2
    $iRectX2 = $tmp
    EndIf
    If $iRectY1 > $iRectY2 Then
    $tmp = $iRectY1
    $iRectY1 = $iRectY2
    $iRectY2 = $tmp
    EndIf

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

    ;==================================================================================================
    ; Fall 1: Segment komplett im Rechteck
    ;--------------------------------------------------------------------------------------------------
    If $iLineY1 >= $iRectY1 And $iLineY1 <= $iRectY2 And $iLineX1 <= $iRectX2 And $iLineX1 >= $iRectX1 And _
    $iLineY2 >= $iRectY1 And $iLineY2 <= $iRectY2 And $iLineX2 <= $iRectX2 And $iLineX2 >= $iRectX1 Then ; beide Punkte im Kasten
    Local $aResult[2][2] = [ [$iLineX1, $iLineY1], [$iLineX2, $iLineY2]]
    Return $aResult
    EndIf

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

    ;==================================================================================================
    ; Fall 2: Segment senkrecht oder waagrecht
    ;--------------------------------------------------------------------------------------------------
    ; Geradengleichung aus 2 Punkten y = mx + c:
    Local $dst = ($iLineX2 - $iLineX1), $m = 0
    If Not ($dst = 0) Then $m = ($iLineY2 - $iLineY1)/$dst ; Wenn nicht senkrecht, Steigung berechnen
    If $m = 0 Then ; Gerade waagrecht oder senkrecht
    If $iLineY1 > $iLineY2 Then ; jetzt kann man tauschen, das interessiert bei senkrechten oder waagrechten Linien nicht.
    $tmp = $iLineY1
    $iLineY1 = $iLineY2
    $iLineY2 = $tmp
    EndIf
    If $iLineY2 >= $iRectY1 And $iLineY1 <= $iRectY2 And $iLineX1 <= $iRectX2 And $iLineX2 >= $iRectX1 Then
    If $dst = 0 Then ; senkrechte Linie
    Dim $aResult[2][2] = [ [$iLineX1, $iRectY1], [$iLineX1, $iRectY2] ]
    If $iLineY1 > $iRectY1 Then $aResult[0][1] = $iLineY1 ; Die Fälle abdecken, in denen die Linie nicht durch das ganze Rechteck geht
    If $iLineY2 < $iRectY2 Then $aResult[1][1] = $iLineY2
    Else ; waagrechte Linie
    Dim $aResult[2][2] = [ [$iRectX1, $iLineY1], [$iRectX2, $iLineY1] ]
    If $iLineX1 > $iRectX1 Then $aResult[0][1] = $iLineX1 ; Die Fälle abdecken, in denen die Linie nicht durch das ganze Rechteck geht
    If $iLineX2 < $iRectX2 Then $aResult[1][1] = $iLineX2
    EndIf
    Return $aResult
    ;~ Return True
    EndIf
    Return False
    EndIf

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

    ;==================================================================================================
    ; Fall 3: Segment schief
    ;--------------------------------------------------------------------------------------------------
    Local $c = $iLineY1 - ($m*$iLineX1), $x1, $x2, $y1, $y2, $ok=0
    ; schnitt mit waagrechten
    ; x-Wert für $iRectY1
    $x1 = ($iRectY1 -$c)/$m
    If $x1 >= $iRectX1 And $x1 < $iRectX2 And $x1 >= $iLineX1 And $x1 <= $iLineX2 Then
    $aResult[$ok][0] = Round($x1, 15)
    $aResult[$ok][1] = $iRectY1
    $ok += 1
    EndIf
    ; x-Wert für $iRectY2
    $x2 = ($iRectY2 -$c)/$m
    If $x2 >= $iRectX1 And $x2 < $iRectX2 And $x2 >= $iLineX1 And $x2 <= $iLineX2 Then
    $aResult[$ok][0] = Round($x2, 15)
    $aResult[$ok][1] = $iRectY2
    $ok += 1
    If $ok = 2 Then Return $aResult
    EndIf

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

    ; schnitt mit Senkrechten
    ; y-Wert für $iRectX1
    $y1 = $m * $iRectX1 + $c
    If $y1 > $iRectY1 And $y1 < $iRectY2 And (($y1 >= $iLineY1 And $y1 <= $iLineY2) Or ($y1 <= $iLineY1 And $y1 >= $iLineY2)) Then
    $aResult[$ok][0] = $iRectX1
    $aResult[$ok][1] = Round($y1, 15)
    $ok += 1
    If $ok = 2 Then Return $aResult
    EndIf
    ; y-Wert für $iRectX2
    $y2 = $m * $iRectX2 + $c
    If $y2 >= $iRectY1 And $y2 <= $iRectY2 And (($y2 >= $iLineY1 And $y2 <= $iLineY2) Or ($y2 <= $iLineY1 And $y2 >= $iLineY2)) Then
    $aResult[$ok][0] = $iRectX2
    $aResult[$ok][1] = Round($y2, 15)
    $ok += 1
    If $ok = 2 Then Return $aResult
    EndIf

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

    ;==================================================================================================
    ; Fall 4: Nur ein Schnittpunkt mit Rechteckkanten
    ;--------------------------------------------------------------------------------------------------
    If $ok = 1 Then ; Die Linie hört im Rechteck auf oder berührt nur
    ; Punkt 1 der Linie testen:

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

    If $iLineY1 >= $iRectY1 And $iLineY1 <= $iRectY2 And $iLineX1 <= $iRectX2 And $iLineX1 >= $iRectX1 Then ; Punkt 1 ist im Kasten
    ; Wenn der Punkt schon gefunden wurde, testen, ob der 2. Punkt auch drin liegt, sollte eigentlich schon per Fall 1 gelöst sein ;)
    If $aResult[0][0] = $iLineX1 And $aResult[0][1] = $iLineY1 And $iLineY2 >= $iRectY1 And $iLineY2 <= $iRectY2 And $iLineX2 <= $iRectX2 And $iLineX2 >= $iRectX1 Then ; Punkt ist im Kasten
    $aResult[1][0] = $iLineX2
    $aResult[1][1] = $iLineY2
    Else ; Wenn der 2. Punkt nicht im REchteck liegt, dann ist das ein Berührpunkt, also doppelte Rückgabe
    $aResult[1][0] = $iLineX1
    $aResult[1][1] = $iLineY1
    EndIf
    ElseIf $iLineY2 >= $iRectY1 And $iLineY2 <= $iRectY2 And $iLineX2 <= $iRectX2 And $iLineX2 >= $iRectX1 Then ; Punkt 2 ist im Kasten
    $aResult[1][0] = $iLineX2
    $aResult[1][1] = $iLineY2
    EndIf

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

    If $aResult[0][0] > $aResult[1][0] Then ; X-Wert des 1. Punkts ist größer als vom zweiten. Also vertauschen
    $tmp = $aResult[1][0]
    $aResult[1][0] = $aResult[0][0]
    $aResult[0][0] = $tmp

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

    $tmp = $aResult[1][1]
    $aResult[1][1] = $aResult[0][1]
    $aResult[0][1] = $tmp
    EndIf
    Return $aResult

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

    EndIf

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

    ; kein Schnitt
    Return False
    EndFunc

    [/autoit]


    Edit: Funktion besser kommentiert und noch ein paar Sachen geändert.

    2 Mal editiert, zuletzt von progandy (5. August 2010 um 18:58)