mapquest c++ program

16
Manny Silverstein – Mini MapQuest C++ Project Project Description: Below are some trial run screen-shots and the code for my C++ Programming III (EEN318) final project. The project was done in Microsoft Visual Studio 2012. The data used comes from three text files. One is a list of places in the United States, including information such as their name, state, latitude, longitude, and a reference number to the nearest intersection, which is the line of the intersection file. The second file is the list of intersections. Each intersection has a nearest place, latitude, and longitude. The last file is the connections file, which is a list of roads. Each connection has the two intersections it connects, as well as the name of the road. The assignment was to read in these three files and link them up in a way that you can get from one place to another by following connections that connect the nearest intersections to those places. Once done, the user can enter two places and the program will find the shortest path between the two. The final part of the project was to read in several binary files describing different maps within the US, and using the information to display the map graphically. The files get stored in a two dimensional array, with each point representing a point in the window where the graph is drawn, and given info on the altitude of that point (or if it’s the ocean). When the user searches for two places, the program will display the smallest map that contains both locations and trace the shortest route between them. In my program, the place objects are stored in a hash table, the intersection objects are stored in a large array, with the index number of the array corresponding to the reference number of the intersection (used in the place and connection objects). Connection objects are attached directly to intersection objects as a linked list. If you search for a place that exists in multiple states, the program asks which state the place you’re searching for is in. My shortest path algorithm is a version of Dijkstra’s Algorithm. Scroll to the next page to see screen-shots of sample runs of the project as well as all of the source code.

Upload: manny-silverstein

Post on 23-Oct-2015

36 views

Category:

Documents


3 download

DESCRIPTION

A small scale version of a MapQuest like program. Final project for Programming III (EEN318).

TRANSCRIPT

Page 1: MapQuest C++ Program

Manny Silverstein – Mini MapQuest C++ Project

Project Description:

Below are some trial run screen-shots and the code for my C++ Programming III (EEN318) final project.

The project was done in Microsoft Visual Studio 2012.

The data used comes from three text files. One is a list of places in the United States, including

information such as their name, state, latitude, longitude, and a reference number to the nearest

intersection, which is the line of the intersection file. The second file is the list of intersections. Each

intersection has a nearest place, latitude, and longitude. The last file is the connections file, which is a

list of roads. Each connection has the two intersections it connects, as well as the name of the road.

The assignment was to read in these three files and link them up in a way that you can get from one

place to another by following connections that connect the nearest intersections to those places. Once

done, the user can enter two places and the program will find the shortest path between the two.

The final part of the project was to read in several binary files describing different maps within the US,

and using the information to display the map graphically. The files get stored in a two dimensional

array, with each point representing a point in the window where the graph is drawn, and given info on

the altitude of that point (or if it’s the ocean). When the user searches for two places, the program will

display the smallest map that contains both locations and trace the shortest route between them.

In my program, the place objects are stored in a hash table, the intersection objects are stored in a large

array, with the index number of the array corresponding to the reference number of the intersection

(used in the place and connection objects). Connection objects are attached directly to intersection

objects as a linked list. If you search for a place that exists in multiple states, the program asks which

state the place you’re searching for is in. My shortest path algorithm is a version of Dijkstra’s Algorithm.

Scroll to the next page to see screen-shots of sample runs of the project as well as all of the source code.

Page 2: MapQuest C++ Program

Manny Silverstein EEN318 Final Project

Here’s a sample, finding directions from Miami to Tallahassee:

Page 3: MapQuest C++ Program

Here’s the map drawing for New York to San Diego:

Portland to Seattle:

Page 4: MapQuest C++ Program

Code:

#include "library.h" const int tableSize=50000; //build Place object class Place { public: Place(); Place(int, string, string, string, int, double, double, double, int, double); virtual ~Place(); int state_code; string tract_code; string postal; string name; int population; double area; double latitude; double longitude; int loc_reference; double road_distance; void print(); }; Place::Place() { state_code=0; tract_code=""; postal=""; name=""; population=0; area=0; latitude=0; longitude=0; loc_reference=0; road_distance=0; } Place::Place(int s, string t, string p, string n, int pop, double a, double lat, double longi, int loc, double r) { state_code=s; tract_code=t; postal=p; name=n; population=pop; area=a; latitude=lat; longitude=longi; loc_reference=loc; road_distance=r; } Place::~Place() { } void Place::print() {

Page 5: MapQuest C++ Program

cout << "\n"; cout << name << ", " << postal << "\n"; cout << "Population: " << population << ", Area: " << area << " square miles\n"; cout << "Latitude " << latitude << "N, Longitude " << longitude << "W\n"; cout << road_distance << " miles from intersection " << loc_reference << "\n"; } //build HashLink object to hold Places in Hash table class HashLink { public: Place *current; HashLink *next; HashLink(); HashLink(Place*, HashLink*); virtual ~HashLink(); }; HashLink::HashLink() { current=new Place(); next=NULL; } HashLink::HashLink(Place *P, HashLink *H) { current=P; next=H; } HashLink::~HashLink() { } //Hash function int Hash(string s) { const int init = 21512713, mult = 96169, emergency = 876127; int v = init; for (int i=0; i<s.length(); i+=1) v = v * mult + s[i]; if (v < 0) v = -v; if (v < 0) v = emergency; return v % tableSize; } //build Connection object class Connection { public: string name; string type; int endA; int endB; double miles; Connection *cnext; Connection(); Connection(string, string, int, int, double); ~Connection(); };

Page 6: MapQuest C++ Program

Connection::Connection() { name = ""; type = ""; endA = 0; endB = 0; miles = 0; cnext = NULL; } Connection::Connection(string n, string t, int A, int B, double m) { name = n; type = t; endA = A; endB = B; miles = m; cnext = NULL; } Connection::~Connection() { } //build Intersection object class Intersection { public: double longitude; double latitude; double distance; bool visited; Place *p; Connection *c; Intersection(); Intersection(double, double, double, Place*); ~Intersection(); }; Intersection::Intersection() { longitude=0; latitude=0; distance=0; p=NULL; c=NULL; visited=false; } Intersection::Intersection(double lon, double lat, double dist, Place *pl) { longitude=lon; latitude=lat; distance=dist; p=pl; c=NULL; visited=false; } Intersection::~Intersection() {

Page 7: MapQuest C++ Program

} //various functions to help while reading data in string trim(string s) { s = s.substr((s.find_first_not_of(' ')),(s.find_last_not_of(' ')+1)); return s; } string caps(string s) { for(int i=0; i<s.size(); i++) { if(i==0) { if (s[i] <= 'z' && s[i] >= 'a') s[i] -= 32; } if(s[i]==' ') { if (s[i+1] <= 'z' && s[i+1] >= 'a') s[i+1] -= 32; } if(i>0&&s[i-1]!=' ') { if (s[i]<='Z' && s[i]>='A') s[i] += 32; } } return s; } string postal_caps(string s) { for(int i=0; i<s.size(); i++) { if (s[i] <= 'z' && s[i] >= 'a') s[i] -= 32; } return s; } //data from file reading functions HashLink **readPlaceData(string File) { HashLink **theTable = new HashLink*[tableSize]; for(int i=0; i<tableSize; i++) { theTable[i]=NULL; } string a; ifstream fin; fin.open(File.c_str()); if (fin.fail()) { cout << "Error: Can't read named-places file.\n"; } while(true) { getline(fin,a); if (fin.fail()) break; string state_number = a.substr(0,2); string tract_number = a.substr(2,5); string state = a.substr(7,2); string city = a.substr(9,45); string pop = a.substr(56,7); string area = a.substr(65,10); string lat = a.substr(76,9); string longi = a.substr(85,11); string reference = a.substr(96,5); string distance = a.substr(101,8); city=trim(city);

Page 8: MapQuest C++ Program

pop=trim(pop); area=trim(area); lat=trim(lat); longi=trim(longi); reference=trim(reference); distance=trim(distance); int sn = atol(state_number.c_str()); int popu = atol(pop.c_str()); double are=atof(area.c_str()); double latitude=atof(lat.c_str()); double longitude=atof(longi.c_str()); longitude=longitude*-1; int ref=atol(reference.c_str()); double dist=atof(distance.c_str()); int i=Hash(city); Place *p = new Place(sn, tract_number, state, city, popu, are, latitude, longitude, ref, dist); if(theTable[i]==NULL) { theTable[i]=new HashLink(p, NULL); } else { HashLink *currHash=theTable[i]; while((currHash->next)!=NULL) currHash=(currHash->next); currHash->next=new HashLink(p, NULL); } } return theTable; } Intersection **readIntersectionData(string File, HashLink **S) { Intersection **theList = new Intersection*[30000]; string a; ifstream fin; fin.open(File.c_str()); int k = 0; if (fin.fail()) { cout << "Error: Can't read Intersections file.\n"; } while(true) { getline(fin,a); if (fin.fail()) break; string longi = a.substr(0,9); string lati = a.substr(12,7); string dista = a.substr(21,6); string st = a.substr(28,2); string plce = a.substr(31,37); longi = trim(longi); lati = trim(lati); dista = trim (dista); plce = trim(plce); double lon = atof(longi.c_str()); double lat = atof(lati.c_str()); double dist = atof(dista.c_str()); Place *n = new Place; int i = Hash(plce); HashLink *currHash = S[i]; while(currHash->current->postal!=st) { currHash=currHash->next; if(currHash==NULL) {

Page 9: MapQuest C++ Program

cout << "Error: Could not locate proper Place Object for Intersection line " << k << "/n/n"; break; } } n=currHash->current; theList[k] = new Intersection(lon, lat, dist, n); k++; } return theList; } void readConnectionData(string File, Intersection **I) { ifstream fin; fin.open(File.c_str()); if (fin.fail()) { cout << "Error: Can't read Connections file./n"; } while(true) { if (fin.fail()) break; string n, t, A, B, m; fin >> n >> t >> A >> B >> m; int eA = atol(A.c_str()); int eB = atol(B.c_str()); double mil = atof(m.c_str()); Intersection *currA = I[eA]; Intersection *currB = I[eB]; if(currA->c==NULL) { currA->c=new Connection(n, t, eA, eB, mil); } else { Connection *currcon=currA->c; while((currcon->cnext)!=NULL) currcon=(currcon->cnext); currcon->cnext=new Connection(n, t, eA, eB, mil); } if(currB->c==NULL) { currB->c=new Connection(n, t, eA, eB, mil); } else { Connection *currcon=currB->c; while((currcon->cnext)!=NULL) currcon=(currcon->cnext); currcon->cnext=new Connection(n, t, eA, eB, mil); } } } //finding the shortest path struct path_node { int current; int previous; double distance; path_node(int c, int p, double d) { current=c; previous=p, distance=d; } }; int moving(Connection *C, int I) { if(C->endA==I) { return C->endB; } else if (C->endB==I) { return C->endA; } else { return 0; }

Page 10: MapQuest C++ Program

} int nextnode(path_node **P, Intersection**I) { double min=100000; int i=0; int themin; while(i<30000) { if(P[i]!=NULL) { if(I[i]->visited==false) { if(P[i]->distance<min) { min=P[i]->distance; themin=P[i]->current; } } } i++; } return themin; } void driving(int start, int finish, path_node **P, Intersection **I) { P[start]=new path_node(start, 0, 0); int point = start; Connection *last=NULL; while(point!=finish) { I[point]->visited=true; Connection *tempcon=I[point]->c; double total_distance=P[point]->distance; while(tempcon!=NULL) { int nextint=moving(tempcon,point); if(nextint!=0) { if(I[nextint]->visited==false){ if(P[nextint]==NULL) { P[nextint]=new path_node(nextint, point, total_distance+tempcon->miles); } else { if(total_distance+tempcon->miles<P[nextint]->distance) { P[nextint]=new path_node(nextint, point, total_distance+tempcon->miles); } } } } tempcon=tempcon->cnext; } point=nextnode(P,I); } } int path(Place *A, Place *B, Intersection **I, path_node **P) { int s = A->loc_reference; int f = B->loc_reference; driving(s, f, P, I); cout << "\n-------------------------------------\n\n"; cout << "-------------------------------------\n\nPath found!\n\nDrawing map...\n"; return f; }

Page 11: MapQuest C++ Program

//Place search function Place *search(HashLink **S, Intersection **I) { string a; getline(cin, a); a=caps(a); if (a=="Exit") { return NULL; } int i=Hash(a); HashLink *currHash = S[i]; if(currHash==NULL) { cout << "\n" << "City not found :(" << "\n\n"; return NULL; } while(currHash->current->name!=a) { currHash=currHash->next; if(currHash==NULL) { cout << "\n" << "City not found :(" << endl << endl; return NULL; } } if(currHash->current->name==a&&(currHash->next==NULL||currHash->next->current->name!=a)) { currHash->current->print(); } else { cout << "\n" << "That city exists in "; while(currHash->next!=NULL) { if (currHash->current->name==a) { cout << currHash->current->postal << ", "; currHash=(currHash->next); } } cout << "and " << currHash->current->postal << ".\n"; string t; cout << "Which state are you looking in? "; getline(cin,t); currHash=S[i]; t=postal_caps(t); while(currHash->current->postal!=t) { currHash=currHash->next; if(currHash==NULL) { cout << "City not found :(" << "\n\n"; return NULL; } } currHash->current->print(); } int c = currHash->current->loc_reference; return currHash->current; } //graphics void place_point(Place* P, double mx, double my, int latmax, int longmax) { double lat=P->latitude; double y = my*(lat-latmax); double lon=P->longitude; double x = mx*(lon-longmax);

Page 12: MapQuest C++ Program

set_pen_color(color::red); set_pen_width(12); draw_point(x,y); } void draw_roads(int f, double mx, double my, int latmax, int longmax, Intersection **I, path_node **P) { int curr=f; while(P[curr]->previous!=0) { Intersection *A=I[curr]; Intersection *B=I[P[curr]->previous]; double lata=A->latitude; double ya = my*(lata-latmax); double lona=A->longitude; double xa = mx*(-lona-longmax); double latb=B->latitude; double yb = my*(latb-latmax); double lonb=B->longitude; double xb = mx*(-lonb-longmax); set_pen_color(color::red); set_pen_width(3); move_to(xa,ya); draw_to(xb,yb); curr=P[curr]->previous; } } struct mapcoverage{ int max_lat; int min_lat; int max_lon; int min_lon; string file; mapcoverage(int mla, int mila, int maln, int minln, string f) { max_lat=mla; min_lat=mila; max_lon=-maln; min_lon=-minln; file=f; } }; void binary_map(Place *A, Place *B, int f, Intersection **I, path_node **P) { mapcoverage *mapslist[150]; mapcoverage *themap; ifstream fin("coverage.txt"); int k=0; int min_la, max_la, min_lo, max_lo; string mapfile; while(fin.fail()!=true) { fin >> min_la >> max_la >> min_lo >> max_lo >> mapfile; mapslist[k]=new mapcoverage(min_la, max_la, min_lo, max_lo, mapfile); k++; } k=0; int lonchange=1000, latchange=1000; while(k<150) { if((A->latitude>mapslist[k]->min_lat&&A->latitude<mapslist[k]->max_lat)&&(B->latitude>mapslist[k]->min_lat&&B->latitude<mapslist[k]->max_lat)) { if((A->longitude>mapslist[k]->min_lon&&A->longitude<mapslist[k]->max_lon)&&(B->longitude>mapslist[k]->min_lon&&B->longitude<mapslist[k]->max_lon)){ int templonch, templatch; templonch=mapslist[k]->max_lon-mapslist[k]->min_lon;

Page 13: MapQuest C++ Program

templatch=mapslist[k]->max_lat-mapslist[k]->min_lat; if(templonch<lonchange||templatch<latchange) { themap=mapslist[k]; lonchange=templonch; latchange=templatch; } } } k++; } int maxalt; string datafile=themap->file; int W, N, DLon, DLat; W=themap->max_lon; N=themap->max_lat; DLon=themap->max_lon-themap->min_lon; DLat=themap->max_lat-themap->min_lat; FILE *thefile = fopen(datafile.c_str(),"r"); fseek(thefile, 0, SEEK_END); int filesize = ftell(thefile); fseek(thefile, 0, SEEK_SET); int other; int numrows; if(DLat==DLon) { other=600; const int numcolumns=600; const int rowsize = numcolumns * sizeof(short int); numrows = filesize/rowsize; short int (* a)[numcolumns]; a = new short int[numrows][numcolumns]; int n = fread(a, rowsize, numrows, thefile); int row=0; maxalt=4000; fclose(thefile); double colormap[10000]; int turn=0; int i=0; while (i<=maxalt) { colormap[i]=1-i/(double)maxalt; i++; } if (turn==0) { make_window(numcolumns, numrows); } else { set_window_size(numcolumns, numrows); } int drow=0; while (drow < numrows) { int dcol=0; while (dcol < numcolumns) { int altitude=a[drow][dcol]; if (altitude==-500) { set_pen_color(color::blue); draw_point(dcol, drow); } else { if (altitude<0) { altitude=0; } set_pen_color(0, colormap[altitude], 0); draw_point(dcol, drow); } dcol+=1; } drow+=1; } turn+=1; }

Page 14: MapQuest C++ Program

else{ other=800; const int numcolumns=800; const int rowsize = numcolumns * sizeof(short int); numrows = filesize/rowsize; short int (* a)[numcolumns]; a = new short int[numrows][numcolumns]; int n = fread(a, rowsize, numrows, thefile); int row=0; maxalt=4000; fclose(thefile); double colormap[10000]; int turn=0; int i=0; while (i<=maxalt) { colormap[i]=1-i/(double)maxalt; i++; } if (turn==0) { make_window(numcolumns, numrows); } else { set_window_size(numcolumns, numrows); } int drow=0; while (drow < numrows) { int dcol=0; while (dcol < numcolumns) { int altitude=a[drow][dcol]; if (altitude==-500) { set_pen_color(color::blue); draw_point(dcol, drow); } else { if (altitude<0) { altitude=0; } set_pen_color(0, colormap[altitude], 0); draw_point(dcol, drow); } dcol+=1; } drow+=1; } turn+=1; } double mx, my; my=(double)numrows/((double)(N-DLat)-(double)N); mx=(double)other/((double)(W-DLon)-(double)W); place_point(A,mx,my,N,W); place_point(B,mx,my,N,W); draw_roads(f,mx,my,N,W,I,P); } //printing the directions string compass(double curlon, double curlat, Intersection *nextint) { double ew, ns; int j, k; if(nextint->longitude>curlon) { ew = nextint->longitude-curlon; j=0; } else if(curlon>nextint->longitude) { ew = curlon-nextint->longitude; j=1; } else ew = 0.0; if(nextint->latitude>curlat) { ns = nextint->latitude-curlat; k=0;} else if(curlat>nextint->latitude) { ns = curlat-nextint->latitude; k=1;} else ns = 0.0; if(ew>ns) { if(j==0) return "E"; else if(j==1) return "W";

Page 15: MapQuest C++ Program

} else if(ns>ew) { if(k==0) return "N"; else if(k==1) return "S"; } } void print_directions(Intersection **I, path_node **P, int f){ cout << "\n-------------------------------------\n\n"; cout << "-------------------------------------\n\nDirections:\n\n"; double total_distance=0; Connection *list[30000]; string dir[30000]; int i=0; int temp=f; while(P[temp]->previous!=NULL) { double dist=0; int p = P[temp]->previous; Intersection *m = I[temp]; Connection *c = m->c; int n=moving(c, temp); while(n!=p) { c=c->cnext; n=moving(c, temp); } dist=dist+c->miles; list[i]=c; dir[i]=compass(I[p]->longitude,I[p]->latitude,m); i++; temp=p; } i--; while(i>=0) { double dist=0; if(i>0){ while(list[i]->name==list[i-1]->name) { dist = dist+list[i]->miles; i--; if(i==0) break; } } dist=dist+list[i]->miles; total_distance=total_distance+dist; string h=dir[i]; cout << "\nTake " << list[i]->name << " " << h << " for " << dist << " miles."; i--; } cout << "\n\nTotal distance: " << total_distance << " miles." << endl; } //main void main() { string FileA = "named-places.txt"; string FileB = "intersections.txt"; string FileC = "connections.txt"; cout << "Loading...\n\n"; HashLink **PlaceHash=readPlaceData(FileA); Intersection **InterList=readIntersectionData(FileB, PlaceHash); readConnectionData(FileC, InterList);

Page 16: MapQuest C++ Program

path_node *pathlist[30000]; int i=0; while(i<30000){ pathlist[i]=NULL; i++; } cout << "Please enter first city: "; Place *A=NULL; Place *B=NULL; while(A==NULL) { A=search(PlaceHash, InterList); } cout << "\n\nPlease enter second city: "; while(B==NULL) { B=search(PlaceHash, InterList); } while(A==B) { cout << "\n\nPlease don't pick the same city twice! enter second city: "; B=search(PlaceHash, InterList); } cout << "\nFinding the path...\n\n"; int finish=path(A,B,InterList,pathlist); binary_map(A,B,finish,InterList,pathlist); print_directions(InterList,pathlist,finish); }