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?


Log in to reply