Re: How to plot simple 2D Graphs in C/C++ ?

Discussion in 'C++' started by Boris Glawe, Aug 25, 2003.

  1. Boris Glawe

    Boris Glawe Guest

    Hi,

    I wrote a plotter for the terminal a
    long long time ago.
    The function is hardcoded.
    Many comments and some variable names
    are in german...
    And programming style is horrible, since
    I wrote it a long long time ago ;-)

    The code is attached to the message...

    maybe it helps.

    greets Boris

    /* plotter.cpp Boris Glawe, 8.1.2002

    Ausführbar auf Terminals mit einer Auflösung von 80x25
    oder höher...
    */


    #include <iostream.h>
    #include <math.h>

    #define TASTFREQ 80
    #define ROWLENGTH 80 // Breite des Bildschirms
    #define SCREENHEIGHT 50 // Höhe der Tabelle


    /******************************************************************/

    class Graph {

    private:

    long double tab[TASTFREQ]; //vertikale Breite
    char row[ROWLENGTH+1]; // horizontale Breite (plus newline)

    long double max; //maximalwert in Fkt.
    long double min; //minimalwert in Fkt.

    long double xa; //kleinster x-Wert
    long double xe; //größter x-Wert -> dargestelltes Intervall...



    long double f(long double x){
    return sin(x) + sin(2*x) + sin(3*x) + sin(4*x);
    }






    /*Folgende Funktion ordnet einem Zahlenwert einen Feldindex zu.
    Sie erwartet fünf Argumente.
    1.Index des ersten Feldes im Array
    2.Index des letzten Feldes im Array
    3.Den kleinsten einzuordnenden Wert
    4.Faktor, der den "Wert" eines Feldes angibt
    5.der einzuordnende Wert
    Es wird das Intervall zwischen einem Maximalwert und einem
    Minimalwert in zwei Hälften geteilt.
    Es wird geprüft, in welcher Hälfte der Wert liegt und der
    selbe Vorgang wird mit dieser Hälfte solange rekursiv wiederholt,
    bis ein eindeutiges Feld bestimmt ist...
    Der rekursive Aufruf und die vielen Parameter machen das Programm
    unübersichtlich, ersparen aber viele Rechenschritte...
    */

    int classify(int a, int e,
    long double minvalue, long double dx, long double v){

    int anfang = a;
    int ende = e;
    int mitte;

    if( (e - a) % 2 == 0) mitte = (e + a) / 2;
    else mitte = (e + a -1) / 2;

    if (mitte == a) return mitte ;

    if(v >= minvalue + dx*(mitte) ){
    anfang = mitte;
    return classify(anfang,ende,minvalue,dx,v);
    }
    else{
    ende = mitte;
    return classify(anfang,ende,minvalue,dx,v);
    }
    }






    void make_tab(){
    long double dx = xa;
    int i;

    for (i=0; i<TASTFREQ; i++){
    tab = f(dx);
    dx += (xe - xa) / TASTFREQ;
    }
    }



    void init_graph(){

    int i;

    //Finde Extremwerte des Graphen...
    //falls alle fkt.-werte > 0 sind dann muss 0 trotzdem
    //Minimum sein, damit die Achsen richtig gezeichnet werden
    //Das gleich gilt, falls alle Wert < 0 sind...
    max = 0;
    min = 0;

    for (i=0; i<TASTFREQ; i++){
    if (tab > max) max = tab;
    if (tab < min) min = tab;
    }


    //den array row[] reseten...
    for(i=0; i<ROWLENGTH; i++){
    row=' ';
    }
    }



    public:

    //Standardkonstruktor:Standardbereich 0 bis 2 PI...
    Graph (){

    xa = 0.0; xe = 2.0*M_PI;

    make_tab(); // Tabellenwerte erstellen
    init_graph(); // Eigenschaften des Graphen berechnen..

    }

    //Konstruktor: Parameter geben den Bildbereich an.
    Graph (long double a, long double e){

    xa = a; xe = e;

    make_tab();
    init_graph();

    }//Ende Konstruktoren





    void print_values(){
    int i;

    cout << "Min:\t" << min << endl;
    cout << "Max:\t" << max << endl;

    for (i=0;i<TASTFREQ; i++){
    cout << tab << endl;
    }

    cout << endl << endl; // Abstand zur nächsten Ausgabe...

    }




    void draw_endless_graph() {

    int i,k,zero_point;

    //Normierung der Werte auf Arraylänge
    long double fieldwidth = (max - min) / ROWLENGTH;


    //Nullpunkt auf Bildschirmarray finden...
    zero_point = classify(0,ROWLENGTH,min,fieldwidth,0.0);

    // Kopfzeile schreiben...
    cout << "MAX: " << max << "\t\tMIN: " << min << endl;

    for(i=0; i<ROWLENGTH; i++) {
    if (i == zero_point) cout << "0";
    else cout << "-";
    }
    cout << endl;


    /* Durchlaufe alle Werte in tab[] und ordne sie einzeln
    in row[] ein...schreibe dann row[] auf Bildschirm */
    for(i=0; i<TASTFREQ; i++){
    row[zero_point] = '|';
    k=classify(0,ROWLENGTH-1,min,fieldwidth,tab);
    row[k] = '*'; row[ROWLENGTH] = 0;
    cout << row << endl;// Einzeichnen des Fkt.-wertes

    row[k] = ' '; // Feld wieder leeren...
    }
    //...und wieder aufräumen !!
    for (i=0; i<ROWLENGTH; i++) { row = ' ' ; row[ROWLENGTH] = 0; }

    cout << endl << endl; // Abstand zur nächsten Ausgabe...

    }




    void draw_window_graph() {

    int i,j,zero_point_x,zero_point_y;
    long double fieldwidth_x = (xe - xa) / ROWLENGTH;
    long double fieldwidth_y = (max - min) / SCREENHEIGHT;


    //Nullpunkt auf Bildschirmvertikalen finden...
    zero_point_y = classify(0,SCREENHEIGHT-1,min,fieldwidth_y,0.0);
    zero_point_x = classify(0,ROWLENGTH-1,xa,fieldwidth_x,0.0);


    // Kopfzeile schreiben...
    cout << "MAX: " << max << "\t\tMIN: " << min << endl;

    for(i=0; i<ROWLENGTH; i++) cout << "-";
    cout << endl;


    /*Da der Index 0 mit dem minimalen Wert identifizeirt ist,
    und die Ausgabe der Zeilen von oben nach unten erfolgt,
    muss der Index rückwärts laufen. Damit ist die letzte Zeile
    im Bildschirm auch der niedrigste Wert*/
    for (i=SCREENHEIGHT-1; i>=0; i--) {

    //erst mal aufräumen und dann x- und y-Achse einzeichnen...
    for(j=0;j<ROWLENGTH;j++) row[j] = ' ';
    if( i == zero_point_y )
    for (j=0;j<ROWLENGTH;j++) row[j]='-';

    for(j=0; j<ROWLENGTH; j++){

    if( zero_point_x == j ) row[j]='|';//y-Achse einzeichnen...

    if( classify(0,SCREENHEIGHT-1,min,fieldwidth_y,tab[j]) == i ){
    row[j] = '*';
    } // <- fkt.-wert einzeichnen

    } //ende for j

    row[ROWLENGTH] = 0; // Newline schreiben...
    cout << row << endl;

    }//ende for i

    cout << endl << endl; // Abstand zur nächsten Ausgabe...

    } //ende fkt.



    };

    /******************************************************************/








    int main() {

    cout << "Programm zum Zeichnen von Funktionskurven...." << endl;

    Graph obj;
    Graph obj2(-2,0.5);


    cout << "Ausgabe in vertikaler Richtung..." << endl ;
    obj.draw_endless_graph();
    cout << "Ausgabe in horizontaler Richtung..." << endl ;
    obj.draw_window_graph();


    cout << "Ausgabe mit anderem x-Achsenintervall..." << endl;
    obj2.draw_endless_graph();
    obj2.draw_window_graph();

    return 0;

    }
     
    Boris Glawe, Aug 25, 2003
    #1
    1. Advertisements

  2. Please don't post attachments to non-binary groups, and please do not
    give non-standard code as the answer to a question on this group.

    -Kevin
     
    Kevin Goodsell, Aug 25, 2003
    #2
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.