Search code examples
c++openglglut

draw an arbitrary line with OpenGL(i.e. no limit on axis range)


I want to draw a 2D line with parameters defined by user. But the range of x and y axis is [-1,1].

How can I draw the line that can be completely displayed in the window? I used gluOrtho2D(-10.0, 10.0, -10.0, 10.0) but it doesn't seem a good choice because the range is dynamic according to the parameters.

For example, the line is y=ax^3+bx^2+cx+d. the range of x is [1, 100].

My code is:

#include "pch.h"
#include<windows.h>

#include <gl/glut.h>

#include <iostream>
using namespace std;

double a, b, c, d;
void init(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(-10.0, 10.0, -10.0, 10.0);
}

double power(double x, int p) {
    double y = 1.0;
    for (int i = 0; i < p; ++i) {
        y *= x;
    }
    return y;
}

void linesegment(void)
{
    glClear(GL_COLOR_BUFFER_BIT);
    glColor3f(1, 0, 0);
    glPointSize(1);

    glBegin(GL_POINTS);
    for (int i = 1; i <= 10; ++i) {
        double y = a * power(i, 3) + b * power(i, 2) + c * i + d;
        glVertex2f(i, y);
    }
    glEnd();

    glFlush();
}

int main(int argc, char**argv)

{
    if (argc < 4) {
        cout << "should input 4 numbers" << endl;
        return 0;
    }

    a = atof(argv[1]);
    b = atof(argv[2]);
    c = atof(argv[3]);
    d = atof(argv[4]);

    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
    glutInitWindowPosition(50, 100);
    glutInitWindowSize(400, 300);
    glutCreateWindow("AnExample");

    init();

    glutDisplayFunc(linesegment);
    glutMainLoop();

    return 0;
}

Solution

  • Setting projection matrix is not a one-time-only operation. You can change it anytime you like. As a matter of fact, the way you do init is strongly discouraged. Just set the projection parameters in your drawing function. Also use standard library functions and don't roll your own. No need to implement power yourself. Just use the pow standard library function. Last but not least, use double buffering; for it gives better performance, and has better compatibility.

    #include "pch.h"
    #include <windows.h>
    
    #include <gl/glut.h>
    
    #include <iostream>
    #include <cmath>
    using namespace std;
    
    double a, b, c, d;
    double x_min, x_max, y_min, y_max; // <<<<---- fill these per your needs
    
    void linesegment(void)
    {
        glClear(GL_COLOR_BUFFER_BIT);
    
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(x_min, x_max, y_min, y_max, -1, 1);
    
        glColor3f(1, 0, 0);
        glPointSize(1);
    
        glBegin(GL_POINTS);
        for (int i = 1; i <= 10; ++i) {
            double y = a * pow(i, 3) + b * pow(i, 2) + c * i + d;
            glVertex2f(i, y);
        }
        glEnd();
    
        glFlush();
    }