// Peter Bui // CSE 40166 Computer Graphics (Fall 2010) // Program 2: simple plotting program #include "color.h" #include #include #include #include #include #include #include #include using namespace std; // Point data type ------------------------------------------------------------- typedef struct { float x; float y; } point; bool cmp_x(const point &a, const point &b) { return a.x < b.x; } bool cmp_y(const point &a, const point &b) { return a.y < b.y; } bool cmp_point(const point &a, const point &b) { return (a.x == b.x) ? cmp_y(a, b) : cmp_x(a, b); } // Constants ------------------------------------------------------------------- enum PLOT_MODES { PLOT_MODE_POINTS, PLOT_MODE_CIRCLES, PLOT_MODE_LINE, PLOT_MODE_FAN, PLOT_MODE_TRIANGLES, PLOT_MODE_QUADS, PLOT_MODE_UNKNOWN }; // Global variables ------------------------------------------------------------ static vector Points; static float XMin, XMax, YMin, YMax; static float Thickness = 4.0; static int Padding = 2; static int WindowWidth = 640; static int WindowHeight = 480; static int CircleTriangles = 32; static float CircleRadius = 0.25; static float TriangleWidth = 0.25; static float QuadWidth = 0.25; static int AxesColor = COLOR_BLACK; static int BackgroundColor = COLOR_WHITE; // Read points from data file -------------------------------------------------- void read_points(const char *fname) { FILE *fs; point p; fs = fopen(fname, "r"); if (!fs) { fprintf(stderr, "plot: could not open file %s\n", fname); exit(EXIT_FAILURE); } while (fscanf(fs, "%f %f", &p.x, &p.y) == 2) Points.push_back(p); sort(Points.begin(), Points.end(), cmp_point); XMin = min_element(Points.begin(), Points.end(), cmp_x)->x; XMax = max_element(Points.begin(), Points.end(), cmp_x)->x; YMin = min_element(Points.begin(), Points.end(), cmp_y)->y; YMax = max_element(Points.begin(), Points.end(), cmp_y)->y; } // Set view based on points ---------------------------------------------------- void init() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(XMin - Padding, XMax + Padding, YMin - Padding, YMax + Padding); glMatrixMode(GL_MODELVIEW); glClearColor(ColorTable[BackgroundColor][0], ColorTable[BackgroundColor][1], ColorTable[BackgroundColor][2], 1.0); glEnable(GL_POINT_SMOOTH); } // Plot axes ------------------------------------------------------------------- void plot_axes() { glColor3fv(ColorTable[AxesColor]); glLineWidth(Thickness); glBegin(GL_LINES); { glVertex2f(XMin, 0.0); glVertex2f(XMax, 0.0); glVertex2f(0.0, YMin); glVertex2f(0.0, YMax); } glEnd(); } // Plot points as points ------------------------------------------------------- void plot_points() { glBegin(GL_POINTS); { for (size_t i = 0; i < Points.size(); i++) { glColor3fv(color_rotate()); glVertex2f(Points[i].x, Points[i].y); } } glEnd(); } // Plot points as circles ------------------------------------------------------ void plot_circle(float o_x, float o_y) { int i; GLfloat angle; glBegin(GL_TRIANGLE_FAN); { glVertex2f(o_x, o_y); for (i = 0; i <= CircleTriangles ; i++) { angle = i * 2.0 * M_PI / CircleTriangles; glVertex2f(o_x + CircleRadius * cos(angle), o_y + CircleRadius * sin(angle)); } } glEnd(); } void plot_circles() { for (size_t i = 0; i < Points.size(); i++) { glColor3fv(color_rotate()); plot_circle(Points[i].x, Points[i].y); } } // Plot points as line --------------------------------------------------------- void plot_line() { glBegin(GL_LINE_STRIP); { for (size_t i = 0; i < Points.size(); i++) { glColor3fv(color_rotate()); glVertex2f(Points[i].x, Points[i].y); } } glEnd(); } // Plot points as fan ---------------------------------------------------------- void plot_fan() { glBegin(GL_TRIANGLE_FAN); { glVertex2f((XMax - XMin) / 2.0, 0.0); for (size_t i = 0; i < Points.size(); i++) { glColor3fv(color_rotate()); glVertex2f(Points[i].x, Points[i].y); } } glEnd(); } // Plot points as strip -------------------------------------------------------- void plot_strip() { glBegin(GL_TRIANGLE_STRIP); { for (size_t i = 0; i < Points.size(); i++) { glColor3fv(color_rotate()); glVertex2f(Points[i].x, Points[i].y); glVertex2f(Points[i].x, 0.0); } } glEnd(); } // Plot points as triangles --------------------------------------------------- void plot_triangles() { glBegin(GL_TRIANGLES); { for (size_t i = 0; i < Points.size(); i++) { glColor3fv(color_rotate()); glVertex2f(Points[i].x, Points[i].y); glVertex2f(Points[i].x + TriangleWidth, 0.0); glVertex2f(Points[i].x - TriangleWidth, 0.0); } } glEnd(); } // Plot points as quads -------------------------------------------------------- void plot_quads() { glBegin(GL_QUADS); { for (size_t i = 0; i < Points.size(); i++) { glColor3fv(color_rotate()); glVertex2f(Points[i].x - QuadWidth, Points[i].y); glVertex2f(Points[i].x + QuadWidth, Points[i].y); glVertex2f(Points[i].x + QuadWidth, 0.0); glVertex2f(Points[i].x - QuadWidth, 0.0); } } glEnd(); } // Print text ------------------------------------------------------------------ void print_text(const char *s) { glRasterPos2f(0, YMin - Padding / 2); for (const char *c = s; *c; c++) glutBitmapCharacter(GLUT_BITMAP_8_BY_13, *c); } // Display callback ------------------------------------------------------------ void display() { int ViewportWidth = WindowWidth*2 / PLOT_MODE_UNKNOWN; int ViewportHeight = WindowHeight*3 / PLOT_MODE_UNKNOWN; glClear(GL_COLOR_BUFFER_BIT); for (int m = 0; m < PLOT_MODE_UNKNOWN; m++) { glViewport((m % 3) * ViewportWidth, (m < 3) ? ViewportHeight : 0, ViewportWidth, ViewportHeight); plot_axes(); switch (m) { case PLOT_MODE_POINTS: plot_points(); print_text("points"); break; case PLOT_MODE_CIRCLES: plot_circles(); print_text("circles"); break; case PLOT_MODE_LINE: plot_line(); print_text("line"); break; case PLOT_MODE_FAN: plot_fan(); print_text("fan"); break; case PLOT_MODE_TRIANGLES: plot_triangles(); print_text("triangles"); break; case PLOT_MODE_QUADS: plot_quads(); print_text("quads"); break; } } glFlush(); } // Show usage ------------------------------------------------------------------ void show_usage() { printf("usage: plot [options] \n"); printf("General Options:\n"); printf(" -m Plotting mode (points = 0, circles = 1, line = 2, fan = 3, triangles = 4, quads = 5)\n"); printf(" -p Padding\n"); printf(" -t Thickness of axes/lines\n"); printf(" -h Show this help message\n"); printf("\nWindow Options:\n"); printf(" -W Set window width\n"); printf(" -H Set window height\n"); printf("\nCircle Options:\n"); printf(" -T Number of triangles to use\n"); printf(" -R Radius of circle\n"); printf("\nTriangles Options:\n"); printf(" -B Base width of triangles\n"); printf("\nQuads Options:\n"); printf(" -Q Width of quads\n"); } // Parse command line arguments ------------------------------------------------ void parse_command_line_arguments(int argc, char *argv[]) { int c; while ((c = getopt(argc, argv, "p:t:W:H:T:R:B:Q:h")) >= 0) { switch (c) { case 'p': Padding = strtol(optarg, NULL, 10); break; case 't': Thickness = strtof(optarg, NULL); break; case 'W': WindowWidth = strtol(optarg, NULL, 10); break; case 'H': WindowHeight = strtol(optarg, NULL, 10); break; case 'T': CircleTriangles = strtol(optarg, NULL, 10); break; case 'R': CircleRadius = strtof(optarg, NULL); break; case 'B': TriangleWidth = strtof(optarg, NULL); break; case 'Q': QuadWidth = strtof(optarg, NULL); break; case 'h': show_usage(); exit(EXIT_SUCCESS); break; default: fprintf(stderr, "plot: unknown command line argument %c\n", c); show_usage(); exit(EXIT_FAILURE); break; } } if ((argc - optind) != 1) { show_usage(); exit(EXIT_FAILURE); } else { read_points(argv[optind]); } } // Main execution -------------------------------------------------------------- int main(int argc, char *argv[]) { glutInit(&argc, argv); parse_command_line_arguments(argc, argv); glutInitWindowSize(WindowWidth, WindowHeight); glutCreateWindow("plot"); glutDisplayFunc(display); init(); glutMainLoop(); return (EXIT_SUCCESS); } // vim: sts=4 sw=4 ts=8 ft=cpp