title: Geospatial coordinates and distance in kilometers
body: <p>This is a followup to <a href="https://stackoverflow.com/questions/378281/latlon-distance-heading-latlon">this question</a>.</p>
  
  <p>I seem to be stuck on this.  Basically, I need to be able to convert back and forth to referring to coordinates either in the standard degree system OR by measuring a distance north from the south pole along the international date line, and then a distance east starting from that point on the date line.  To do this (as well as some more general distance-measuring stuff), I have one method for determining the distance between two lat/lon points, and another method that takes a lat/lon point, a heading and a distance, and returns the lat/lon point at the end of that course.</p>
  
  <p>Here are the two static methods I've defined:</p>
  
  <pre><code>/* Takes two lon/lat pairs and returns the distance between them in kilometers.
  */
  public static double distance (double lat1, double lon1, double lat2, double lon2) {
      double theta = toRadians(lon1-lon2);
      lat1 = toRadians(lat1);
      lon1 = toRadians(lon1);
      lat2 = toRadians(lat2);
      lon2 = toRadians(lon2);
  
      double dist = sin(lat1)*sin(lat2) + cos(lat1)*cos(lat2)*cos(theta);
      dist = toDegrees(acos(dist)) * 60 * 1.1515 * 1.609344 * 1000;
  
      return dist;
  }
  
  /* endOfCourse takes a lat/lon pair, a heading (in degrees clockwise from north), and a distance (in kilometers), and returns
   * the lat/lon pair that would be reached by traveling that distance in that direction from the given point.
   */
  public static double[] endOfCourse (double lat1, double lon1, double tc, double dist) {
      double pi = Math.PI;
      lat1 = toRadians(lat1);
      lon1 = toRadians(lon1);
      tc = toRadians(tc);
      double dist_radians = toRadians(dist / (60 * 1.1515 * 1.609344 * 1000));
      double lat = asin(sin(lat1) * cos(dist_radians) + cos(lat1) * sin(dist_radians) * cos(tc));
      double dlon = atan2(sin(tc) * sin(dist_radians) * cos(lat1), cos(dist_radians) - sin(lat1) * sin(lat));
      double lon = ((lon1-dlon + pi) % (2*pi)) - pi;
      double[] endPoint = new double[2];
      endPoint[0] = lat; endPoint[1] = lon;
      return endPoint;
  }
  </code></pre>
  
  <p>And here's the function I'm using to test it:</p>
  
  <pre><code>public static void main(String args[]) throws java.io.IOException, java.io.FileNotFoundException {
      double distNorth = distance(0.0, 0.0, 72.0, 0.0);
      double distEast = distance(72.0, 0.0, 72.0, 31.5);
      double lat1 = endOfCourse(0.0, 0.0, 0.0, distNorth)[0];
      double lon1 = endOfCourse(lat1, 0.0, 90.0, distEast)[1];
      System.out.println("end at: " + lat1 + " / " + lon1);
      return;
  }
  </code></pre>
  
  <p>The "end at" values should be appx. 72.0 / 31.5.  But instead I'm getting approximately 1.25 / 0.021.</p>
  
  <p>I assume I must be missing something stupid, forgetting to convert units somewhere, or something...  Any help would be greatly appreciated!</p>
  
  <p><strong>UPDATE 1:</strong></p>
  
  <p>I had (correctly) written the distance function to return meters, but wrote kilometers in the comments by mistake ... which of course confused me when I came back to it today.  Anyway, now that's fixed, and I've fixed the factoring error in the endOfCourse method, and I also realized I'd forgotten to convert back to degrees from radians in that method too.  Anyway: while it appears I'm now getting the correct latitude number (71.99...), the longitude number is way off (I get 3.54 instead of 11.5).</p>
  
  <p><strong>UPDATE 2:</strong>
  I had a typo in the test, as mentioned below.  It's now fixed in the code.  The longitude number is still, however, wrong: I'm now getting -11.34 instead of 11.5.  I think there must be something wrong with these lines:</p>
  
  <pre><code>double dlon = atan2(sin(tc) * sin(dist_radians) * cos(lat1), cos(dist_radians) - sin(lat1) * sin(lat));
  double lon = ((lon1-dlon + pi) % (2*pi)) - pi;
  </code></pre>