PageRenderTime 53ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/LonelySharp/GeoLocation.cs

http://github.com/anthonyvscode/LonelySharp
C# | 201 lines | 110 code | 20 blank | 71 comment | 8 complexity | 61de2f7a1c422a4d3a24127686fa7da5 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using LonelySharp.Utilities;
  6. namespace LonelySharp
  7. {
  8. /**
  9. * Represents a point on the surface of a sphere. (The Earth is almost
  10. * spherical.)
  11. *
  12. * This code was originally published at
  13. * http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates#Java
  14. *
  15. * @author Jan Philip Matuschek
  16. * @version 22 September 2010
  17. * @converted to C# by Anthony Zigenbine on 19th October 2010
  18. */
  19. public class GeoLocation
  20. {
  21. private double radLat; // latitude in radians
  22. private double radLon; // longitude in radians
  23. private double degLat; // latitude in degrees
  24. private double degLon; // longitude in degrees
  25. private static double MIN_LAT = Helpers.ConvertDegreesToRadians(-90d); // -PI/2
  26. private static double MAX_LAT = Helpers.ConvertDegreesToRadians(90d); // PI/2
  27. private static double MIN_LON = Helpers.ConvertDegreesToRadians(-180d); // -PI
  28. private static double MAX_LON = Helpers.ConvertDegreesToRadians(180d); // PI
  29. private const double earthRadius = 6371.01;
  30. private GeoLocation()
  31. {
  32. }
  33. /// <summary>
  34. /// Return GeoLocation from Degrees
  35. /// </summary>
  36. /// <param name="latitude">The latitude, in degrees.</param>
  37. /// <param name="longitude">The longitude, in degrees.</param>
  38. /// <returns>GeoLocation in Degrees</returns>
  39. public static GeoLocation FromDegrees(double latitude, double longitude)
  40. {
  41. GeoLocation result = new GeoLocation
  42. {
  43. radLat = Helpers.ConvertDegreesToRadians(latitude),
  44. radLon = Helpers.ConvertDegreesToRadians(longitude),
  45. degLat = latitude,
  46. degLon = longitude
  47. };
  48. result.CheckBounds();
  49. return result;
  50. }
  51. /// <summary>
  52. /// Return GeoLocation from Radians
  53. /// </summary>
  54. /// <param name="latitude">The latitude, in radians.</param>
  55. /// <param name="longitude">The longitude, in radians.</param>
  56. /// <returns>GeoLocation in Radians</returns>
  57. public static GeoLocation FromRadians(double latitude, double longitude)
  58. {
  59. GeoLocation result = new GeoLocation
  60. {
  61. radLat = latitude,
  62. radLon = longitude,
  63. degLat = Helpers.ConvertRadiansToDegrees(latitude),
  64. degLon = Helpers.ConvertRadiansToDegrees(longitude)
  65. };
  66. result.CheckBounds();
  67. return result;
  68. }
  69. private void CheckBounds()
  70. {
  71. if (radLat < MIN_LAT || radLat > MAX_LAT ||
  72. radLon < MIN_LON || radLon > MAX_LON)
  73. throw new Exception("Arguments are out of bounds");
  74. }
  75. /**
  76. * @return the latitude, in degrees.
  77. */
  78. public double getLatitudeInDegrees()
  79. {
  80. return degLat;
  81. }
  82. /**
  83. * @return the longitude, in degrees.
  84. */
  85. public double getLongitudeInDegrees()
  86. {
  87. return degLon;
  88. }
  89. /**
  90. * @return the latitude, in radians.
  91. */
  92. public double getLatitudeInRadians()
  93. {
  94. return radLat;
  95. }
  96. /**
  97. * @return the longitude, in radians.
  98. */
  99. public double getLongitudeInRadians()
  100. {
  101. return radLon;
  102. }
  103. public override string ToString()
  104. {
  105. return "(" + degLat + "\u00B0, " + degLon + "\u00B0) = (" +
  106. radLat + " rad, " + radLon + " rad)";
  107. }
  108. /// <summary>
  109. /// Computes the great circle distance between this GeoLocation instance and the location argument.
  110. /// </summary>
  111. /// <param name="location">Location to act as the centre point</param>
  112. /// <returns>the distance, measured in the same unit as the radius argument.</returns>
  113. public double DistanceTo(GeoLocation location)
  114. {
  115. return Math.Acos(Math.Sin(radLat) * Math.Sin(location.radLat) +
  116. Math.Cos(radLat) * Math.Cos(location.radLat) *
  117. Math.Cos(radLon - location.radLon)) * earthRadius;
  118. }
  119. /// <summary>
  120. /// Computes the bounding coordinates of all points on the surface
  121. /// of a sphere that have a great circle distance to the point represented
  122. /// by this GeoLocation instance that is less or equal to the distance
  123. /// argument.
  124. /// For more information about the formulae used in this method visit
  125. /// http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates
  126. /// </summary>
  127. /// <param name="distance">The distance from the point represented by this
  128. /// GeoLocation instance. Must me measured in the same unit as the radius argument.
  129. /// </param>
  130. /// <returns>An array of two GeoLocation objects such that:
  131. ///
  132. /// a) The latitude of any point within the specified distance is greater
  133. /// or equal to the latitude of the first array element and smaller or
  134. /// equal to the latitude of the second array element.
  135. /// If the longitude of the first array element is smaller or equal to
  136. /// the longitude of the second element, then
  137. /// the longitude of any point within the specified distance is greater
  138. /// or equal to the longitude of the first array element and smaller or
  139. /// equal to the longitude of the second array element.
  140. ///
  141. /// b) If the longitude of the first array element is greater than the
  142. /// longitude of the second element (this is the case if the 180th
  143. /// meridian is within the distance), then
  144. /// the longitude of any point within the specified distance is greater
  145. /// or equal to the longitude of the first array element
  146. /// or smaller or equal to the longitude of the second
  147. /// array element.</returns>
  148. public GeoLocation[] BoundingCoordinates(double distance)
  149. {
  150. if (distance < 0d)
  151. throw new Exception("Distance cannot be less than 0");
  152. // angular distance in radians on a great circle
  153. double radDist = distance / earthRadius;
  154. double minLat = radLat - radDist;
  155. double maxLat = radLat + radDist;
  156. double minLon, maxLon;
  157. if (minLat > MIN_LAT && maxLat < MAX_LAT)
  158. {
  159. double deltaLon = Math.Asin(Math.Sin(radDist) /
  160. Math.Cos(radLat));
  161. minLon = radLon - deltaLon;
  162. if (minLon < MIN_LON) minLon += 2d * Math.PI;
  163. maxLon = radLon + deltaLon;
  164. if (maxLon > MAX_LON) maxLon -= 2d * Math.PI;
  165. }
  166. else
  167. {
  168. // a pole is within the distance
  169. minLat = Math.Max(minLat, MIN_LAT);
  170. maxLat = Math.Min(maxLat, MAX_LAT);
  171. minLon = MIN_LON;
  172. maxLon = MAX_LON;
  173. }
  174. return new GeoLocation[]
  175. {
  176. FromRadians(minLat, minLon),
  177. FromRadians(maxLat, maxLon)
  178. };
  179. }
  180. }
  181. }