• Hi :P

    hier kommt ein Tool von mir, um sich einen oder mehrere Funktionsgraphen schnell und einfach zeichnen zu lassen. Einfach die Funktionsvorschrift (z.B. x² oder 4x+3) eingeben und auf "plot" klicken. Danch kann man den Graph verschieben und zoomen, um bestimmte Stellen genauer zu betrachten.

    Um den Zoom zu verbessern, würde ich die Graphen gerne auf GDIPlus-Pfaden aufbauen, allerdings habe ich nur _GDIPlus_PathWarp gefunden, um den Pfad selbst zu verändern, die Methode hat jedoch auch nach langem Rumprobieren nicht funktioniert.. Wenn da jemand mal ein funktionierendes Beispiel posten könnte, würde ich mich freuen :)

    Gruß syne

    features


    Einheit Zentimeter, nicht Pixel
    Verschieben des Koordinatensystems,
    zoom durch Scrollen oder Feld aufspannen mit der rechten Maustaste,
    verschiedene Farben für die Graphen

    Code
    [autoit]


    #include <WindowsConstants.au3>
    #include <GUIConstants.au3>
    #include <WinAPI.au3>
    #include <Array.au3>
    #include <GDIPlus.au3>
    #include <Misc.au3>

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

    Global Const $pi = 4*ATan(1), $2rad = $pi/180, $e = 2.718281828
    Global Const $struct = "ptr bmp;ptr grafx"
    Global Const $dpcm = _GetDPCm()

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

    Global $width = 650, $height = 500
    Global $drawW = $width-20, $drawH = $height-20-29-20-10
    Global $zoom = 1, $color = 0x000000
    Global $var = "x"

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

    Global $origin[2] = [$drawW/2, $drawH/2]
    Global $graphs[11] = [0]
    Global $start[3] = [0, 0, False]

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

    Global $GUI = GUICreate("Graphenzeichner", $width, $height, -1, -1)
    GUISetBkColor(0xFFFFFF)
    GUIRegisterMsg($WM_PAINT, "_paint")
    GUIRegisterMsg($WM_LBUTTONDOWN, "_LButtonDown")
    GUIRegisterMsg($WM_RBUTTONDOWN, "_RButtonDown")
    GUIRegisterMsg($WM_RBUTTONUP, "_RButtonUp")
    GUIRegisterMsg($WM_MOUSEWHEEL, "_mousewheel")

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

    $p = -20
    Global $beg = GUICtrlCreateLabel("f(" & $var & ") = ", 38+$p, $height-20-29+3, 59, 29)
    GUICtrlSetFont(-1, 15)

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

    Global $input = GUICtrlCreateInput("3*e^(-0.5*x²)", 97+$p, $height-20-29, 400, 29)
    GUICtrlSetFont(-1, 15)

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

    Global $plot = GUICtrlCreateButton("plot", 507+$p, $height-20-29, 100, 29)
    GUICtrlSetFont(-1, 14)

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

    Global $popup = GUICtrlCreateLabel("", $width-45, $height-49, 30, 30, $WS_BORDER)
    GUICtrlSetBkColor($popup, 0x000000)

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

    Dim $accKeys[1][2] = [["{ENTER}", $plot]]
    GUISetAccelerators($accKeys)

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

    Global $GUI2 = GUICreate("", 115, 115, $width-115-5-2, $height-115-5-2, $WS_POPUPWINDOW, BitOR($WS_EX_TOOLWINDOW, $WS_EX_MDICHILD), $GUI)
    GUISetBkColor(0xFFFFFF, $GUI2)

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

    Global $lbls[6][2] = [[0, 0x000000], [0, 0x1207B4], [0, 0x8F11B9], [0, 0xFF0000], [0, 0x12B407], [0, 0x12C0BC]]

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

    For $i = 0 To UBound($lbls)-1
    $lbls[$i][0] = GUICtrlCreateLabel("" , 6+Mod($i, 3)*37, 6+Floor($i/3)*37, 30, 30, $WS_BORDER)
    GUICtrlSetBkColor($lbls[$i][0], $lbls[$i][1])
    Next

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

    Global $choose = GUICtrlCreateLabel("Choose color", 6, 90, 80, 20)
    GUICtrlSetColor($choose, 0x0000FF)
    GUICtrlSetFont($choose, 10, 400, 4, "Arial")
    GUICtrlSetCursor($choose, 0)

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

    _GDIPlus_Startup()

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

    Global $grafx = _GDIPlus_GraphicsCreateFromHWND($GUI)
    Global $bmp = _GDIPlus_BitmapCreateFromGraphics($drawW, $drawH, $grafx)
    Global $backbuffer = _GDIPlus_ImageGetGraphicsContext($bmp)
    _GDIPlus_GraphicsSetSmoothingMode($backbuffer, 2)

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

    _drawAll()

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

    GUISetState(@SW_SHOW, $GUI)

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

    While 1
    $msg = GUIGetMsg()
    Switch $msg
    Case $GUI_EVENT_CLOSE
    For $i = 1 To $graphs[0]
    _GDIPlus_GraphicsDispose(DllStructGetData($graphs[$i], "grafx"))
    _GDIPlus_ImageDispose(DllStructGetData($graphs[$i], "bmp"))
    $graphs[$i] = 0
    Next
    _GDIPlus_GraphicsDispose($backbuffer)
    _GDIPlus_ImageDispose($bmp)
    _GDIPlus_GraphicsDispose($grafx)
    _GDIPlus_Shutdown()
    Exit
    Case $plot
    If $graphs[0] < 10 Then
    $fct = GUICtrlRead($input)
    $fct = _makeExecutable($fct)
    _plotGraph($fct, $backbuffer, $color)
    _GDIPlus_GraphicsDrawImageRect($grafx, $bmp, 10, 10, $drawW, $drawH)
    Else
    MsgBox(48, "Graphenzeichner", "Maximale Anzahl an Graphen erreicht.")
    EndIf
    Case $popup
    GUISetState(@SW_SHOW, $GUI2)
    Case $lbls[0][0] To $lbls[5][0]
    For $i = 0 To UBound($lbls, 1)-1
    If $msg = $lbls[$i][0] Then
    $color = $lbls[$i][1]
    GUICtrlSetBkColor($popup, "0x" & Hex($lbls[$i][1], 6))
    GUISetState(@SW_HIDE, $GUI2)
    EndIf
    Next
    Case $choose
    $tmp = _ChooseColor(2, 0x000000, 0, $GUI)
    If $tmp <> -1 Then
    $color = $tmp
    GUICtrlSetBkColor($popup, $color)
    GUISetState(@SW_HIDE, $GUI2)
    EndIf
    EndSwitch
    Sleep(50)
    WEnd

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

    Func _drawCoordSys($graphics)
    Local $pen = _GDIPlus_PenCreate()
    Local $cap = _GDIPlus_ArrowCapCreate(3, 3)
    _GDIPlus_PenSetCustomEndCap($pen, $cap)

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

    _GDIPlus_GraphicsClear($graphics, 0xFFEAEAEA)
    _GDIPlus_GraphicsDrawRect($graphics, 0, 0, $drawW-1, $drawH-1)
    _GDIPlus_GraphicsDrawLine($graphics, $origin[0], $drawH, $origin[0], 0, $pen)
    _GDIPlus_GraphicsDrawLine($graphics, 0, $origin[1], $drawW, $origin[1], $pen)
    For $i = $dpcm*$zoom To $drawW Step $dpcm*$zoom
    _GDIPlus_GraphicsDrawLine($graphics, $origin[0]+$i, $origin[1]-2, $origin[0]+$i, $origin[1]+2)
    _GDIPlus_GraphicsDrawLine($graphics, $origin[0]-$i, $origin[1]-2, $origin[0]-$i, $origin[1]+2)
    _GDIPlus_GraphicsDrawLine($graphics, $origin[0]-2, $origin[1]+$i, $origin[0]+2, $origin[1]+$i)
    _GDIPlus_GraphicsDrawLine($graphics, $origin[0]-2, $origin[1]-$i, $origin[0]+2, $origin[1]-$i)
    Next

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

    _GDIPlus_ArrowCapDispose($cap)
    _GDIPlus_PenDispose($pen)
    EndFunc

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

    Func _makeExecutable($fct)
    $fct = StringReplace($fct, "e", $e)
    $fct = StringReplace($fct, "pi", $pi)
    $fct = StringReplace($fct, "²", "^2")
    $fct = StringReplace($fct, "³", "^3")
    $fct = StringRegExpReplace($fct, "([x\d)])([x(])" , "$1*$2")
    $fct = StringReplace($fct, $var, "$x")
    Return $fct
    EndFunc

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

    Func _plotGraph($fct, $graphics, $col)
    Local $tBmp = _GDIPlus_BitmapCreateFromGraphics(2*$drawW, 2*$drawH, $graphics)
    Local $bb = _GDIPlus_ImageGetGraphicsContext($tBmp)
    _GDIPlus_GraphicsSetSmoothingMode($bb, 2)
    Local $pen = _GDIPlus_PenCreate("0xFF" & Hex($col, 6))
    Local $yO, $y, $x = (-$drawW-1)/$dpcm
    $yO = -1*Execute($fct)*$dpcm

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

    If $yO = "" Then
    MsgBox(48, "Graphenzeichner", "Die eingegebene Funktion konnte nicht berechnet werden.")
    _GDIPlus_PenDispose($pen)
    _GDIPlus_GraphicsDispose($bb)
    _GDIPlus_ImageDispose($tBmp)
    Return
    EndIf

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

    For $i = -$drawW To $drawW
    $x = $i / $dpcm
    $y = -1*Execute($fct)*$dpcm
    _GDIPlus_GraphicsDrawLine($bb, $i+$drawW-1, $yO+$drawH, $i+$drawW, $y+$drawH, $pen)
    $yO = $y
    Next
    _GDIPlus_GraphicsDrawImageRect($graphics, $tBmp, $origin[0]-$drawW*$zoom, $origin[1]-$drawH*$zoom, $drawW*2*$zoom, $drawH*2*$zoom)

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

    $graphs[0] += 1
    Local $tmp = DllStructCreate($struct)
    DllStructSetData($tmp, "bmp", $tBmp)
    DllStructSetData($tmp, "grafx", $bb)
    $graphs[$graphs[0]] = $tmp

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

    _GDIPlus_PenDispose($pen)
    EndFunc

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

    Func _drawAll($out = True)
    _drawCoordSys($backbuffer)
    For $i = 1 To $graphs[0]
    _GDIPlus_GraphicsDrawImageRect($backbuffer, DllStructGetData($graphs[$i], "bmp"), $origin[0]-$drawW*$zoom, $origin[1]-$drawH*$zoom, $drawW*2*$zoom, $drawH*2*$zoom)
    Next
    _GDIPlus_GraphicsDrawString($backbuffer, "zoom: " & $zoom, 3, 3, "Calibri", 10)
    If $out Then _GDIPlus_GraphicsDrawImageRect($grafx, $bmp, 10, 10, $drawW, $drawH)
    EndFunc

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

    Func _paint($hWnd, $msg, $wParam, $lParam)
    _GDIPlus_GraphicsDrawImageRect($grafx, $bmp, 10, 10, $drawW, $drawH)
    Return $GUI_RUNDEFMSG
    EndFunc

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

    Func _LButtonDown($hWnd, $msg, $wParam, $lParam)
    GUISetState(@SW_HIDE, $GUI2)
    Local $inf = GUIGetCursorInfo($GUI)
    Local $oInf = $inf
    If Not IsArray($inf) Then Return $GUI_RUNDEFMSG

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

    If _PointInRect($inf[0], $inf[1], 10, 10, $drawW, $drawH) Then
    While $inf[2]
    If _PointInRect($origin[0]-($oInf[0]-$inf[0]), $origin[1]-($oInf[1]-$inf[1]), 0, 0, $drawW, $drawH) Then
    $origin[0] -= $oInf[0]-$inf[0]
    $origin[1] -= $oInf[1]-$inf[1]
    _drawAll()
    EndIf
    $oInf = $inf
    $inf = GUIGetCursorInfo($GUI)
    WEnd
    EndIf
    EndFunc

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

    Func _RButtonDown($hWnd, $msg, $wParam, $lParam)
    Local $inf = GUIGetCursorInfo($GUI)
    If Not IsArray($inf) Then Return $GUI_RUNDEFMSG

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

    If _PointInRect($inf[0], $inf[1], 10, 10, $drawW, $drawH) Then
    While $inf[3]
    If $start[2] Then
    _drawAll(False)
    _GDIPlus_GraphicsDrawRect($backbuffer, $start[0]-10, $start[1]-10, $inf[0]-$start[0], $inf[1]-$start[1])
    _GDIPlus_GraphicsDrawImageRect($grafx, $bmp, 10, 10, $drawW, $drawH)
    Else
    $start[0] = $inf[0]
    $start[1] = $inf[1]
    $start[2] = True
    EndIf
    $inf = GUIGetCursorInfo($GUI)
    WEnd
    EndIf
    EndFunc

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

    Func _RButtonUp($hWnd, $msg, $wParam, $lParam)
    $inf = GUIGetCursorInfo($GUI)
    If Not IsArray($inf) Then Return $GUI_RUNDEFMSG

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

    $start[2] = False

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

    Local $w = $inf[0]-$start[0], $h = $inf[1]-$start[1]
    Do
    $w += 2
    $h += 2
    Until ($w >= $drawW Or $h >= $drawH)

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

    $zoom = Round(Min3($w/($inf[0]-$start[0]), $h/($inf[1]-$start[1]), 3), 1)

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

    $origin[0] += $origin[0]-($start[0]+($inf[0]-$start[0])/2)
    $origin[1] += $origin[1]-($start[1]+($inf[1]-$start[1])/2)

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

    _drawAll()
    EndFunc

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

    Func _mousewheel($hWnd, $msg, $wParam, $lParam)
    Local $inf = GUIGetCursorInfo($GUI)
    If Not IsArray($inf) Then Return $GUI_RUNDEFMSG

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

    Local $dir = BitAND($wParam, 0x800000)-1
    $dir = -Abs($dir)/$dir

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

    Switch True
    Case _PointInRect($inf[0], $inf[1], 10, $height-20-29+3, 59, 29)
    $var = Asc($var) - 97 + $dir
    $var = Iif($var < 0, 25, Mod($var, 26)) + 97
    $var = Chr($var)

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

    GUICtrlSetData($beg, "f(" & $var & ") = ")
    Case _PointInRect($inf[0], $inf[1], 10, 10, $drawW, $drawH)
    $zoom += 0.1*$dir
    $zoom = Round(Iif($zoom < 0.5, 0.5, Iif($zoom > 3, 3, $zoom)), 1)
    _drawAll()
    EndSwitch
    EndFunc

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

    Func _PointInRect($xPt, $yPt, $xTL, $yTL, $w, $h)
    Return ($xPt >= $xTL And $xPt <= $xTL+$w And $yPt >= $yTL And $yPt <= $yTL+$h)
    EndFunc

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

    Func _GetDPCm()
    Local $hDC = DllCall("user32.dll", "long", "GetDC", "long", 0)
    Local $aRet = DllCall("gdi32.dll", "long", "GetDeviceCaps", "long", $hDC[0], "long", 90)
    Local $hDC = DllCall("user32.dll", "long", "ReleaseDC", "long", 0, "long", $hDC)
    Return $aRet[0]/2.54
    EndFunc

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

    Func Iif($t, $v1, $v2)
    If $t Then Return $v1
    Return $v2
    EndFunc

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

    Func Min($v1, $v2)
    If $v1 < $v2 Then Return $v1
    Return $v2
    EndFunc

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

    Func Min3($v1, $v2, $v3)
    Return Min($v1, Min($v2, $v3))
    EndFunc

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

    Func Max($v1, $v2)
    If $v1 > $v2 Then Return $v1
    Return $v2
    EndFunc

    [/autoit]

    Einmal editiert, zuletzt von syne (29. Dezember 2010 um 15:06)

  • Erstens:

    Spoiler anzeigen
    Code
    Global Const $pi = $GDIP_PI, $2rad = $GDIP_RAD, $e = 2.718281828
    Global Const $pi = ^ ERROR
    >Exit code: 1	Time: 0.412

    Zweitens:

    Spoiler anzeigen
    Code
    #include <GDIP.au3> 
    
    
    >Exit code: 1	Time: 0.312