You are on page 1of 2

Print Article

Seite 1 von 2

Issue Date: FoxTalk July 1998

Calculate the Distance Between Two Points

Doug Dodge

Have you ever needed to calculate the distance between two points on the globe? This function will take two points -- described in terms of longitude and latitude -- and return the distance between them in miles.
Calculating the distance between two points on the globe isn't as simple as you might first think. Before I discuss why, let me refresh your memory about longitude and latitude. Lines of latitude circle the globe. The equator, for example, is a line of latitude. A degree of latitude is the distance between two consecutive lines of latitude. Since two lines of latitude are parallel, the distance between them is always the same. Thus, a degree of latitude measured near the North Pole (such as between 88 degrees and 89 degrees) is the same as near the Equator (such as between 1 degree and 2 degrees.) A degree of latitude is always about 69 miles. On the other hand, lines of longitude run from one pole to the other. Two lines of longitude intersect at both poles -- the distance between them is 0 -- and are furthest apart at the equator, where the distance is approximately 69 miles. (The circumference of the earth is approximately 25,000 miles, and there are 360 degrees of longitude: 25,000/360 = 69.44 miles.) For example, a degree of longitude (running across the globe) in Houston, Texas, or Perth, Australia (30 degrees) is approximately equal to 59 miles, while a degree of longitude in Montreal or Venice (45 degrees latitude) is 48 miles, and in Stockholm or Anchorage, it's 34 miles. As a result, you can't simply calculate the distance between two points by calculating the number of degrees between them and then multiplying the result by a number of miles per degree. The number of miles per degree of longitude varies depending on where, latitudinally, it is. The following equation, provided by CD Light in Sandy, Utah, takes these factors into account: nDistance = ; 3958.7500 * ; ACOS(SIN(nLat1/nDegrees) * ; SIN(nLat2/nDegrees) + ; COS(nLat1/nDegrees) * ; COS(nLat2/nDegrees) * ; COS(nLon2/nDegrees - nLon1/nDegrees)) where nDegrees = 180/PI() This formula can be incorporated into a routine that calculates the distance between two points on the globe, like so: * distance.prg PARAMETERS nLat1, nLon1, nLat2, nLon2 PRIVATE nParms, nDistance STORE pcount() TO nParms STORE -1 TO nDistance nDegrees = 180/PI() IF nParms <> 4 =MESSAGEBOX( ; "Incorrect number of parameters passed.", 16) ELSE * * The following formula was adapted from the * information provided by: * * CD Light * 8861 Silverstone Way * Sandy, Utah 84093-1679 * * (801) 943-0162 * (800) 571-3914 * * 05.02.06

Print Article

Seite 2 von 2

nDistance = ; 3958.7500 * ; ACOS(SIN(nLat1/nDegrees) * ; SIN(nLat2/nDegrees) + ; COS(nLat1/nDegrees) * ; COS(nLat2/nDegrees) * ; COS(nLon2/nDegrees - nLon1/nDegrees)) ENDIF RETURN nDistance Call this routine to calculate the distance between Cairo and London like so: ? distance(30,30,52,0) 2152.7475 This function can be particularly handy when calculating the distance between ZIP codes or finding all the ZIP codes within a certain distance of a base ZIP code. For example, the following routine will perform the second function. It depends on access to a database that holds each ZIP code and its associated longitude and latitude.

* getdist.prg PARAMETERS nDist, nLat, nLon PRIVATE nRetVal STORE -1 TO nRetVal IF pcount() <> 3 = MESSAGEBOX( ; "Incorrect number of parameters passed to " ; + PROGRAM() + " - terminating", 16) ELSE SELECT ; *, distance(nLat, nLon, a.latitude, a.longitude) ; AS distance ; FROM zipcode a; WHERE distance(nLat, nLon, a.latitude, a.longitude) ; <= nDist AND ; a.latitude <> nLat AND ; a.longitude <> nLon IF _TALLY > 0 STORE 0 TO nRetVal ELSE STORE -2 TO nRetVal ENDIF ENDIF RETURN nRetVal There are two things I should mention about the SELECT command shown in the preceding code. First, the last two lines ensure that the current position isn't included in the result set. You might wish to delete these lines if you want to include that position. Second, there isn't an output destination. This is because in my application, I directed the output to a grid, as displayed in Figure 1 . Figure 1. This screen allows the user to select companies that match specific criteria, including being within a range of a designated ZIP code.

Obviously, the actual SELECT that populated this grid was more complex, needing to handle multiple conditions and bind the result to the grid. Nonetheless, the essence of the form's mechanism is contained within this routine. I hope this pair of functions proves to be useful in your library of routines. 05.02.06