#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 totalTlinesnum=0; // the total tlines num of window query returned void signal_handler(int n) { close(con_sock); exit(0); } /* establish_connection() will do what its name suggests: makes a connection to the server. It will use the global variables host and srv_port as input. Then it will update the value of con_sock, which is the file descriptor of the socket used for communicating with the server. */ void establish_connection() { struct sockaddr_in name; struct hostent *hptr; int flag; /* step (a) create a socket */ con_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); // it is misconception to use "AF_INET" instead of "PF_INET" if (con_sock <= 0) { perror("Open socket failed"); exit(1); } name.sin_family = PF_INET; name.sin_port = htons(srv_port); /* getting the host IP information */ if ((hptr = gethostbyname(host)) == NULL) { perror("gethostbyname"); exit(1); } bcopy(hptr->h_addr, (char *)&name.sin_addr.s_addr, hptr->h_length); printf("Trying to contact %s...\n", host); /* making connection */ flag = connect(con_sock, (struct sockaddr *) &name, sizeof(name)); if (flag < 0) { perror("No connection"); close(con_sock); exit(1); } printf("Connected\n"); } extern int errno; void usage() { fprintf(stderr, "usage: client [-p port]\n"); exit(1); } void connectServer(int argc,char** argv){ /* Received a signal. Close the connection and quit. */ int lg; /* shift the parameters */ argc--; argv++; /* set initial value of the server. */ strcpy(host, "localhost"); while (argc > 0) { if (argv[0][0] != '-') { /* setting new server name */ strcpy(host, argv[0]); argv ++; argc --; continue; } switch (argv[0][1]) { /* setting port number */ case 'p': srv_port = atoi(argv[1]); argv += 2; argc -= 2; break; default: usage(); } } /* Intercept some signals so we can quit the program more gracefully when interrupted by such signals. */ signal(SIGTERM, signal_handler); signal(SIGQUIT, signal_handler); signal(SIGINT, signal_handler); establish_connection(); //make_trans(); } /* readData will do window query */ void readData(double x_left, double x_right, double y_top, double y_bottom) { char buff[1024], out[1024], ftemp[100]; char *c; int lg, flag; double rectangle[4]; int counter=0; flag = 1; rectangle[0]=x_left; rectangle[1]=x_right; rectangle[2]=y_top; rectangle[3]=y_bottom; //for each query, setup a new connection connectServer(argcbak,argvbak); totalTlinesnum = 0; do { /*Jump out to receive data*/ if (counter>=4){ flag=0; break; } sprintf(out, "%f\r\n",rectangle[counter] ); /*printf("x_left=%f\n", x_left); printf("x_right=%f\n", x_right); printf("y_top=%f\n", y_top); printf("y_bottom=%f\n", y_bottom); printf("out=%s\n", out); */ /* write everything to the network. */ lg = write(con_sock, out, strlen(out)); lg = read(con_sock, buff, 1024); if (buff[lg - 1] != '\n' || buff[lg - 2] != '\r') { fprintf(stderr, "Error: Wrong format\r\n"); } /* Display the response to standard put */ buff[lg - 1] = '\0'; buff[lg - 2] = '\n'; //printf("%s\n",buff); counter++; } while (flag); //read map data from Server flag=1; numBlock=0; counter=0; sprintf(out, "ready\r\n"); lg = write(con_sock, out, strlen(out)); do { lg = read(con_sock, TLineBuff, buffMax); /*if (numBlock==5000){ printf("blockNum=%d\n", numBlock); numBlock=0; }*/ if (lg == -1 && errno == EBADF) goto error; if (TLineBuff[lg - 1] != '\n' || TLineBuff[lg - 2] != '\r') { printf(TLineBuff, "Error: Bad receive from Server\r\n"); goto error; } //TLineBuff[lg - 2] = '\0'; //strncpy(c,TLineBuff, 4); if(strncmp(TLineBuff, "done", 4) == 0){ printf("Server data all over\n"); sprintf(out, "quit \r\n"); // tell server quit lg = write(con_sock, out, strlen(out)); flag = 0; break; } else { numBlock++; int i=0; int j=0; /*if (numBlock==31) printf("****num%d=%d****\n",numBlock,totalTlinesnum); */ int doneFlag=1; //rendering the float to do{ ftemp[j]=TLineBuff[i]; j++; i++; if (TLineBuff[i]==' '){ ftemp[j]='\0'; i++; j=0; //printf("%f\n", atof(ftemp)); //Tline[totalTlinesnum][counter]=atof(ftemp); if ( counter == 0 ) resultTLine[totalTlinesnum].startx = atof(ftemp); else if ( counter == 1 ) resultTLine[totalTlinesnum].endx = atof(ftemp); else if ( counter == 2 ) resultTLine[totalTlinesnum].starty = atof(ftemp); else if ( counter == 3 ) resultTLine[totalTlinesnum].endy = atof(ftemp); counter++; if (counter==4){ counter=0; totalTlinesnum++; } if (TLineBuff[i]=='\r'){ doneFlag=0; break; } }; }while((doneFlag)&&(i 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 = totalTlinesnum; 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); readData(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){ readData(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(); readData(win1left,win1right,win1top,win1bottom); drawWindow(); printf("win1 done, draw win2\n"); readData(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(); }