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.
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.
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.
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)
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.
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.)