GDI+ richtig verwendet?

  • Hi,

    ich habe folgendes Skript, das viele kleine Blöcke zeichnet mit _GDIPlus_GraphicsFillRect(). Das Ganze ist jedoch recht langsam, obwohl ich GDI+ verwende. Vielleicht mache ich etwas falsch beim Zeichen ..

    Kurz zum Skript selbst. Der rote Block wird solange "durchlöchert", bis es einen Weg vom oberen schwarzen Balken zum unteren schwarzen Balken gibt. Also eine durchgehende Verbindung.

    Das Ganze sieht dann so aus: [Blockierte Grafik: http://cl.ly/image/0I1u163q3P2D/Aufzeichnen.PNG]

    Spoiler anzeigen
    [autoit]


    #include <Array.au3>
    #include <ButtonConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlus.au3>
    #include <Timers.au3>

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

    Global $n = 50
    Global $components = $n * $n
    Global $id[$components]
    Global $cells[$n][$n]
    Global $Graphics[$n][$n]
    Global $tsample = 10000000
    Global $thr = 0.592746
    Global $time = 0
    Global $akt_thr = 0

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

    $fac = 5
    $Form = GUICreate("Simulation {" & $n * $n & "}", $n * $fac, $n * $fac + 50, 100, 100)
    $Label_Comp = GUICtrlCreateLabel("Components: " & $components, 10, $n * $fac + 10, 200, 17)
    $Label_CT = GUICtrlCreateLabel("Cur. Threshold: 0", 10, $n * $fac + 30, 200, 17)
    $Label_T = GUICtrlCreateLabel("Time converge: ", 120, $n * $fac + 10, 200, 17)
    GUICtrlSetColor(-1, 0x000080)
    GUISetState(@SW_SHOW)

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

    _GDIPlus_Startup()
    $hBrushBlue = _GDIPlus_BrushCreateSolid(0xFFFF0000)
    $hBrushB = _GDIPlus_BrushCreateSolid(0xFF000000)
    For $i = 0 To $n - 1
    For $j = 0 To $n - 1
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($Form)
    _GDIPlus_GraphicsFillRect($hGraphic, $i * $fac, $j * $fac, $fac, $fac, $hBrushBlue)
    Next
    Next

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

    For $i = 0 To $components - 1
    $id[$i] = $i
    Next

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

    For $k = 0 To $n - 2
    unite(cell($k, 0), cell($k + 1, 0))
    unite(cell($k, $n - 1), cell($k + 1, $n - 1))
    Next
    For $k = 0 To $n - 1
    $cells[$k][0] = True
    $cells[$k][$n - 1] = True
    Next

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

    $t = _simulate()
    ConsoleWrite("treshold: " & (1 * $t / ($n * $n)) & " - t: " & $t & " - time: " & $time & " - akt_thr: " & $akt_thr & @CRLF)

    [/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 _simulate()
    $t = 0
    While True
    Local $stt = _Timer_Init()
    If _root(cell(0, 0), cell($n - 1, $n - 1)) Then Return $t
    _step()
    _show()
    $t += 1
    Local $tsample = _Timer_Diff($stt)
    $time += $tsample
    $akt_thr = ($thr - ($t / ($n * $n))) * $tsample
    GUICtrlSetData($Label_T, "Time converge: " & Round($akt_thr, 2))
    GUICtrlSetData($Label_CT, "Cur. Threshold: " & ($t / ($n * $n)))
    WEnd
    EndFunc ;==>_simulate

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

    Func _show()
    For $r = 0 To $n - 1
    For $p = 0 To $n - 1
    If $cells[$r][$p] Then
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($Form)
    _GDIPlus_GraphicsFillRect($hGraphic, $r * $fac, $p * $fac, $fac, $fac, $hBrushB)
    EndIf
    Next
    Next
    EndFunc ;==>_show

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

    Func _step()
    Local $m, $h
    While $cells[$m][$h]
    $m = Random(0, $n - 1, 1)
    $h = Random(0, $n - 1, 1)
    WEnd
    $cells[$m][$h] = True
    If $m < $n - 1 And $cells[$m + 1][$h] Then unite(cell($m, $h), cell($m + 1, $h))
    If $m > 0 And $cells[$m - 1][$h] Then unite(cell($m, $h), cell($m - 1, $h))
    If $h < $n - 1 And $cells[$m][$h + 1] Then unite(cell($m, $h), cell($m, $h + 1))
    If $h > 0 And $cells[$m][$h - 1] Then unite(cell($m, $h), cell($m, $h - 1))
    EndFunc ;==>_step

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

    Func cell($i, $j)
    Return $i + $j * $n
    EndFunc ;==>cell

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

    Func _find($x)
    While $x <> $id[$x]
    $id[$x] = $id[$id[$x]]
    $x = $id[$x]
    WEnd
    Return $x
    EndFunc ;==>_find

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

    Func _root($p, $q)
    Return _find($p) == _find($q)
    EndFunc ;==>_root

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

    Func unite($p, $q)
    $i = _find($p)
    $j = _find($q)
    If $i == $j Then Return
    $id[$i] = $j
    $components -= 1
    GUICtrlSetData($Label_Comp, "Components: " & $components)
    EndFunc ;==>unite

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

    Schonmal Danke!

  • Das einzige, was mir so auf die Schnelle auffällt ist, dass du bei jedem Verwenden von GDI+ die Graphics neu erstellst. Einmal direkt nach dem Erstellen der GUI reicht. Ich glaube aber kaum, dass das einen großen Geschwindigkeitsverlust ausmacht.
    Wenn du das Skript schneller machen willst, kannst du es ja mal mit GUICtrlCreateGraphics und den dazugehörigen Funktionen versuchen.

  • Ja du verwendest es falsch^^. Einerseits musst du nicht jedes mal wenn du etwas zeichnest

    [autoit]

    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($Form)

    [/autoit]

    aufrufen, das ganze einmal am Script Anfang sollte reichen. Außerdem solltest du einen "Buffer" verwenden. Ich habe mal einen in dein Script eingebaut, vielleicht hilft es dir ja^^.

    [autoit]

    #include <Array.au3>
    #include <ButtonConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlus.au3>
    #include <Timers.au3>

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

    Global $n = 50
    Global $components = $n * $n
    Global $id[$components]
    Global $cells[$n][$n]
    Global $Graphics[$n][$n]
    Global $tsample = 10000000
    Global $thr = 0.592746
    Global $time = 0
    Global $akt_thr = 0

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

    $fac = 5
    $Form = GUICreate("Simulation {" & $n * $n & "}", $n * $fac, $n * $fac + 50, 100, 100)
    $Label_Comp = GUICtrlCreateLabel("Components: " & $components, 10, $n * $fac + 10, 200, 17)
    $Label_CT = GUICtrlCreateLabel("Cur. Threshold: 0", 10, $n * $fac + 30, 200, 17)
    $Label_T = GUICtrlCreateLabel("Time converge: ", 120, $n * $fac + 10, 200, 17)
    GUICtrlSetColor(-1, 0x000080)
    GUISetState(@SW_SHOW)

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

    _GDIPlus_Startup()

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

    Global $hGraphic = _GDIPlus_GraphicsCreateFromHWND($Form)
    Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($n * $fac, $n * $fac + 50, $hGraphic)
    Global $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)

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

    $hBrushBlue = _GDIPlus_BrushCreateSolid(0xFFFF0000)
    $hBrushB = _GDIPlus_BrushCreateSolid(0xFF000000)
    For $i = 0 To $n - 1
    For $j = 0 To $n - 1
    _GDIPlus_GraphicsFillRect($hBuffer, $i * $fac, $j * $fac, $fac, $fac, $hBrushBlue)
    Next
    Next

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

    For $i = 0 To $components - 1
    $id[$i] = $i
    Next

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

    For $k = 0 To $n - 2
    unite(cell($k, 0), cell($k + 1, 0))
    unite(cell($k, $n - 1), cell($k + 1, $n - 1))
    Next
    For $k = 0 To $n - 1
    $cells[$k][0] = True
    $cells[$k][$n - 1] = True
    Next

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

    $t = _simulate()
    ConsoleWrite("treshold: " & (1 * $t / ($n * $n)) & " - t: " & $t & " - time: " & $time & " - akt_thr: " & $akt_thr & @CRLF)

    [/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 _simulate()
    $t = 0
    While True
    Local $stt = _Timer_Init()
    If _root(cell(0, 0), cell($n - 1, $n - 1)) Then Return $t
    _step()
    _show()
    _GDIPlus_GraphicsDrawImage($hGraphic,$hBitmap,0,0)

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

    $t += 1
    Local $tsample = _Timer_Diff($stt)
    $time += $tsample
    $akt_thr = ($thr - ($t / ($n * $n))) * $tsample
    GUICtrlSetData($Label_T, "Time converge: " & Round($akt_thr, 2))
    GUICtrlSetData($Label_CT, "Cur. Threshold: " & ($t / ($n * $n)))
    WEnd
    EndFunc ;==>_simulate

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

    Func _show()
    For $r = 0 To $n - 1
    For $p = 0 To $n - 1
    If $cells[$r][$p] Then
    _GDIPlus_GraphicsFillRect($hBuffer, $r * $fac, $p * $fac, $fac, $fac, $hBrushB)
    EndIf
    Next
    Next
    EndFunc ;==>_show

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

    Func _step()
    Local $m, $h
    While $cells[$m][$h]
    $m = Random(0, $n - 1, 1)
    $h = Random(0, $n - 1, 1)
    WEnd
    $cells[$m][$h] = True
    If $m < $n - 1 And $cells[$m + 1][$h] Then unite(cell($m, $h), cell($m + 1, $h))
    If $m > 0 And $cells[$m - 1][$h] Then unite(cell($m, $h), cell($m - 1, $h))
    If $h < $n - 1 And $cells[$m][$h + 1] Then unite(cell($m, $h), cell($m, $h + 1))
    If $h > 0 And $cells[$m][$h - 1] Then unite(cell($m, $h), cell($m, $h - 1))
    EndFunc ;==>_step

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

    Func cell($i, $j)
    Return $i + $j * $n
    EndFunc ;==>cell

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

    Func _find($x)
    While $x <> $id[$x]
    $id[$x] = $id[$id[$x]]
    $x = $id[$x]
    WEnd
    Return $x
    EndFunc ;==>_find

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

    Func _root($p, $q)
    Return _find($p) == _find($q)
    EndFunc ;==>_root

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

    Func unite($p, $q)
    $i = _find($p)
    $j = _find($q)
    If $i == $j Then Return
    $id[$i] = $j
    $components -= 1
    GUICtrlSetData($Label_Comp, "Components: " & $components)
    EndFunc ;==>unite

    [/autoit]

    Und wegen der Geschwindigkeit, ist das Problem nicht einfach nur das vorallem gegen Ende bei den Randoms einfach viele schon schwarze quadrate getroffen werden?

  • Also von GDI+ Seite her kann man nichts schneller machen. Klar kann man einen Buffer verwenden, aber das kostet nochmals wertvolle Zeit, die du aj einsparen möchtest.
    Weglassen kannst du das holen des Grafikhandels in der Funktion _show(). Das scriüt wird dann zwar schneller, aber man merkt es nicht wirklich.

    Was man machen KANN ist eine DLL für die Rechenarbeiten in FreeBasic schreiben. Das ist recht einfach und eventuell beschleunigt es dein Script. Genau weiß ich es nicht.

    mfg
    Hauke

  • Ok hab ne Lösung gefunden die das ganze deutlich schneller macht (Braucht auf meinem PC dann noch etwa 8 Sekunden.
    Ignorier einfach meine andere^^

    [autoit]

    #include <Array.au3>
    #include <ButtonConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlus.au3>
    #include <Timers.au3>

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

    Global $n = 50
    Global $components = $n * $n
    Global $id[$components]
    Global $cells[$n][$n]
    Global $Graphics[$n][$n]
    Global $tsample = 10000000
    Global $thr = 0.592746
    Global $time = 0
    Global $akt_thr = 0

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

    $fac = 5
    $Form = GUICreate("Simulation {" & $n * $n & "}", $n * $fac, $n * $fac + 50, 100, 100)
    $Label_Comp = GUICtrlCreateLabel("Components: " & $components, 10, $n * $fac + 10, 200, 17)
    $Label_CT = GUICtrlCreateLabel("Cur. Threshold: 0", 10, $n * $fac + 30, 200, 17)
    $Label_T = GUICtrlCreateLabel("Time converge: ", 120, $n * $fac + 10, 200, 17)
    GUICtrlSetColor(-1, 0x000080)
    GUISetState(@SW_SHOW)

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

    _GDIPlus_Startup()

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

    Global $hGraphic = _GDIPlus_GraphicsCreateFromHWND($Form)
    Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($n * $fac, $n * $fac + 50, $hGraphic)
    Global $hBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)

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

    $hBrushBlue = _GDIPlus_BrushCreateSolid(0xFFFF0000)
    $hBrushB = _GDIPlus_BrushCreateSolid(0xFF000000)
    For $i = 0 To $n - 1
    For $j = 0 To $n - 1
    _GDIPlus_GraphicsFillRect($hBuffer, $i * $fac, $j * $fac, $fac, $fac, $hBrushBlue)
    Next
    Next

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

    For $i = 0 To $components - 1
    $id[$i] = $i
    Next

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

    For $k = 0 To $n - 2
    unite(cell($k, 0), cell($k + 1, 0))
    unite(cell($k, $n - 1), cell($k + 1, $n - 1))
    Next
    For $k = 0 To $n - 1
    $cells[$k][0] = True
    $cells[$k][$n - 1] = True
    Next
    _show()
    $t = _simulate()
    ConsoleWrite("treshold: " & (1 * $t / ($n * $n)) & " - t: " & $t & " - time: " & $time & " - akt_thr: " & $akt_thr & @CRLF)

    [/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 _simulate()
    $t = 0
    While True
    Local $stt = _Timer_Init()
    If _root(cell(0, 0), cell($n - 1, $n - 1)) Then Return $t
    _step()
    ;_show()
    _GDIPlus_GraphicsDrawImage($hGraphic,$hBitmap,0,0)

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

    $t += 1
    Local $tsample = _Timer_Diff($stt)
    $time += $tsample
    $akt_thr = ($thr - ($t / ($n * $n))) * $tsample
    GUICtrlSetData($Label_T, "Time converge: " & Round($akt_thr, 2))
    GUICtrlSetData($Label_CT, "Cur. Threshold: " & ($t / ($n * $n)))
    WEnd
    EndFunc ;==>_simulate

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

    Func _show()
    For $r = 0 To $n - 1
    For $p = 0 To $n - 1
    If $cells[$r][$p] Then
    _GDIPlus_GraphicsFillRect($hBuffer, $r * $fac, $p * $fac, $fac, $fac, $hBrushB)
    EndIf
    Next
    Next
    EndFunc ;==>_show

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

    Func _step()
    Local $m, $h
    While $cells[$m][$h]
    $m = Random(0, $n - 1, 1)
    $h = Random(0, $n - 1, 1)
    WEnd
    $cells[$m][$h] = True
    _GDIPlus_GraphicsFillRect($hBuffer, $m * $fac, $h * $fac, $fac, $fac, $hBrushB)
    If $m < $n - 1 And $cells[$m + 1][$h] Then unite(cell($m, $h), cell($m + 1, $h))
    If $m > 0 And $cells[$m - 1][$h] Then unite(cell($m, $h), cell($m - 1, $h))
    If $h < $n - 1 And $cells[$m][$h + 1] Then unite(cell($m, $h), cell($m, $h + 1))
    If $h > 0 And $cells[$m][$h - 1] Then unite(cell($m, $h), cell($m, $h - 1))
    EndFunc ;==>_step

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

    Func cell($i, $j)
    Return $i + $j * $n
    EndFunc ;==>cell

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

    Func _find($x)
    While $x <> $id[$x]
    $id[$x] = $id[$id[$x]]
    $x = $id[$x]
    WEnd
    Return $x
    EndFunc ;==>_find

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

    Func _root($p, $q)
    Return _find($p) == _find($q)
    EndFunc ;==>_root

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

    Func unite($p, $q)
    $i = _find($p)
    $j = _find($q)
    If $i == $j Then Return
    $id[$i] = $j
    $components -= 1
    GUICtrlSetData($Label_Comp, "Components: " & $components)
    EndFunc ;==>unite

    [/autoit]

    Die einzelnen Quadrate werden nur einmal auf den Buffer gezeichnet was das ganze deutlich beschleunigt

  • Hm... Das erscheint mir noch ein wenig langsam.
    Ich habs mal mit ein paar GDI Ergänzungen auf 0.6 Sekunden gebracht (Mein PC ist aber auch relativ flott).

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>
    #include <ButtonConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlus.au3>
    #include <WinAPI.au3>
    #include <Timers.au3>

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

    Global $n = 50
    Global $components = $n * $n
    Global $id[$components]
    Global $cells[$n][$n]
    Global $Graphics[$n][$n]
    Global $tsample = 10000000
    Global $thr = 0.592746
    Global $time = 0
    Global $akt_thr = 0

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

    $fac = 5
    $iSize = $n * $fac
    $Form = GUICreate("Simulation {" & $n * $n & "}", $iSize, $iSize + 50, 100, 100)
    $Label_Comp = GUICtrlCreateLabel("Components: " & $components, 10, $iSize + 10, 200, 17)
    $Label_CT = GUICtrlCreateLabel("Cur. Threshold: 0", 10, $iSize + 30, 200, 17)
    $Label_T = GUICtrlCreateLabel("Time converge: ", 120, $iSize + 10, 200, 17)
    GUICtrlSetColor(-1, 0x000080)
    GUISetState(@SW_SHOW)

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

    $hDC_Window = _WinAPI_GetDC($Form)
    $hDC_Bitmap = _WinAPI_CreateCompatibleDC($hDC_Window)
    $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC_Window, $iSize, $iSize)
    _WinAPI_SelectObject($hDC_Bitmap, $hBitmap)

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

    _GDIPlus_Startup()

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

    Global $hBuffer = _GDIPlus_GraphicsCreateFromHDC($hDC_Bitmap)

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

    $hBrushBlue = _GDIPlus_BrushCreateSolid(0xFFFF0000)
    $hBrushB = _GDIPlus_BrushCreateSolid(0xFF000000)

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

    _GDIPlus_GraphicsFillRect($hBuffer, 0, 0, $iSize, $iSize, $hBrushBlue)
    _WinAPI_BitBlt($hDC_Window, 0, 0, $iSize, $iSize, $hDC_Bitmap, 0, 0, $SRCCOPY)

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

    For $i = 0 To $components - 1
    $id[$i] = $i
    Next

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

    For $k = 0 To $n - 2
    unite(cell($k, 0), cell($k + 1, 0))
    unite(cell($k, $n - 1), cell($k + 1, $n - 1))
    Next
    For $k = 0 To $n - 1
    $cells[$k][0] = True
    $cells[$k][$n - 1] = True
    Next
    _show()
    $t = _simulate()
    ConsoleWrite("treshold: " & (1 * $t / ($n * $n)) & " - t: " & $t & " - time: " & $time & " - akt_thr: " & $akt_thr & @CRLF)

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

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    _WinAPI_ReleaseDC($Form, $hDC_Window)
    _WinAPI_DeleteDC($hDC_Bitmap)
    _WinAPI_DeleteObject($hBitmap)

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

    _GDIPlus_GraphicsDispose($hBuffer)
    _GDIPlus_BrushDispose($hBrushBlue)
    _GDIPlus_BrushDispose($hBrushB)
    _GDIPlus_Shutdown()
    Exit
    EndSwitch
    WEnd

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

    Func _simulate()
    $t = 0
    While True
    Local $stt = _Timer_Init()
    If _root(cell(0, 0), cell($n - 1, $n - 1)) Then Return $t
    _step()
    ;_show()
    _WinAPI_BitBlt($hDC_Window, 0, 0, $iSize, $iSize, $hDC_Bitmap, 0, 0, $SRCCOPY)

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

    $t += 1
    Local $tsample = _Timer_Diff($stt)
    $time += $tsample
    $akt_thr = ($thr - ($t / ($n * $n))) * $tsample
    GUICtrlSetData($Label_T, "Time converge: " & Round($akt_thr, 2))
    GUICtrlSetData($Label_CT, "Cur. Threshold: " & ($t / ($n * $n)))
    WEnd
    EndFunc ;==>_simulate

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

    Func _show()
    For $r = 0 To $n - 1
    For $p = 0 To $n - 1
    If $cells[$r][$p] Then
    _GDIPlus_GraphicsFillRect($hBuffer, $r * $fac, $p * $fac, $fac, $fac, $hBrushB)
    EndIf
    Next
    Next
    EndFunc ;==>_show

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

    Func _step()
    Local $m, $h
    While $cells[$m][$h]
    $m = Random(0, $n - 1, 1)
    $h = Random(0, $n - 1, 1)
    WEnd
    $cells[$m][$h] = True
    _GDIPlus_GraphicsFillRect($hBuffer, $m * $fac, $h * $fac, $fac, $fac, $hBrushB)
    If $m < $n - 1 And $cells[$m + 1][$h] Then unite(cell($m, $h), cell($m + 1, $h))
    If $m > 0 And $cells[$m - 1][$h] Then unite(cell($m, $h), cell($m - 1, $h))
    If $h < $n - 1 And $cells[$m][$h + 1] Then unite(cell($m, $h), cell($m, $h + 1))
    If $h > 0 And $cells[$m][$h - 1] Then unite(cell($m, $h), cell($m, $h - 1))
    EndFunc ;==>_step

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

    Func cell($i, $j)
    Return $i + $j * $n
    EndFunc ;==>cell

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

    Func _find($x)
    While $x <> $id[$x]
    $id[$x] = $id[$id[$x]]
    $x = $id[$x]
    WEnd
    Return $x
    EndFunc ;==>_find

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

    Func _root($p, $q)
    Return _find($p) == _find($q)
    EndFunc ;==>_root

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

    Func unite($p, $q)
    $i = _find($p)
    $j = _find($q)
    If $i == $j Then Return
    $id[$i] = $j
    $components -= 1
    GUICtrlSetData($Label_Comp, "Components: " & $components)
    EndFunc ;==>unite

    [/autoit]
  • Wenn man auf die Ausgabe in den Labels verzichten kann geht bei mit von ~1200 auf ~480 Millisekunden runter^^

    Spoiler anzeigen
    [autoit]

    #include <Array.au3>
    #include <ButtonConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlus.au3>
    #include <WinAPI.au3>
    #include <Timers.au3>

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

    Global $n = 50
    Global $components = $n * $n
    Global $id[$components]
    Global $cells[$n][$n]
    Global $Graphics[$n][$n]
    Global $tsample = 10000000
    Global $thr = 0.592746
    Global $time = 0
    Global $akt_thr = 0

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

    $fac = 5
    $iSize = $n * $fac
    $Form = GUICreate("Simulation {" & $n * $n & "}", $iSize, $iSize + 50, 100, 100)
    $Label_Comp = GUICtrlCreateLabel("Components: " & $components, 10, $iSize + 10, 200, 17)
    $Label_CT = GUICtrlCreateLabel("Cur. Threshold: 0", 10, $iSize + 30, 200, 17)
    $Label_T = GUICtrlCreateLabel("Time converge: ", 120, $iSize + 10, 200, 17)
    GUICtrlSetColor(-1, 0x000080)
    GUISetState(@SW_SHOW)

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

    $hDC_Window = _WinAPI_GetDC($Form)
    $hDC_Bitmap = _WinAPI_CreateCompatibleDC($hDC_Window)
    $hBitmap = _WinAPI_CreateCompatibleBitmap($hDC_Window, $iSize, $iSize)
    _WinAPI_SelectObject($hDC_Bitmap, $hBitmap)

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

    _GDIPlus_Startup()

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

    Global $hBuffer = _GDIPlus_GraphicsCreateFromHDC($hDC_Bitmap)

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

    $hBrushBlue = _GDIPlus_BrushCreateSolid(0xFFFF0000)
    $hBrushB = _GDIPlus_BrushCreateSolid(0xFF000000)

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

    _GDIPlus_GraphicsFillRect($hBuffer, 0, 0, $iSize, $iSize, $hBrushBlue)
    _WinAPI_BitBlt($hDC_Window, 0, 0, $iSize, $iSize, $hDC_Bitmap, 0, 0, $SRCCOPY)

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

    For $i = 0 To $components - 1
    $id[$i] = $i
    Next

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

    For $k = 0 To $n - 2
    unite(cell($k, 0), cell($k + 1, 0))
    unite(cell($k, $n - 1), cell($k + 1, $n - 1))
    Next
    For $k = 0 To $n - 1
    $cells[$k][0] = True
    $cells[$k][$n - 1] = True
    Next
    _show()
    $t = _simulate()
    ConsoleWrite("treshold: " & (1 * $t / ($n * $n)) & " - t: " & $t & " - time: " & $time & " - akt_thr: " & $akt_thr & @CRLF)

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

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    _WinAPI_ReleaseDC($Form, $hDC_Window)
    _WinAPI_DeleteDC($hDC_Bitmap)
    _WinAPI_DeleteObject($hBitmap)

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

    _GDIPlus_GraphicsDispose($hBuffer)
    _GDIPlus_BrushDispose($hBrushBlue)
    _GDIPlus_BrushDispose($hBrushB)
    _GDIPlus_Shutdown()
    Exit
    EndSwitch
    WEnd

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

    Func _simulate()
    $t = 0
    While True
    Local $stt = _Timer_Init()
    If _root(cell(0, 0), cell($n - 1, $n - 1)) Then Return $t
    _step()
    ;_show()
    _WinAPI_BitBlt($hDC_Window, 0, 0, $iSize, $iSize, $hDC_Bitmap, 0, 0, $SRCCOPY)

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

    $t += 1
    Local $tsample = _Timer_Diff($stt)
    $time += $tsample
    $akt_thr = ($thr - ($t / ($n * $n))) * $tsample
    ;~ GUICtrlSetData($Label_T, "Time converge: " & Round($akt_thr, 2))
    ;~ GUICtrlSetData($Label_CT, "Cur. Threshold: " & ($t / ($n * $n)))
    WEnd
    EndFunc ;==>_simulate

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

    Func _show()
    For $r = 0 To $n - 1
    For $p = 0 To $n - 1
    If $cells[$r][$p] Then
    _GDIPlus_GraphicsFillRect($hBuffer, $r * $fac, $p * $fac, $fac, $fac, $hBrushB)
    EndIf
    Next
    Next
    EndFunc ;==>_show

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

    Func _step()
    Local $m, $h
    While $cells[$m][$h]
    $m = Random(0, $n - 1, 1)
    $h = Random(0, $n - 1, 1)
    WEnd
    $cells[$m][$h] = True
    _GDIPlus_GraphicsFillRect($hBuffer, $m * $fac, $h * $fac, $fac, $fac, $hBrushB)
    If $m < $n - 1 And $cells[$m + 1][$h] Then unite(cell($m, $h), cell($m + 1, $h))
    If $m > 0 And $cells[$m - 1][$h] Then unite(cell($m, $h), cell($m - 1, $h))
    If $h < $n - 1 And $cells[$m][$h + 1] Then unite(cell($m, $h), cell($m, $h + 1))
    If $h > 0 And $cells[$m][$h - 1] Then unite(cell($m, $h), cell($m, $h - 1))
    EndFunc ;==>_step

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

    Func cell($i, $j)
    Return $i + $j * $n
    EndFunc ;==>cell

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

    Func _find($x)
    While $x <> $id[$x]
    $id[$x] = $id[$id[$x]]
    $x = $id[$x]
    WEnd
    Return $x
    EndFunc ;==>_find

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

    Func _root($p, $q)
    Return _find($p) == _find($q)
    EndFunc ;==>_root

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

    Func unite($p, $q)
    $i = _find($p)
    $j = _find($q)
    If $i == $j Then Return
    $id[$i] = $j
    $components -= 1
    ;~ GUICtrlSetData($Label_Comp, "Components: " & $components)
    EndFunc ;==>unite

    [/autoit]


    Geht aber halt nur, wenn man drauf verzichten kann.

    mfg
    Hauke

  • Hab den Algorithmus in einer Vorlesung an der Princeton University kennengelernt. Als Anwendungsbeispiel wurde ein Stein genannt, der durchlöchert wird. Wann ließt Wasser durch den Stein, weil es eine durchgehendes Loch hat?

    So hab ich mir gedacht, machst du das mal als Autoit Skript. Kann man natürlich auch für das Spiel "Hex" verwenden.