Zeichnen von Funktionsgraphen



  • Hallo,

    ich brauche nochmal eure Hilfe 😋

    Ich habe ein soweit sehr gut funktionierendes Programm geschrieben, welches die Graphen von vom Benutzer eingegebenen Funktionen zeichnen soll (mithilfe der Win-API, falls es jmd interessiert, ist aber unwichtig).

    Das Programm geht wie folgt vor:
    Es startet ganz links, und geht dann in ca. 0.02er Schritten nach rechts, bis es am Rand dort angekommen ist. Für den entsprechenden X-Wert errechnet das Programm dann den Y-Wert.

    So weit so gut...

    Nun gibt es aber diese speziellen Graphen, die einen negativen, ungeraden Exponenten haben (für alle, die nicht solche Graphen nicht mehr kennen: x-1 beispielsweise besteht aus zwei Kurven, die nicht miteinander verbunden sind (http://wikis.zum.de/rsg/images/6/64/F24-x-graph.jpg)). Selbstverständlich sollen auch solche Graphen fehlerfrei dargestellt werden können.

    Leider werden sie aber genau das nicht, da es durchaus vorkommt, dass das Programm nur den Wert für bspw. -0.001 und 0.0191 ausrechnet, und diese beiden dann miteinander verbindet, was leider nicht richtig ist.
    Hinzu kommt, dass dieser "kritische" Punkt sich auch verschieben lässt (bei (x+1)-1 liegt er bspw. bei 1), sodass einfach eine zusätzliche Prüfung der 0-Stelle mich nicht weiter bringt.

    Deshalb möchte ich euch fragen, ob ihr eine Idee habt, wie man dieses Problem lösen könnte, sodass auch solche Graphen korrekt dargestellt werden.



  • EdKannst du überprüfen ob die Funktion stetig ist? Kannst du die Stellen identifizieren an denen die Funktion nicht definiert ist?

    Edit: Ich fürchte zudem, dass diese Frage mit Standard C++ nicht viel zu tun hat. @SeppJ, bitte entsprechend verschieben.



  • Vielleicht habe ich mich etwas ungenau ausgedrückt... 🤡

    Ob eine Funktion stetig ist, weiß ich leider nicht, würde aber mein Problem lösen. Allerdings habe ich keine Idee, wie ich eine solche Überprüfung durchführen sollte... 😕


  • Mod

    Dein Algorithmus ist ungünstig. Ein festes Raster von x-Abständen ist nicht geeignet, um Funktionen zu zeichnen, die stark variieren. Deine Punktdichte muss davon abhängen, wie wild sich die Funktion verändert. Und selbstverständlich zeichnest du keine unendlich langen Verbindungslinien ein. Wenn die Länge einer Verbindung immer größer wird, obwohl (bzw. gerade weil) du mehr Zwischenpunkte berechnest, dann verbindest du diese Punkte eben nicht.

    Ein paar Anregungen und Stichworte zur Eigenrecherche findest du hier:
    http://scicomp.stackexchange.com/questions/2377/algorithms-for-adaptive-function-plotting



  • Dieser Thread wurde von Moderator/in SeppJ aus dem Forum C++ (alle ISO-Standards) in das Forum Rund um die Programmierung verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • SeppJ schrieb:

    Und selbstverständlich zeichnest du keine unendlich langen Verbindungslinien ein. Wenn die Länge einer Verbindung immer größer wird, obwohl (bzw. gerade weil) du mehr Zwischenpunkte berechnest, dann verbindest du diese Punkte eben nicht.

    Wäre es nicht einfacher (und auch besser) die Steigung zu limitieren?
    Also quasi

    dx = max_dx * 2;
    do
    {
        dx /= 2;
        x = last_x + dx;
        y = f(x);
        dy = y - last_y;
    }
    while (abs(dy) > max_dy && dx > min_dx)
    
    if (dy <= max_dy)
        draw_line(last_x, last_y, x, y);
    else
        draw_dot(x, y);
    
    last_x = x;
    last_y = y;
    

    Die Länge der Verbindung (also "dy" in meinem Beispiel) wird ja nicht bei jeder nicht-stetigen Funktion grösser wenn man dx kleiner macht. z.B. ist (x < 0) ? x : (x + 1) auch nicht stetig, aber trotzdem wird dy immer kleiner je kleiner man dx macht.


  • Mod

    Klingt gut. Meine praktische Erfahrung auf dem Gebiet ist gering, ich habe nur sofort gesehen, dass ich es nicht so machen würde, wie der Threadersteller, und dann die ersten Verbesserungen beschrieben, die mir einfielen. (Und dann noch gegoogelt, wie es die Profis machen, aber das beste was ich fand, ist der verlinkte Thread)



  • Hallo Alex,

    du kannst dir auch mal mein Graph-Programm aus Parser für mathematische Formeln anschauen (ist zwar C#, aber der allgemeien Code ist ja sehr C++ ähnlich) - dort verwende ich ein boolsche Flag 'bDraw', welches entsprechend gesetzt wird.

    Du schreibst, dein Code "geht dann in ca. 0.02er Schritten nach rechts" - es reicht bei der Ausgabe doch, daß du nur jeden Pixel berechnest und zeichnest (dann bist du unabhängig von dem X-Wertebereich [MinX, MaxX] des zu zeichnenden Funktionausschnitts):

    double xx = (MaxX - MinX) / width;
    
    for(double x = MinX; x <= MaxX; x += xx)
    

    (wobei width dann der Pixelbreite entspricht).



  • Danke erstmal für die zahlreichen und konstruktiven Antworten!!! 👍
    Ihr seid echt klasse! 😃 👍

    @hustbaer: Dein Vorschlag ist klasse! Den Graphen der Funktion 1/x zeichnet das Programm nun ohne Probleme fehlerfrei. 🙂
    Natürlich steigt auch der Rechenaufwand, was dazu führt, das es immer kurz dauert bis die Graphen gezeichnet sind.
    Gibt es da einen Weg, das Zeichnen zu beschleunigen?


Anmelden zum Antworten