Funktionsplotter - Funktionen ganz einfach darstellen

  • Hallo,

    ich möchte hier meinen Funktionsplotter vorstellen. Dieser kann Funktionen anzeigen und zeigt einem die Werte für die Funktion an, wenn man mit der Maus über das Fenster geht.
    Im Moment zeigt er nur eine Funktion an, ich werde das aber bald ergänzen, sobald ich den Fehler mit dem falschen Intervall behoben hab.

    Info!
    Leider sind die Formeln die ich zum errechnen verwende, nur für ein Intervall von [-x; y] geeignet. Es kann bei [x; y] Intervallen zu Fehlzeichnungen kommen.
    Des Weiteren musste ich die Funktion musste ich leider per _GDIPlus_GraphicsFillRect zeichnen, da _GDIPlus_GraphicsDrawLine bei kleinen Koordinaten nichts zeichnet.

    Der Funktionsplotter selbst ist nicht komplett mein Werk, da mir ein Freund (K.K.) ein wenig bei den Formeln geholfen hatte.

    Hoffentlich sind die Formeln im Script verständlich - wenn nicht, einfach fragen!

    Lob, Kritik und sonstiges Feedback ist gerne gesehen!

  • Der folgende Vorschlag ist ausdrücklich unoptimiert.
    (Geschwindigkeitsfaktor >10 ist locker drin. Vorallem beim ArrayAdd (da jedes Mal ReDim genutzt wird))

    Er soll nur eine einfache Möglichkeit aufzeigen:
    Vorher
    - 10 Rechtecke/Pixel (warum so viele ?)
    - Einfache Linie ohne Effekte (Einfluss höchstens Farblich möglich)
    - Stufen in der Linie

    Nachher
    - 1 Punkt/Pixel (man kann auch weniger nehmen, aber die Geschwindigkeit reicht locker aus um diese Genauigkeit zu bieten)
    - Linie wird per GraphicsDrawCurve gezeichnet -> Smoothing sowie Penwahl möglich !

    Todo:
    Code ansehen und verstehen -> Code verbessern :)

    Spoiler anzeigen
    [autoit]

    #include <GdiPlus.au3>
    #include <Array.au3>

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

    Opt("MouseCoordMode", 2)
    $hGUI = GUICreate("Funktionsplotter", 700, 418, -1, -1)

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

    GUICtrlCreateLabel("", 424, 168, 260, 1, 7)
    GUICtrlCreateLabel("", 424, 272, 260, 1, 7)

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

    Local $fXMin, $fXMax, $fYMin, $fYMax, $sEquation, $iMouseTemp

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

    $hXMin = GUICtrlCreateInput("-10", 488, 14, 57, 34, 1)
    $hXMax = GUICtrlCreateInput("10", 488, 54, 57, 34, 1)
    $hXScale = GUICtrlCreateInput("1", 488, 94, 57, 34, 1)
    $hYMin = GUICtrlCreateInput("-10", 624, 14, 57, 34, 1)
    $hYMax = GUICtrlCreateInput("10", 624, 54, 57, 34, 1)
    $hYScale = GUICtrlCreateInput("1", 624, 94, 57, 34, 1)
    $hAxis = GUICtrlCreateCheckbox("Achsen", 424, 136, 89, 17)
    $hXValue = GUICtrlCreateLabel("0", 496, 288, 183, 30, 1)
    $hYValue = GUICtrlCreateLabel("0", 496, 320, 183, 30, 1)
    $hEquation = GUICtrlCreateInput("sin(cos(x))^9*13+sin(3.4*x)", 424, 214, 257, 34, 1)
    $hDrawGraph = GUICtrlCreateButton("Zeiche Graphen", 416, 361, 275, 49)

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

    Local $aControls[20] = [GUICtrlCreateLabel("XMin:", 424, 16, 56, 30), GUICtrlCreateLabel("XMax:", 424, 56, 60, 30), GUICtrlCreateLabel("XScale:", 424, 96, 67, 30), _
    GUICtrlCreateLabel("YMin:", 560, 16, 55, 30), GUICtrlCreateLabel("YMax:", 560, 56, 59, 30), GUICtrlCreateLabel("YScale:", 560, 96, 66, 30), _
    GUICtrlCreateLabel("Funktion:", 424, 184, 86, 30), GUICtrlCreateLabel("X Wert:", 424, 288, 71, 30), GUICtrlCreateLabel("Y Wert:", 424, 320, 70, 30), _
    $hXMin, $hXMax, $hXScale, $hYMin, $hYMax, $hYScale, $hAxis, $hXValue, $hYValue, $hEquation, $hDrawGraph]

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

    For $i = 0 To UBound($aControls) - 1
    GUICtrlSetFont($aControls[$i], 16, 800, 0, "Calibri")
    Next

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

    GUICtrlSetState($hAxis, 1)
    GUISetState(@SW_SHOW)

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

    _GDIPlus_Startup()
    Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI), _
    $hWhiteBrush = _GDIPlus_BrushCreateSolid(0xFFFFFFFF), _
    $hRedBrush = _GDIPlus_BrushCreateSolid(0xFFFF0000)

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

    _GDIPlus_GraphicsSetSmoothingMode($hGraphics, 2)

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

    _DrawFrame()

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

    OnAutoItExitRegister("_CleanExit")

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

    While Sleep(10)
    Switch GUIGetMsg()
    Case -3
    _CleanExit()

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

    Case $hDrawGraph
    _DrawFrame()

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

    EndSwitch

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

    If $iMouseTemp <> MouseGetPos(0) and MouseGetPos(0) >= 8 and MouseGetPos(0) <= 408 and MouseGetPos(1) >= 8 and MouseGetPos(1) <= 408 Then
    $fXMin = Number(GUICtrlRead($hXMin))
    $fXMax = Number(GUICtrlRead($hXMax))
    $sEquation = StringReplace(GUICtrlRead($hEquation), ",", ".")
    $iMouseTemp = MouseGetPos(0)

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

    GUICtrlSetData($hXValue, Round((MouseGetPos(0) - 8) / 400 * (Abs($fXMin) + Abs($fXMax)) + $fXMin, 5))
    GUICtrlSetData($hYValue, Round(Execute(StringReplace($sEquation, "x", (MouseGetPos(0) - 8) / 400 * (Abs($fXMin) + Abs($fXMax)) + $fXMin)), 5))
    EndIf
    WEnd

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

    Func _DrawFrame()
    Local $fXMin = Number(GUICtrlRead($hXMin)), $fXMax = Number(GUICtrlRead($hXMax)), _
    $fYMin = Number(GUICtrlRead($hYMin)), $fYMax = Number(GUICtrlRead($hYMax)), _
    $fXScale = Number(GUICtrlRead($hXScale)), $fYScale = Number(GUICtrlRead($hYScale)), _
    $sEquation = StringReplace(GUICtrlRead($hEquation), ",", "."), $fTmp, _
    $iX = -1 * $fXMin / (Abs($fXMin) + Abs($fXMax)) * 398 + 9, _
    $iY = -1 * $fYMin / (Abs($fYMin) + Abs($fYMax)) * 398 + 9, _
    $aPoints[1][2]

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

    _GDIPlus_GraphicsFillRect($hGraphics, 8, 8, 400, 400, $hWhiteBrush)
    _GDIPlus_GraphicsDrawRect($hGraphics, 8, 8, 400, 400)

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

    If $fXMin > $fXMax Then
    MsgBox(16, "Fehler", "XMin ist größer als XMax.")
    ElseIf $fYMin > $fYMax Then
    MsgBox(16, "Fehler", "YMin ist größer als YMax.")
    Else
    If BitAND(GUICtrlRead($hAxis), 1) and $fXMin * $fXMax < 0 Then
    _GDIPlus_GraphicsDrawLine($hGraphics, $iX, 8, $iX, 408)
    For $i = $fYMin To $fYMax Step $fYScale
    _GDIPlus_GraphicsDrawLine($hGraphics, $iX - 3, (-1 * ($i - $fYMin) / (Abs($fYMin) + Abs($fYMax)) * 398 + 9) + 398, $iX + 3, (-1 * ($i - $fYMin) / (Abs($fYMin) + Abs($fYMax)) * 398 + 9) + 398)
    Next
    EndIf
    If BitAND(GUICtrlRead($hAxis), 1) and $fYMin * $fYMax < 0 Then
    _GDIPlus_GraphicsDrawLine($hGraphics, 8, $iY, 408, $iY)
    For $i = $fXMin To $fXMax Step $fXScale
    _GDIPlus_GraphicsDrawLine($hGraphics, ($i - $fXMin) / (Abs($fXMin) + Abs($fXMax)) * 398 + 9, $iY - 3, ($i - $fXMin) / (Abs($fXMin) + Abs($fXMax)) * 398 + 9, $iY + 3)
    Next
    EndIf

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

    For $i = $fXMin To $fXMax Step (Abs($fXMin) + Abs($fXMax)) / 398
    ;~ _GDIPlus_GraphicsDrawLine($hGraphics, ($i - (Abs($fXMin) + Abs($fXMax)) / 400 - $fXMin) / (Abs($fXMin) + Abs($fXMax)) * 400 + 8, _
    ;~ (-1 * Execute(StringReplace($sEquation, "x", $i - (Abs($fXMin) + Abs($fXMax)) / 400)) - $fYMin) / (Abs($fYMin) + Abs($fYMax)) * 400 + 8, _
    ;~ ($i - $fXMin) / (Abs($fXMin) + Abs($fXMax)) * 400 + 8, _
    ;~ (-1 * Execute(StringReplace($sEquation, "x", $i)) - $fYMin) / (Abs($fYMin) + Abs($fYMax)) * 400 + 8, $hRedBrush)

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

    $fTmp = (-1 * Execute(StringReplace($sEquation, "x", $i)) - $fYMin) / (Abs($fYMin) + Abs($fYMax)) * 398 + 9

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

    If $fTmp >= 9 and $fTmp <= 407 Then
    _ArrayAdd($aPoints, ($i - $fXMin) / (Abs($fXMin) + Abs($fXMax)) * 398 + 9 & '|' & $fTmp)
    EndIf

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

    ;~ _GDIPlus_GraphicsFillRect($hGraphics, ($i - $fXMin) / (Abs($fXMin) + Abs($fXMax)) * 398 + 9, $fTmp, 1, 1, $hRedBrush)
    Next
    EndIf

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

    $aPoints[0][0] = UBound($aPoints) - 1
    ;~ _ArrayDisplay($aPoints)
    Local $hPen = _GDIPlus_PenCreate(0xFF402010, 2)
    _GDIPlus_GraphicsDrawCurve($hGraphics, $aPoints, $hPen)
    _GDIPlus_PenDispose($hPen)

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

    EndFunc

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

    Func _CleanExit()
    _GDIPlus_BrushDispose($hRedBrush)
    _GDIPlus_BrushDispose($hWhiteBrush)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
    Exit
    EndFunc

    [/autoit]


    lg
    M