[GDI+] Kurve zeichnen (3 Methoden)

  • Moin,

    wer kennt es nicht: Ich möchte eine Funktion f(t) -> (x(t),y(t)) zeichnen und wähle einfach 100 gleichverteilte Punkte in t um das zu tun. Das Ergebnis sieht mies aus. Ich wähle 200 Punkte. Immernoch mies. 1000 vielleicht? Okay, jetzt sieht es OK aus, aber weil meine Kurve irgendwo ein paar fiese Kanten & Peaks hat ist das Ergebnis immernoch nicht Pixelgenau... Also 10000 Punkte?

    Anbei ist ein Skript mit 3 Methoden um eine Kurve zu zeichnen.

    1. Linear (das was oben beschrieben wurde, 1 f(t) call pro Punkt)

    2. Adaptiv (Zunächst mit niedriger Auflösung Linear, dann "schätzen" wo gute Orte für weitere Punkte sind, 1 f(t) call pro Punkt)

    3. Adaptiv2 (Es wird mehr oder weniger via BruteForce herausgefunden wo gute Orte für weitere Punkte sind, "viele" f(t) calls pro Punkt)

    Es sei angemerkt, dass nicht jede Funktion für jeden Anwendungsfall sinnvoll ist. 1 & 2 eignen sich für Echtzeitanwendungen (sie brauchen für ~100 Punkte nur ein paar Millisekunden, je nach PC). 3 ist dafür geeignet wenn man die Funktion mit den wenigst möglichen Punkten "nahezu" bestmöglich abbilden will und die benötigte Zeit keine Rolle spielt (z.B. wenn man die Punkte irgendwo puffert, dann muss man sie nur 1x berechnen und kann sie anschließend relativ performant anzeigen, weil es so wenige sind).

    Die Geschwindigkeit ist leider ziemlich mies, da ich an einigen Stellen faul war (z.B. lineare Liniensuche statt Newton, etc.). Außerdem fehlen mir gewisse Datenstrukturen in AutoIt die ich, mangels Pointersupport, auch nicht nachbauen konnte (bzw. ich war einfach zu faul alles via DllStruct zu machen).

    PS: Jede Funktion f(x) = ... lässt sich als f(x) = (x, y(x)) umschreiben, wie auch im Beispiel verwendet. Man muss also nicht zwingend f:R->R² Funktionen verwenden :)


    Edit: Um zu demonstrieren, dass es auch mit "echten" R² Funktionen klappt kann man z.B. sowas hier verwenden:

    Code
    Func F($t)
    	Local $__[]
    	$__[0] = $t * $iGuiW * 0.9 + $iGuiW * 0.05
    	$__[1] = 50 * ManyGauss($t * 100 - 60) + 100*(2*$t-1)^2
    	Local $a = 0.1, $cx = $iGuiW / 2, $cy = 0
    	Local $_[]
    	$_[0] = $cx + ($__[0] - $cx) * Cos($a) - ($__[1] - $cy) * Sin($a)
    	$_[1] = $cy + ($__[0] - $cx) * Sin($a) + ($__[1] - $cy) * Cos($a)
    	Return $_
    EndFunc

    Eine gewöhnliche f(x) -> R Funktion könnte soetwas nicht abbilden, da einige x-Werte mehrere y-Werte besitzen. Fälle die in diesem Skript "nicht" abgedeckt sind, sind unstetige Funktionen. Falls es irgendwo einen "echten" Sprung in der Funktion gibt (z.B. Funktionen die aus mehreren Teilen bestehen die in einem Plot zu mehreren Linien führen), kann die hier gezeigte Methode nicht verwendet werden.


    lg

    M

  • Mars 4. Juni 2024 um 17:21

    Hat den Titel des Themas von „[GDI+] Kurve zeichnen“ zu „[GDI+] Kurve zeichnen (3 Methoden)“ geändert.