#include #include #include #include #include #include #include "state.h" #include "RGBpixmap.h" #include #include #include #include #include #include #include #include #include #include const int buffMax=1000; const int MAX_POINTS=2000000; int con_sock; int srv_port = 1234; char host[128]; double TLine[MAX_POINTS][4]; char TLineBuff[buffMax]; int argcbak; char **argvbak; Line* resultTLine; // the result of query const double EARTH_RADIUS = 6378.388; // the radius of the earth const double PI = 3.1415926; const int numState = 53; // 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 double center_longitude, center_latitude; const double delta_longitude = 20.0; const double delta_latitude = 10.0; mRGB* pixel; int numBlock=0; int first_time=0; // see if need to copy buffer int b_redraw=0; // see if need to redraw the window query int whole_redraw=0; // see if need to redraw the whole window int initX=150,initY=150; // the initial windows position 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 double panx,pany; // the panning parameters based on buffer cordinate int ValidMove=0,ValidColor=0;; // the boolean test for mouse-clicking and random color int Index,Win,MainWin,NevWin,ZoomWin,TitleWin; // the indifier of three windows int NevMouseClick = 0; // the boolean test for mouse-clicking in navigation window //IntPoint rasterPos(0,0); // rasterPos for drawing image //IntPoint lastMousePos(0,0); // differential position for mouse motion double win1left,win1right,win1top,win1bottom; //the firt query window double win2left,win2right,win2top,win2bottom; //the second query window double range=0.0,ratio=0; //TigerSubdiv sub; // range for Width of map, ratio is Width/Height int total_tline_num=0; // the total tlines num of window query returned void getTLine(double x_left, double x_right, double y_top, double y_bottom) { int stateIndex[numState]; int file_num = 0; total_tline_num = 0; for ( int j = 0; j < numState; j++) { double state_left = state[j].getLeftBound(); double state_right = state[j].getRightBound(); double state_top = state[j].getTopBound(); double state_bottom = state[j].getBottomBound(); //printf("state_left=%d\n", state_left); //printf("state_right=%d\n", state_right); //printf("state_bottom=%d\n", state_bottom); //printf("state_top=%d\n", state_top); int count=0; if (x_left>=state_left && x_left<=state_right && y_bottom<=state_bottom && y_top>=state_bottom) { count++; } if (x_left>=state_left && x_left<=state_right && y_bottom<=state_top && y_top>=state_top) { count++; } if (x_left>=state_left && x_left<=state_right && y_top>=state_top && y_bottom<=state_bottom) { count++; } if (x_right>=state_left && x_right<=state_right && y_bottom>=state_bottom && y_top<=state_top) { count++; } if (x_right>=state_left && x_right<=state_right && y_bottom<=state_bottom && y_top>=state_bottom) { count++; } if (x_right>=state_left && x_right<=state_right && y_bottom<=state_top && y_top>=state_top) { count++; } if (x_right>=state_left && x_right<=state_right && y_top>=state_top && y_bottom<=state_bottom) { count++; } if (x_right>=state_left && x_right<=state_right && y_top<=state_top && y_bottom>=state_bottom) { count++; } if (x_left<=state_left && x_right>=state_right && y_bottom<=state_bottom && y_top>=state_bottom) { count++; } if (x_left<=state_left && x_right>=state_right && y_bottom<=state_top && y_top>=state_top) { count++; } if (x_left<=state_left && x_right>=state_right && y_bottom>=state_bottom && y_top<=state_top) { count++; } if (x_left<=state_left && x_right>=state_right && y_bottom<=state_bottom && y_top>=state_top) { count++; } if (x_left>=state_left && x_right<=state_right && y_bottom<=state_bottom && y_top>=state_bottom) { count++; } if (x_left>=state_left && x_right<=state_right && y_bottom<=state_top && y_top>=state_top) { count++; } if (x_left>=state_left && x_right<=state_right && y_bottom>=state_bottom && y_top<=state_top) { count++; } if (x_left>=state_left && x_right<=state_right && y_bottom<=state_bottom && y_top>=state_top) { count++; } if (count>=1) { //printf("FileNum=%d\n",file_num); stateIndex[file_num] = j; file_num++; } } // end for state // determine if the lines are in the boundary printf("total state file_num=%d\n", file_num); for (int i = 0; i < file_num; i++ ) { // i is for state index int k = stateIndex[i]; for (int j = 0; j < state[k].get_total_lines(); j++){ // j is for line index int count = 0; double point_top; double point_bottom; double point_left; double point_right; if ( state[k].lines[j].startx < state[k].lines[j].endx ){ point_left = state[k].lines[j].startx; point_right = state[k].lines[j].endx; } else { point_left = state[k].lines[j].endx; point_right = state[k].lines[j].startx; } if ( state[k].lines[j].starty < state[k].lines[j].endy ){ point_top = state[k].lines[j].endy; point_bottom = state[k].lines[j].starty; } else { point_top = state[k].lines[j].starty; point_bottom = state[k].lines[j].endy; } if (point_top>=y_top && point_bottom<=y_top) { if (point_right<=x_right && point_left>=point_left) { count++; } else if (point_left<=x_left && point_right>=x_left) { count++; } else if (point_right>=x_right && point_left<=x_right) { count++; } else if (point_right>=x_left && point_left<=x_left) { count++; } } else if (point_top<=y_top && point_bottom>=y_bottom) { if (point_left<=x_left && point_right>=x_left) { count++; } else if (point_right>=x_right && point_left<=x_right) { count++; } else if (point_right<=x_right && point_left>=x_left) { count++; } else if (point_right>=x_right && point_left<=x_left) { count++; } } else if (point_top>=y_bottom && point_bottom<=y_bottom) { if (point_right<=x_right && point_left>=point_left) { count++; } else if (point_left<=x_left && point_right>=x_left) { count++; } else if (point_right>=x_right && point_left<=x_right) { count++; } else if (point_right>=x_left && point_left<=x_left) { count++; } } //printf("count=%d\n", count); if (count>=1) { resultTLine[total_tline_num].startx = state[k].lines[j].startx; resultTLine[total_tline_num].endx = state[k].lines[j].endx; resultTLine[total_tline_num].starty = state[k].lines[j].starty; resultTLine[total_tline_num].endy = state[k].lines[j].endy; total_tline_num++; } // if } // end for j } // end for i } // end of getTLine() // 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*range/120){ // 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); } /***************************************************************/ /* The initial functions */ /***************************************************************/ void MyInit(void) { glClearColor(0.0,0.0,0.0,0.0); glPointSize(2.0); glLineWidth(1.0); srand(time(NULL)); pixel = new mRGB[(ScreenWidth-ScreenHeight/3)*ScreenHeight]; } 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(); } void drawWindow(){ glBegin(GL_LINES); for ( int j = 0; j < numState; j++) { int total = total_tline_num; for ( int i=0; i < total; i++){ glVertex2d(resultTLine[i].startx, resultTLine[i].starty); glVertex2d(resultTLine[i].endx, resultTLine[i].endy); } } glEnd(); } void copy(int x1, int y1, int width, int height, double panx, double pany) { // copy a region of the display back onto the display if(first_time==0) return; delete []pixel; pixel = new mRGB[(ScreenWidth-ScreenHeight/3)*ScreenHeight]; //tell OpenGL NOT to try to align pixels to 4 byte boundaries in memory glPixelStorei(GL_PACK_ALIGNMENT,1); glReadPixels(x1, y1, width, height, GL_RGB, GL_UNSIGNED_BYTE,pixel); glClearColor(0.0,0.0,0.0,0.0); // clear the background glClear(GL_COLOR_BUFFER_BIT); double rx=Center_Width-range/2; double ry=Center_Height-range*ratio/2; printf("copy buffer\n"); glPushMatrix(); if (panx <= 0 && pany <= 0) { // drag left and down glRasterPos2d(rx, ry); } else if (panx<= 0 && pany >= 0) { // drag left and up glRasterPos2d(rx,ry+pany); } else if (panx>=0 && pany<= 0) { // drag right and down glRasterPos2d(rx+panx, ry); } else { // (panx>= 0 && pany>= 0), drag right and up glRasterPos2d(rx+panx,ry+pany); } //glRasterPos2d(Center_Width-range/2,Center_Height-range*ratio/2); //tell OpenGL NOT to try to align pixels to 4 byte boundaries in memory glPixelStorei(GL_UNPACK_ALIGNMENT,1); glDrawPixels(width, height, GL_RGB, GL_UNSIGNED_BYTE,pixel); glPopMatrix(); // use the ordinary method provided by Professor didn't work for our project. :( //draw(rasterPos.x,rasterPos.y); } /***************************************************************/ /* The display call-back function for Main Window */ /***************************************************************/ void MainDisplay(void) { if (first_time==0){ glClearColor(0.0,0.0,0.0,0.0); // clear the background glClear(GL_COLOR_BUFFER_BIT); printf("clear buffer\n"); first_time=1; } //copy between two buffers, assign the window position which need to be saved if (((panx>range)||(-panx>range))&&((pany>(range*ratio))||(-pany>(range*ratio)))){ panx=0; pany=0; whole_redraw=1; printf("out of range, no copy\n"); } int px,py; if (range!=0){ px=(int)(panx/range*(ScreenWidth-ScreenHeight/3)); py=(int)(pany/(range*ratio)*ScreenHeight); } else { //(range==0) px=0; py=0; } if ((px!=0)||(py!=0)){ printf("%d******%d\n",px,py); //the panX&Y in viewport if ((px>=0)&&(py>=0)){ //right and up copy(0,0,ScreenWidth-ScreenHeight/3-px,ScreenHeight-py,panx,pany); win1left=Center_Width-range/2; win1right=Center_Width-range/2+panx; win1top=Center_Height+range*ratio/2; win1bottom=Center_Height-range*ratio/2; win2left=Center_Width-range/2+panx; win2right=Center_Width+range/2; win2top=Center_Height-range*ratio/2+pany; win2bottom=Center_Height-range*ratio/2; } else if ((px<=0)&&(py<=0)){//left and down copy(-px,-py,ScreenWidth-ScreenHeight/3+px,ScreenHeight+py,panx,pany); win1left=Center_Width-range/2; win1right=Center_Width+range/2; win1top=Center_Height+range*ratio/2; win1bottom=Center_Height+range*ratio/2+pany; win2left=Center_Width+range/2+panx; win2right=Center_Width+range/2; win2top=Center_Height+range*ratio/2+pany; win2bottom=Center_Height-range*ratio/2; } else if ((px>=0)&&(py<=0)){//right and down copy(0,-py,ScreenWidth-ScreenHeight/3-px,ScreenHeight+py,panx,pany); win1left=Center_Width-range/2; win1right=Center_Width-range/2+panx; win1top=Center_Height+range*ratio/2; win1bottom=Center_Height-range*ratio/2; win2left=Center_Width-range/2+panx; win2right=Center_Width+range/2; win2top=Center_Height+range*ratio/2; win2bottom=Center_Height+range*ratio/2+pany; } else if ((px<=0)&&(py>=0)){//left and up copy(-px,0,ScreenWidth-ScreenHeight/3+px,ScreenHeight-py,panx,pany); win1left=Center_Width-range/2; win1right=Center_Width+range/2; win1top=Center_Height-range*ratio/2+pany; win1bottom=Center_Height-range*ratio/2; win2left=Center_Width+range/2+panx; win2right=Center_Width+range/2; win2top=Center_Height+range*ratio/2; win2bottom=Center_Height-range*ratio/2+pany; } //copy(0,0,ScreenWidth-ScreenHeight/3,ScreenHeight,panx,pany); panx=0; pany=0; glFlush(); glutSwapBuffers(); glutPostRedisplay(); } //the part A, redraw everything. Just for test, will be substituted by window queries glViewport(0,0,ScreenWidth-ScreenHeight/3,ScreenHeight); ValidColor=1; glColor3f(0.0,0.0,1.0); // indicate now in Main Window if (ratio==0) ratio=(top_bound-bottom_bound)/(right_bound-left_bound); if (range==0){ // store map original information //SetWindow((right_bound+left_bound)/2,(top_bound+bottom_bound)/2,(right_bound-left_bound),(top_bound-bottom_bound)); range=(right_bound-left_bound)*0.1; Center_Width=(right_bound+left_bound)/2; Center_Height=(top_bound+bottom_bound)/2; SetWindow(Center_Width,Center_Height,range,range*ratio); getTLine(Center_Width - range/2,Center_Width+range/2,Center_Height+range*ratio/2,Center_Height - range*ratio/2); drawWindow(); DrawLine(); glFlush(); glutSwapBuffers(); glutPostRedisplay(); } else if (whole_redraw==1){ getTLine(Center_Width - range/2,Center_Width+range/2,Center_Height+range*ratio/2,Center_Height - range*ratio/2); drawWindow(); DrawLine(); glFlush(); glutSwapBuffers(); glutPostRedisplay(); whole_redraw=0; } else { //only redraw when changes occured //drawMap(); if (b_redraw==1) { //readData(Center_Width - range/2,Center_Width,Center_Height,Center_Height - range*ratio/2); //drawWindow(); getTLine(win1left,win1right,win1top,win1bottom); drawWindow(); printf("win1 done, draw win2\n"); getTLine(win2left,win2right,win2top,win2bottom); drawWindow(); b_redraw=0; DrawLine(); // draw latitude and longitude //temprarily removed //MarkLine(Center_Width,Center_Height); // label latitude/longitude glFlush(); glutSwapBuffers(); glutPostRedisplay(); } } } /***************************************************************/ /* The display call-back function for Nevigation Window */ /***************************************************************/ void NevDisplay(void) { //if (first_Nevtime==0){ glClearColor(0.4,0.4,0.4,0.0); // clear the background glClear(GL_COLOR_BUFFER_BIT); // first_Nevtime=1; //} 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(); //if (first_Zoomtime==0){ glClearColor(0.5,0.5,0.5,0.0); // clear the background glClear(GL_COLOR_BUFFER_BIT); // first_Zoomtime=1; //} 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); center_longitude = (left_bound + right_bound)/2; center_latitude = (bottom_bound + top_bound)/2; } // getUSBoundary() /***************************************************************/ /* 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); } resultTLine = (Line*)malloc(MAX_POINTS*sizeof(Line)); /*for ( int j = 0; j < size; j++) { strcpy(file_name, map_dir); strcat(file_name, "/"); strcat(file_name, FILE_NAME[j]); strcpy(FILE_NAME[j],file_name); printf("%s\n",FILE_NAME[j]); }*/ // Create Main Window glutInit(&argc,argv); glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGB); glutInitWindowSize(ScreenWidth,ScreenHeight); glutInitWindowPosition(initX,initY); MainWin=glutCreateWindow("Tiger Nevigation"); // the next three lines are essential for the // glRasterPos2i(x,y) to work properly! glMatrixMode(GL_PROJECTION); gluOrtho2D(0.0, (GLdouble)(ScreenWidth-ScreenHeight/3), 0.0, (GLdouble)ScreenHeight); glMatrixMode(GL_MODELVIEW); argcbak=argc; argvbak=argv; MyInit(); //connectServer(argc,argv); // 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); glPixelStorei(GL_UNPACK_ALIGNMENT,1); glutMainLoop(); }