/* * Webbased Visualizaion, Homework 3 */ #include #include #include #include "hw3.h" #include "Pixmap.h" float xdist(const Point2& p1, const Point2& p2) { return p2.x - p1.x; } float ydist(const Point2& p1, const Point2& p2) { return p2.y - p1.y; } Point2 center(Point2 p1, Point2 p2) { return Point2(p1.x + (xdist(p1, p2) / 2), p1.y + (ydist(p1, p2) / 2)); } Point2 pmin, pmax; Point2 originalPmin, originalPmax; int mainWindow, viewWindow, zoomWindow, sliderWindow; int screenScale = 0; const float MIN_ZOOM = 1; const float MAX_ZOOM = 32; float zoomRatio = 3; float transX = 0; float transY = 0; IntPoint lastMousePos(0, 0); IntPoint rasterPos(0, 0); RGBpixmap pixmap; enum DrawingState { REDRAW_ALL, DRAGGING, DONE_DRAGGING }; DrawingState redrawState = REDRAW_ALL; Box lastBox; LineFinder *lineFinder = NULL; void draw_map(LineList& ll) { // cerr << "drawing list of " << ll.size() << " elements" << endl; for (LineList::iterator ii = ll.begin(); ii != ll.end(); ii++) { Line *l = *ii; glBegin(GL_LINE_STRIP); for (Point2List::iterator jj = l->points.begin(); jj != l->points.end(); jj++) { glVertex2f((*jj).x, (*jj).y); } glEnd(); } } void reshapeMain(int w, int h) { glutSetWindow(zoomWindow); glutReshapeWindow(100, 100); glutPositionWindow(0, 0); glutSetWindow(sliderWindow); glutReshapeWindow(w - 100, 100); glutPositionWindow(100, 0); glutSetWindow(viewWindow); glutReshapeWindow(w, h - 100); glutPositionWindow (0, 100); glutSetWindow(mainWindow); } void redrawAll() { glutPostWindowRedisplay(viewWindow); glutPostWindowRedisplay(zoomWindow); glutPostWindowRedisplay(sliderWindow); } void reshapeView(int w, int h) { // make sure we don't get division by 0 if(h == 0) { h = 1; } float dx = (pmax.x - pmin.x) / 2; float dy = (pmax.y - pmin.y) / 2; float cx = pmin.x + dx; float cy = pmin.y + dy; float wr = dx / dy; float r = (float) w / h; float ndx = dx; float ndy = dy; if (wr > r) { ndy = dx / r; } else { ndx = dy * r; } pmin.x = cx - ndx; pmin.y = cy - ndy; pmax.x = cx + ndx; pmax.y = cy + ndy; glViewport(0, 0, w, h); } void glDrawRect(GLenum type, float x1, float y1, float x2, float y2) { glBegin(type); glVertex2f(x1, y1); glVertex2f(x1, y2); glVertex2f(x2, y2); glVertex2f(x2, y1); glEnd(); } void glLineLoop(float x1, float y1, float x2, float y2) { glDrawRect(GL_LINE_LOOP, x1, y1, x2, y2); } void glLineLoop(Point2 p1, Point2 p2) { glLineLoop(p1.x, p1.y, p2.x, p2.y); } void displayZoom() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(pmin.x, pmax.x, pmin.y, pmax.y); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClear(GL_COLOR_BUFFER_BIT); // draw border glColor3f(0, 0, 0); glLineLoop(pmin, pmax); glPushMatrix(); Point2 c = center(pmin, pmax); glTranslatef(c.x, c.y, 0); glScalef(1/zoomRatio, 1/zoomRatio, 1); glTranslatef(-c.x, -c.y, 0); glTranslatef(-transX, -transY, 0); glColor3f(0.5, 0.5, 0.5); glRectf(pmin.x, pmin.y, pmax.x, pmax.y); glColor3f(0, 0, 0); glLineLoop(pmin, pmax); glPopMatrix(); glutSwapBuffers(); } void displaySlider() { float w = glutGet(GLUT_WINDOW_WIDTH); float h = glutGet(GLUT_WINDOW_HEIGHT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0, w, 0, h); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glClear(GL_COLOR_BUFFER_BIT); // draw window border glColor3f(0, 0, 0); glLineLoop(0, 0, w, h); float sliderH = h / 4; float sliderW = w - w / 10; float sliderL = sliderW * (zoomRatio / MAX_ZOOM); glColor3f(0.5, 0.5, 0.5); glRectf((w - sliderW) / 2, (h - sliderH) / 2, (w - sliderW) / 2 + sliderL, (h - sliderH) / 2 + sliderH); // draw slider border glColor3f(0, 0, 0); glLineLoop((w - sliderW) / 2, (h - sliderH) / 2, (w - sliderW) / 2 + sliderW, (h - sliderH) / 2 + sliderH); glutSwapBuffers(); } void displayMain() { } void calculateBox(Box& box) { Point2 a = box.min(); Point2 b = box.max(); // cerr << "pre: " << a << " " << b << endl; // pan a.x -= transX / zoomRatio; b.x -= transX / zoomRatio; a.y -= transY / zoomRatio; b.y -= transY / zoomRatio; // zoom float dx = (b.x - a.x) / 2; float dy = (b.y - a.y) / 2; float cx = a.x + dx; float cy = a.y + dy; dx /= zoomRatio; dy /= zoomRatio; a.x = cx - dx; b.x = cx + dx; a.y = cy - dy; b.y = cy + dy; // cerr << "post: " << a << " " << b << endl; box = Box(a, b); } void drawBox(Box& box) { Point2 min = box.min(); Point2 max = box.max(); glColor3f(1, 1, 1); glRectf(min.x, min.y, max.x, max.y); glColor3f(0, 0, 0); LineList *ll = lineFinder->findLines(box); draw_map(*ll); // delete(ll); } void redrawView() { glClear(GL_COLOR_BUFFER_BIT); Box box(pmin, pmax); calculateBox(box); lastBox = box; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(box.min().x, box.max().x, box.min().y, box.max().y); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); drawBox(box); } void drawPixmap() { glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, glutGet(GLUT_WINDOW_WIDTH), 0.0, glutGet(GLUT_WINDOW_HEIGHT)); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); pixmap.draw(rasterPos.x, rasterPos.y); } void updateBoxes() { Box box(pmin, pmax); calculateBox(box); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(box.min().x, box.max().x, box.min().y, box.max().y); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); BoxList bl = box.intersection(lastBox.min().x - box.min().x, lastBox.min().y - box.min().y); lastBox = box; for (BoxList::iterator ii = bl.begin(); ii != bl.end(); ii++) { Point2 a = (*ii).min(); Point2 b = (*ii).max(); // cerr << "drawing: " << a << " " << b << endl; // glColor3f(0, 0, 0); // glLineLoop(a, b); drawBox(*ii); } } void displayView() { glutSetWindow(viewWindow); switch (redrawState) { case REDRAW_ALL: redrawView(); break; case DRAGGING: drawPixmap(); break; case DONE_DRAGGING: updateBoxes(); break; } glutSwapBuffers(); } void displayBuffer() {} void zoom(float factor) { float f = zoomRatio * factor; if (f >= MIN_ZOOM && f <= MAX_ZOOM) { zoomRatio = f; redrawState = REDRAW_ALL; redrawAll(); } } void pan(float dx, float dy) { transX += dx; transY += dy; redrawAll(); } void mouse_pressed(int button, int state, int mx, int my) { glutSetWindow(viewWindow); if (state == GLUT_DOWN) { lastMousePos.set(mx, my); int w = glutGet(GLUT_WINDOW_WIDTH); int h = glutGet(GLUT_WINDOW_HEIGHT); pixmap.read(0, 0, w, h); glPixelStorei(GL_UNPACK_ROW_LENGTH, pixmap.nCols); rasterPos.set(0, 0); lastMousePos.x = mx; lastMousePos.y = my; redrawState = DRAGGING; } else { redrawState = DONE_DRAGGING; redrawAll(); } } void mouse_dragged(int mx, int my) { float ww = pmax.x - pmin.x; float wh = pmax.y - pmin.y; float w = glutGet(GLUT_WINDOW_WIDTH); float h = glutGet(GLUT_WINDOW_HEIGHT); float dx = mx - lastMousePos.x; float dy = my - lastMousePos.y; pan((ww / w) * dx, (wh / h) * dy * -1); rasterPos.x -= mx - lastMousePos.x; rasterPos.y -= lastMousePos.y - my; lastMousePos.set(mx, my); } void kbd_function(unsigned char key, int mx, int my) { switch(key) { case '-': case 'o': zoom(0.5); break; case '=': case 'i': zoom(2); break; } } LineFinder *initNetworkLineFinder(int argc, char *argv[]) { if (argc < 3) { cerr << "usage: " << argv[0] << " HOST PORT" << endl; exit(1); } string host(argv[1]); int port = atoi(argv[2]); return new NetworkLineFinder(host, port); } LineFinder *initSimpleLineFinder(int argc, char *argv[]) { StringList ls; int count = 0; for (int i = 1; i < argc; i++) { ls.push_back(string(argv[i])); count++; } return new SimpleLineFinder(loadCountry(ls)); } int main(int argc, char *argv[]) { string s = string("HW3"); #ifdef STANDALONE lineFinder = initSimpleLineFinder(argc, argv); #else lineFinder = new CachedLineFinder(initNetworkLineFinder(argc, argv), 5); #endif Box bounds = lineFinder->getBoundaries(); originalPmax = pmax = bounds.max(); originalPmax = pmin = bounds.min(); // init GL glutInit(&argc, argv); // initialize the toolkit glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB); // set display mode glutInitWindowSize(640, 480); // set window size glutInitWindowPosition(100, 150); // set window position on screen mainWindow = glutCreateWindow(s.c_str()); // open the screen window glutKeyboardFunc(kbd_function); glutDisplayFunc(displayMain); glutReshapeFunc(reshapeMain); glClearColor(1.0, 1.0, 1.0, 0.0); glColor3f(0.0f, 0.0f, 0.0f); zoomWindow = glutCreateSubWindow(mainWindow, 0, 0, 100, 100); glutKeyboardFunc(kbd_function); glutDisplayFunc(displayZoom); glClearColor(1.0, 1.0, 1.0, 0.0); glColor3f(0.0f, 0.0f, 0.0f); sliderWindow = glutCreateSubWindow(mainWindow, 100, 0, 640 - 100, 100); glutKeyboardFunc(kbd_function); glutDisplayFunc(displaySlider); glClearColor(1.0, 1.0, 1.0, 0.0); glColor3f(0.0f, 0.0f, 0.0f); viewWindow = glutCreateSubWindow(mainWindow, 0, 100, 640, 480 - 100); glutKeyboardFunc(kbd_function); glutDisplayFunc(displayView); glutReshapeFunc(reshapeView); glutMouseFunc(mouse_pressed); glutMotionFunc(mouse_dragged); glClearColor(0.8, 0.8, 0.8, 0.0); glColor3f(0.0f, 0.0f, 0.0f); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glutMainLoop(); }