Lab Assignment -- WSU Tri-Cities CptS 121 (Spring, 2017)

Lab 5: Functions

This lab will develop your skills in calling and writing functions.

This page will be available as

http://www.tricity.wsu.edu/~bobl/cpts121/lab05_functions/writeup.html

Calling it up in a browser will allow you to cut-and-paste the templates below into your editor and save editing time.

Plug your thumbdrive into your workstation and, in a MinGW terminal emulator, create a new directory for this lab and cd to it:

$ cd /e/cpts121
$ mkdir lab05
$ cd lab05

As before, keep all your work in this directory.

We'll develop a program crow_fly that computes the distance in kilometers between any two points on Earth, given their latitudes and longitudes. Here's the template:

#include <stdio.h>
#include <math.h> // for M_PI and trig functions

double dmsToRadians(double dms[3])
{
    /*
     * converts the values in the 3-element array `dms` (degrees,
     * minutes, and seconds) to a single double value in radians and
     * returns it
     *
     * pseudocode:
     *     convert dms[] into a single (fractional) degree value
     *     convert the degree value to radians and return that value
     */
}

void polarToCartesian(double latitude[3], double longitude[3],
                      double position[3])
{
    /*
     * converts `latitude` and `longitude` (both are 3-element --
     * degrees, minutes, and seconds -- arrays) to `position`: a
     * 3-element double array in Cartesian (x, y, and z) coordinates
     * on the unit sphere.
     *
     * pseudocode:
     *     convert latitude to a polar angle `theta` using
     *       dmsToRadians()
     *     convert longitude to an azimuthal angle `phi` using
     *       dmsToRadians()
     *     convert `theta` and `phi` to the x, y, and z components of
     *       `position`
     */
}


double arcLength(double latitude0[3], double longitude0[3],
                 double latitude1[3], double longitude1[3])
{
    /*
     * computes the length (in radians) of an arc ("geodesic") on the
     * unit sphere between points (longitude0, latitude0) and
     * (longitude1, latitude1)
     *
     * pseudocode:
     *     convert `latitude0` and `longitude0` to `position0`
     *       using polarToCartesian()
     *     convert `latitude1` and `longitude1` to `position1`
     *       using polarToCartesian()
     *     compute the cosine of the arc using the formula below
     *     use the acos() (arc cosine) math function to convert the
     *       cosine back to an angle and return it
     */
}


double crowFly(double latitude0[3], double longitude0[3],
               double latitude1[3], double longitude1[3])
{
    /*
     * computes and returns the distance in km from (latitude0,
     * longitude0) to (latitude1, longitude1) on the Earth's surface
     *
     * pseudocode:
     *     compute the arc length from (latitude0, longitude0) to
     *       (latitude1, longitude1) using arcLength()
     *     multiply the arc length by the radius of the Earth (6378 km)
     *       and return that value
     */
}


int main(void)
{
    double latitude0[3], longitude0[3];
    double latitude1[3], longitude1[3];

    printf(" from latitude (d m s): ");
    scanf("%lf %lf %lf", &latitude0[0], &latitude0[1], &latitude0[2]);
    printf("from longitude (d m s): ");
    scanf("%lf %lf %lf", &longitude0[0], &longitude0[1], &longitude0[2]);

    printf("   to latitude (d m s): ");
    scanf("%lf %lf %lf", &latitude1[0], &latitude1[1], &latitude1[2]);
    printf("  to longitude (d m s): ");
    scanf("%lf %lf %lf", &longitude1[0], &longitude1[1], &longitude1[2]);

    printf("              distance: %.1f km\n",
           crowFly(latitude0, longitude0, latitude1, longitude1));
    return 0;
}

The code is available as

http://www.tricity.wsu.edu/~bobl/cpts121/lab05_functions/crow_fly_tplt.c

The main() function is provided. You do not need to change it. There are four other functions you need to implement, as indicated in the comments. Some additional notes:

dmsToRadians()

This function takes a 3-element array containing an angle in degrees, (arc) minutes, and (arc) seconds and converts it to radians, which it returns. Remember that there are 60 seconds in a minute and 60 minutes in a degree and that there are 180 degrees in pi radians.

polarToCartesian()

This function takes a latitude[] and a longitude[], both degree-minute-second 3-arrays, and converts them to radians theta and phi, respectively. These then create the x, y, and z components (in that order) of the position[] array, using these formulae:

x = cosθ cosφ
y = cosθ sinφ
z = sinθ

These are all 3D coordinates on a unit sphere (a sphere of radius one).

arcLength()

This function computes the length of an arc on the unit sphere in radians. Given positions p and q (position0 and position1 in the pseudocode), the formula for the arc length is

θ = cos − 1(pxqx + pyqy + pzqz)

crowFly()

This function returns the distance between two points (given their longitudes and latitudes) on the Earth's surface. (This is a very simple function.)

Example

Here's a typical run for the distance between Richland and Pullman:

$ crow_fly
 from latitude (d m s): 46 16 47
from longitude (d m s): 119 16 53
   to latitude (d m s): 46 44 0
  to longitude (d m s): 117 10 0
              distance: 169.7 km