#include #include #include #include #include #include #include "state.h" const double EARTH_RADIUS = 6378.388; // the radius of the earth const double PI = 3.1415926; const int numState = 54; // number of states const char* stateName[numState] = { "AK", "AL", "AR", "AZ", "CA", "CO", "CT", "DC", "DE", "FL", "GA", "GU", "HI", "IA", "ID", "IL", "IN", "KS", "KY", "LA", "MA", "MD", "ME", "MI", "MN", "MO", "MS", "MT", "NC", "ND", "NE", "NH", "NJ", "NM", "NV", "NY", "OH", "OK", "OR", "PA", "PR", "RI", "SC", "SD", "TN", "TX", "UT", "VA", "VI", "VT", "WA", "WI", "WV", "WY" }; State state[numState]; const char* map_dir = "data"; // the subdirectory that saves the map data const char* file_suffix = "Lines.txt"; // the suffix of map data file char file_name[128]; // map file name double left_bound,right_bound,bottom_bound,top_bound; // the boundary of the whole USA map const double delta_longitude = 20.0; const double delta_latitude = 10.0; int ScreenWidth=640,ScreenHeight=480; // define the MainScreen Size double Center_Width,Center_Height; // the central point of map when display int Mouse_prex=0,Mouse_prey=0; // the mouse previous position int preMoveX,preMoveY; // the mouse postion when click RIGHT button int ValidMove=0,ValidColor=0;; // the boolean test for mouse-clicking and random color int NevMouseClick = 0; // the boolean test for mouse-clicking in navigation window int Index,Win,MainWin,NevWin,ZoomWin,TitleWin; // the indifier of three windows double range=0.0,ratio=0; //TigerSubdiv sub; // range for Width of map, ratio is Width/Height // set viewport of the window void setViewport(int left, int right, int bottom, int top){ glViewport(left, bottom, right - left, top - bottom); } // redraw window event void myReshape(int W, int H){ double R = (right_bound - left_bound) / (top_bound - bottom_bound); if ( R > double(W)/double(H) ){ setViewport(0, W, 0, (int)(((double)W)/R)); } else { setViewport(0, (int)(((double)H)*R), 0, H); } } /***************************************************************/ /* Label the latitude and longitude lines */ /* x/y is the x-cooridate/y-cooridate center point of map */ /***************************************************************/ void MarkLine(double x,double y) { char buffer[10]; // string buffer int len; // string length void *font=GLUT_BITMAP_HELVETICA_12; // the dislayed fone type glColor3f(1.0,1.0,0.0); // label the longitude for (float i=(ceil((x-range/2)*20))/20;i<(float)(x+range/2);i+=delta_longitude){ glRasterPos2d(i,(y-range*ratio/2)+0.0005); //_itoa(i,buffer,10); sprintf(buffer,"%.2f",i); len=(int) strlen(buffer); for (int j=0;j(float)(y-range*ratio/2);i-=delta_latitude){ //label the latitude glRasterPos2d(x-range/2,i); //_itoa(i,buffer,10); sprintf(buffer,"%.2f",i); len=(int) strlen(buffer); for (int j=0;j=-90.0;i-=delta_latitude){ // latitude line -90 ~ 90 glBegin(GL_LINES); glVertex2d(-180,i); glVertex2d(180,i); glEnd(); } } /***************************************************************/ /* Set the Window Size */ /* x/y : center point of window */ /* width/height : window size */ /***************************************************************/ void SetWindow(double x,double y,double width,double height) { glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(x-width/2,x+width/2,y-height/2,y+height/2); //gluOrtho2D(x/2-width/4,x/2+width/4,y/2-height/4,y/2+height/4); } /***************************************************************/ /* The initial functions */ /***************************************************************/ void MyInit(void) { glClearColor(0.0,0.0,0.0,0.0); glPointSize(2.0); glLineWidth(1.0); srand(time(NULL)); } void drawMap(){ glBegin(GL_LINES); for ( int j = 0; j < numState; j++) { int total = state[j].get_total_lines(); for ( int i=0; i < total; i++){ glVertex2d(state[j].lines[i].startx, state[j].lines[i].starty); glVertex2d(state[j].lines[i].endx, state[j].lines[i].endy); } } glEnd(); } /***************************************************************/ /* The display call-back function for Main Window */ /***************************************************************/ void MainDisplay(void) { glClearColor(0.0,0.0,0.0,0.0); // clear the background glClear(GL_COLOR_BUFFER_BIT); glViewport(0,0,ScreenWidth-ScreenHeight/3,ScreenHeight); ValidColor=1; glColor3f(0.0,0.0,1.0); // indicate now in Main Window drawMap(); if (ratio==0) ratio=(top_bound-bottom_bound)/(right_bound-left_bound); if (range==0){ // store map original information range=right_bound-left_bound; Center_Width=(right_bound+left_bound)/2; Center_Height=(top_bound+bottom_bound)/2; printf("center width = %f\n", Center_Width); printf("center height = %f\n", Center_Height); printf("width = %f\n", range); printf("height = %f\n", range*ratio); SetWindow(Center_Width,Center_Height,range,range*ratio); //SetWindow((right_bound+left_bound)/2,(top_bound+bottom_bound)/2,(right_bound-left_bound)/2,(top_bound-bottom_bound)/2); } DrawLine(); // draw latitude and longitude MarkLine(Center_Width,Center_Height); // label latitude/longitude glFlush(); glutSwapBuffers(); glutPostRedisplay(); } /***************************************************************/ /* The display call-back function for Nevigation Window */ /***************************************************************/ void NevDisplay(void) { glClearColor(0.4,0.4,0.4,0.0); // clear the background glClear(GL_COLOR_BUFFER_BIT); glPushMatrix(); gluOrtho2D(left_bound,right_bound,bottom_bound,top_bound); ValidColor=0; glColor3f(1.0,0.0,1.0); // indicate now in Nevigation Window drawMap(); // draw map lines glColor3f(1.0,1.0,1.0); glBegin(GL_LINE_LOOP); // draw the small rectangle indicating position glVertex2d(Center_Width-range/2,Center_Height-range*ratio/2); glVertex2d(Center_Width+range/2,Center_Height-range*ratio/2); glVertex2d(Center_Width+range/2,Center_Height+range*ratio/2); glVertex2d(Center_Width-range/2,Center_Height+range*ratio/2); glEnd(); glPopMatrix(); glFlush(); glutSwapBuffers(); glutPostRedisplay(); } /***************************************************************/ /* The display call-back function for Zoom Window */ /***************************************************************/ void ZoomDisplay(void) { double x,aspect; char buffer[10]; int len; void *font=GLUT_BITMAP_HELVETICA_12; aspect=range/(right_bound-left_bound); // the map ratio diplayed now x=ScreenHeight/6+log10(aspect)/log10(2)*20; // compute the slider's position if (x<10) // left-bound x=10; if (x>(ScreenHeight/3-10)) // right-bound x=ScreenHeight-10; glPushMatrix(); glClearColor(0.5,0.5,0.5,0.0); // clear the background glClear(GL_COLOR_BUFFER_BIT); gluOrtho2D(0,ScreenHeight/3,0,50); glColor3f(0,0,1); // draw the central small bar glRecti(10,20,(int)x,30); glColor3f(1,1,1); glRecti((int)x,20,ScreenHeight/3-10,30); glColor3f(0.7,0.6,0.3); // draw the slider glBegin(GL_POLYGON); glVertex2d(x+3,35); glVertex2d(x,38); glVertex2d(x-3,35); glVertex2d(x-3,15); glVertex2d(x,12); glVertex2d(x+3,15); glEnd(); glColor3f(0.8,0.3,0.5); // draw the arrows glLineWidth(2.0); glBegin(GL_LINES); glVertex2d(10,10); glVertex2d(ScreenHeight/6-5,10); glVertex2d(ScreenHeight/6+5,10); glVertex2d(ScreenHeight/3-10,10); glEnd(); glBegin(GL_POLYGON); glVertex2d(ScreenHeight/3-10,10); glVertex2d(ScreenHeight/3-18,16); glVertex2d(ScreenHeight/3-18,4); glEnd(); glBegin(GL_POLYGON); glVertex2d(10,10); glVertex2d(18,16); glVertex2d(18,4); glEnd(); glColor3f(1.0,0,0); // display the mark for arrows glRasterPos2d(ScreenHeight/12,0); buffer[0]='I';buffer[1]='N';buffer[2]='\0'; len=(int) strlen(buffer); for (int j=0;j right_bound ) right_bound = bound; bound = state[i].getBottomBound(); if ( bound < bottom_bound ) bottom_bound = bound; bound = state[i].getTopBound(); if ( bound > top_bound ) top_bound = bound; } printf("left_bound = %f\n", left_bound); printf("right_bound = %f\n", right_bound); printf("bottom_bound = %f\n", bottom_bound); printf("top_bound = %f\n", top_bound); /* double A,B,C,D; A = (ScreenWidth-ScreenHeight/3) / (right_bound - left_bound); B = ScreenHeight / (top_bound - bottom_bound); C = -A * left_bound; D = -B * bottom_bound; for ( int j = 0; j < numState; j++) { int total = state[j].get_total_lines(); for ( int i=0; i < total; i++){ state[j].lines[i].startx = A * state[j].lines[i].startx + C; state[j].lines[i].starty = B * state[j].lines[i].starty + D; state[j].lines[i].endx = A * state[j].lines[i].endx + C; state[j].lines[i].endy = B * state[j].lines[i].endy + D; } } */ } // getUSBoundary() /***************************************************************/ /* Compute distance between 2 points, */ /* where x is longtitude, y is latitude */ /***************************************************************/ double euclidean_dist(Point2 p1, Point2 p2){ double q1, q2, q3; q1 = cos(PI*(p1.x-p2.x)/180.0); q2 = cos(PI*(p1.y-p2.y)/180.0); q3 = cos(PI*(p1.y+p2.y)/180.0); return EARTH_RADIUS * acos( 0.5*((1.0+q1)*q2 - (1.0-q1)*q3) ) + 1.0; } void changeCoordinates(){ Point2 center, p, p1, p2; double d1, d2; center.x = (right_bound+left_bound)/2; center.y = (top_bound+bottom_bound)/2; printf("center.x = %f\n", center.x); printf("center.y = %f\n", center.y); p1.x = left_bound; p1.y = bottom_bound; p2.x = right_bound; p2.y = bottom_bound; d1 = euclidean_dist(p1,p2); printf("width=%f\n", d1); // bottom width > top width left_bound = -d1/2; right_bound = d1/2; p1.x = left_bound; p1.y = top_bound; p2.x = left_bound; p2.y = bottom_bound; d2 = euclidean_dist(p1,p2); printf("height=%f\n", d2); top_bound = d2/2; bottom_bound = -d2/2; for ( int j = 0; j < numState; j++) { int total = state[j].get_total_lines(); for ( int i=0; i < total; i++){ p.x = state[j].lines[i].startx; p.y = state[j].lines[i].starty; d1 = euclidean_dist(center, p); p.x = center.x; // the y_oriented distance is accurate d2 = euclidean_dist(center, p); if ( state[j].lines[i].startx < center.x ) state[j].lines[i].startx = -sqrt(d1*d1-d2*d2); else state[j].lines[i].startx = sqrt(d1*d1-d2*d2); if ( state[j].lines[i].starty < center.y ) state[j].lines[i].starty = -d2; else state[j].lines[i].starty = d2; p.x = state[j].lines[i].endx; p.y = state[j].lines[i].endy; d1 = euclidean_dist(center, p); p.x = center.x; // the y_oriented distance is accurate d2 = euclidean_dist(center, p); if ( state[j].lines[i].endx < center.x ) state[j].lines[i].endx = -sqrt(d1*d1-d2*d2); else state[j].lines[i].endx = sqrt(d1*d1-d2*d2); if ( state[j].lines[i].endy < center.y ) state[j].lines[i].endy = -d2; else state[j].lines[i].endy = d2; //printf("startx = %f, starty = %f\n", state[j].lines[i].startx, state[j].lines[i].starty); } } // for j } // changeCoordinates() /***************************************************************/ /* Program Main Function */ /***************************************************************/ void main(int argc, char* argv[]) { getUSBoundary(); for ( int j = 0; j < numState; j++) { state[j].setName(stateName[j]); strcpy(file_name, map_dir); strcat(file_name, "/"); strcat(file_name, state[j].getName()); strcat(file_name, file_suffix); state[j].readStateMap(file_name); } //changeCoordinates(); // Create Main Window glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB); glutInitWindowSize(ScreenWidth,ScreenHeight); glutInitWindowPosition(150,150); MainWin=glutCreateWindow("Tiger Nevigation"); MyInit(); // define call-back function glutDisplayFunc(MainDisplay); glutMouseFunc(MainMouse); glutMotionFunc(MainMovedMouse); glutKeyboardFunc(MainKeyboard); // Create Nevigation Window and Define Call-back function NevWin=glutCreateSubWindow(MainWin,ScreenWidth-ScreenHeight/3,0,ScreenHeight/3,ScreenHeight/3); glutDisplayFunc(NevDisplay); glutKeyboardFunc(NevKeyboard); glutMouseFunc(NevMouse); // Create Nevigation Window and Define Call-back function ZoomWin=glutCreateSubWindow(MainWin,ScreenWidth-ScreenHeight/3,ScreenHeight/3+10,ScreenHeight/3,50); glutDisplayFunc(ZoomDisplay); glutKeyboardFunc(ZoomKeyboard); //Create Title Window and Define Call-back funtion TitleWin=glutCreateSubWindow(MainWin,ScreenWidth-ScreenHeight/3, ScreenHeight/3+70, ScreenHeight/3, 2*ScreenHeight/3-70); glutDisplayFunc(TitleDisplay); glutReshapeFunc(myReshape); // reshape window event glutSetWindow(MainWin); glutMainLoop(); }