/// <summary> /// Calculate the distance between two points. This algorithm does not take the curvature of the Earth into /// account, so it only works for small distance up to, say 200 km, and not too close to the poles. /// </summary> /// <param name="p1">Point 1. @Nonnull</param> /// <param name="p2">Point 2. @Nonnull</param> /// <returns>Straight distance between p1 and p2. Only accurate for small distances up to 200 km.</returns> public static double distanceInMeters(Point p1, Point p2) { CheckArgs.checkNonnull("p1", p1); CheckArgs.checkNonnull("p2", p2); Point from; Point to; if (p1.lonDeg <= p2.lonDeg) { from = p1; to = p2; } else { from = p2; to = p1; } // Calculate mid point of 2 latitudes. double avgLat = from.latDeg + ((to.latDeg - from.latDeg) / 2.0); double deltaLonDeg360 = Math.Abs(to.lonDeg - from.lonDeg); double deltaLonDeg = ((deltaLonDeg360 <= 180.0) ? deltaLonDeg360 : (360.0 - deltaLonDeg360)); double deltaLatDeg = Math.Abs(to.latDeg - from.latDeg); // Meters per longitude is fixed; per latitude requires * cos(avg(lat)). double deltaXMeters = degreesLonToMetersAtLat(deltaLonDeg, avgLat); double deltaYMeters = degreesLatToMeters(deltaLatDeg); // Calculate length through Earth. This is an approximation, but works fine for short distances. double lenMeters = Math.Sqrt((deltaXMeters * deltaXMeters) + (deltaYMeters * deltaYMeters)); return(lenMeters); }
/// <summary> /// Create a random point, uniformly distributed over the surface of the Earth. /// </summary> /// <param name="randomGenerator">Random generator used to create a point. @Nonnull</param> /// <returns>Random point with uniform distribution over the sphere. @Nonnull</returns> public static Point fromUniformlyDistributedRandomPoints(Random randomGenerator) { CheckArgs.checkNonnull("randomGenerator", randomGenerator); // Calculate uniformly distributed 3D point on sphere (radius = 1.0): // http://mathproofs.blogspot.co.il/2005/04/uniform-random-distribution-on-sphere.html double unitRand1 = randomGenerator.NextDouble(); double unitRand2 = randomGenerator.NextDouble(); double theta0 = (2.0 * Math.PI) * unitRand1; double theta1 = Math.Acos(1.0 - (2.0 * unitRand2)); double x = Math.Sin(theta0) * Math.Sin(theta1); double y = Math.Cos(theta0) * Math.Sin(theta1); double z = Math.Cos(theta1); // Convert Carthesian 3D point into lat/lon (radius = 1.0): // http://stackoverflow.com/questions/1185408/converting-from-longitude-latitude-to-cartesian-coordinates double latRad = Math.Asin(z); double lonRad = Math.Atan2(y, x); // Convert radians to degrees. System.Diagnostics.Debug.Assert(!Double.IsNaN(latRad)); System.Diagnostics.Debug.Assert(!Double.IsNaN(lonRad)); double lat = RadianToDegree(latRad); double lon = RadianToDegree(lonRad); return(fromMicroDeg(degToMicroDeg(lat), degToMicroDeg(lon))); }