CSSE 120 Final C Programming Project—AroundTheWorld

Project Requirements

Overview - Around the world in <many> miles

A 2000 Rose-Hulman graduate named Deming Speed has already made his millions, and after retiring to his lifelong-dream-community of Terre Haute, he plans to take a special trip. He wants to visit several of the largest cities of the world (largest populations, according to the 1993 World Almanac). The question he thinks about in his life of leisure is, "In what order should I visit them?" He has come up with several possible schemes. Two of them are:

1) Alphabetical order.

2) In order from northernmost to southernmost.

For each visitation order, Deming wants to know the total number of miles that he will fly if he starts in the first city and travels to each of the remaining largest cities in the given order, stopping at the last city. You have been hired to help him calculate these distances.

 Because Mr. Speed owns his own fleet of planes, you may assume that there is always a direct flight from city to city, wherever needed.  Because Deming is so well-loved all over the world, every country lets him fly through their airspace.  This means that the distance between cities is the "great circle" distance. 


You have been provided with the city names (in the file cities.dat)  along with their latitudes and longitudes (in degrees, minutes, and direction).  In a second file called simple.dat, we have shown some fake cities for which it should be easy to calculate the distances by hand to check your program's answers.

The base code and data files for this program are  in the AroundTheWorld project in your individual SVN repository.

We have also placed in your repository a working project called TestScores. You should read and understand it during the Session 28 class;  ask your instructor or an in-class assistant about anything you do not understand. Studying the code in that project may help you see how to do some of the things you need to do for this one.  We recommend that you run that code and spend some time understanding it before writing your code for this project.

Requirements

For each of the two possible routes, you should print a table with one line per destination city (in the order in which the cities are visited). Each  line should list (at least) the name of the city, its location (latitude and longitude), the number of miles flown to reach this city from the previous city, and an accumulated distance flown so far on the entire trip. On the first line, the accumulated distance will be 0. Format the table for easy readability.

Print the names of the two cities from the input file that are closest to each other (with an appropriate message).

In addition to printing the above information, you should also provide a menu that allows the user to interactively choose any two cities from the list; the program then calculates and prints the distance (in miles) between those cities.  You may want to write this part of the code first, so you can test your distance function before working on sorting and producing the tables.

Your program should be written in such a way that it can handle any number of cities up to 100. It should determine how many cities to use from what it reads in the data file.  The TestScores project code will be especially useful for this.

You should define a city structure type with fields for each of the data items that your program needs to remember about an individual city.  Then you will need an array of city's.

You are allowed to get help from other people, but the code you turn in should be written and understood by you.

Commit your completed code to your repository.

Distance Function

You will need a function that takes two cities as arguments and calculates the surface distance between them. Test your function by computing and printing the distance between some cities, starting with the ones in simple.dat.

The earth is not a perfect sphere, but for the purpose of this problem you may pretend that it is a sphere.  The average of the polar and equatorial radii of the Earth is 3957 miles; use that number.

 

Using the following website, you can calculate the distance between many pairs of cities, to help you check the results of your function. 

http://www.chemical-ecology.net/java/lat-long.htm

Use type casting in appropriate places if your answers are not correct. You are welcome to use the calculations from that web site (written in JavaScript language) to help you write your C code.  Then you do not have to figure out all of the mathematics behind the calculations. If you find this code hard to read, feel free to use more descriptive variable names.  Note that the numbers in this code come from multiple arrays (nq and nj select the cities), and so there are array subscripts all over the place.  In your code, the distance function will take two cities as its parameters, so there will probably be no arrays involved in the code for that function.  This code's bad example should help you see the value of using descriptive variable names.  How much easier this code would be to read if the author had done so!  Again, don't forget to use type casting  (where they are needed) as you do your calculations.

function caldist(form) {
  var er = 3957
  // Convert latitudes to radians
  var radlat1 = Math.PI * (td[nq] + tm[nq]/60 + ts[nq]/3600)/180
  var radlat2 = Math.PI * (td[nj] + tm[nj]/60 + ts[nj]/3600)/180
  //Convert longitudes to radians
  var radlong1 = Math.PI * (gd[nq] + gm[nq]/60 + gs[nq]/3600)/180
  var radlong2 = Math.PI * (gd[nj] + gm[nj]/60 + gs[nj]/3600)/180  
  //spherical coordinates x=r*cos(ag)sin(at), y=r*sin(ag)*sin(at), z=r*cos(at)  
  //zero ag is up so reverse lat  
  if (tr[nq]=="N") {radlat1=Math.PI/2-radlat1}  
  if (tr[nq]=="S") {radlat1=Math.PI/2+radlat1}  
  if (gr[nq]=="W") {radlong1=Math.PI*2-radlong1}  
  if (tr[nj]=="N") {radlat2=Math.PI/2-radlat2}  
  if (tr[nj]=="S") {radlat2=Math.PI/2+radlat2}  
  if (gr[nj]=="W") {radlong2=Math.PI*2-radlong2}  
  var x1 = er * Math.cos(radlong1)*Math.sin(radlat1)  
  var y1 = er * Math.sin(radlong1)*Math.sin(radlat1)  
  var z1 = er * Math.cos(radlat1)  
  var x2 = er * Math.cos(radlong2)*Math.sin(radlat2)  
  var y2 = er * Math.sin(radlong2)*Math.sin(radlat2)  
  var z2 = er * Math.cos(radlat2)  
  var d = Math.sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2)+(z1-z2)*(z1-z2))  
  //side, side, side, law of cosines and arc cosine
  var theta = Math.acos((er*er+er*er-d*d)/(2*er*er))  
  var distance = theta*er   //arc length is radius times angle.
 

 

Input File Format

Each line of the input file will contain:

A city name: columns 1-20 (if the name is shorter than that, there will be trailing spaces, to bring the total length to 20).
The latitude:
  degrees: columns 22-23
  minutes: columns 25-26
  direction: column 28  (will be N or S)
The longitude:
  degrees: columns 30-32
  minutes: columns 34-35
  direction: column 37   (will be E or W)

 

Grading -- 200 points total

  1. (25) Demonstrate that your program can successfully read and print the data.  If you do the later parts successfully, you will get credit for this automatically.
  2. (40) Demonstrate that your distance function works correctly by calling it with several pairs of cities. If you do part 7 successfully, you will get credit for this automatically.
  3. (30) Print a table of all cities with distances and accumulated distances, as described in the first paragraph under Requirements.  If you are not able to get the sorting parts, it is okay if your table lists the cities in the original order from the input file.
  4. (20) Rearrange the array into alphabetical order, recalculate distances, and print another table.
  5. (20) Rearrange the array in order from north to south, recalculate distances, and print another table.
  6. (10) Calculate which two cities are closest to each other and print their names and their distance apart.
  7. (30) Repeatedly allow the user to choose a pair of cities form the list, and print the distance between them.
  8. (25) Style: reasonable comments, appropriate variable names, breakdown into functions and structures, indenting

Suggestions

You may also want to define a struct type to represent a coordinate (latitude or longitude), which holds degrees, minutes, and direction. Two of these coordinate structs can then be fields of your city struct type.

You may also wish to include some calculated information in your city  structure definition, to avoid repeated recalculation. 

We found that float sometimes loses some accuracy. We suggest that you use type double instead of float in your calculations for more accurate results.

Enhancements

You may earn up to 25 additional points for some creative enhancement, some other interesting thing(s) to do with this data. If you do this, it should appear in your output after the required output. The number of bonus points will depend on quality of your enhancement idea (in your instructor's opinion) and correctness of your implementation of that idea. For example, visiting the cities in order of distance from Indianapolis (shortest distance to longest distance) would be worth 15 points. (The latitude of Indianapolis is 39° 46' N, and the longitude is 86° 9' W.)