Class: Astronoby::Coordinates::Geodetic
- Inherits:
-
Object
- Object
- Astronoby::Coordinates::Geodetic
- Defined in:
- lib/astronoby/coordinates/geodetic.rb
Overview
Geodetic coordinate system (WGS-84 latitude, longitude, and elevation).
Geodetic coordinates describe a position on or above the Earth’s surface using the WGS-84 reference ellipsoid, the same system used by GPS.
The reverse conversion from ECEF (Earth-Centered Earth-Fixed) Cartesian coordinates uses Bowring’s iterative method, which converges in 2-3 iterations for typical satellite altitudes.
Constant Summary collapse
- SEMI_MINOR_AXIS =
Constants::WGS84_EARTH_EQUATORIAL_RADIUS_IN_METERS * (1 - Constants::WGS84_FLATTENING)
- SECOND_ECCENTRICITY_SQUARED =
(Constants::WGS84_EARTH_EQUATORIAL_RADIUS_IN_METERS**2 - SEMI_MINOR_AXIS**2) / SEMI_MINOR_AXIS**2
- MAX_ITERATIONS =
10- CONVERGENCE_THRESHOLD =
1e-12
Instance Attribute Summary collapse
-
#elevation ⇒ Astronoby::Distance
readonly
Elevation above the WGS-84 ellipsoid.
-
#latitude ⇒ Astronoby::Angle
readonly
Geodetic latitude.
-
#longitude ⇒ Astronoby::Angle
readonly
Geodetic longitude.
Class Method Summary collapse
-
.from_ecef(position) ⇒ Astronoby::Coordinates::Geodetic
Converts ECEF Cartesian coordinates to geodetic coordinates using Bowring’s iterative method.
Instance Method Summary collapse
-
#initialize(latitude:, longitude:, elevation:) ⇒ Geodetic
constructor
A new instance of Geodetic.
Constructor Details
#initialize(latitude:, longitude:, elevation:) ⇒ Geodetic
Returns a new instance of Geodetic.
37 38 39 40 41 |
# File 'lib/astronoby/coordinates/geodetic.rb', line 37 def initialize(latitude:, longitude:, elevation:) @latitude = latitude @longitude = longitude @elevation = elevation end |
Instance Attribute Details
#elevation ⇒ Astronoby::Distance (readonly)
Returns elevation above the WGS-84 ellipsoid.
31 32 33 |
# File 'lib/astronoby/coordinates/geodetic.rb', line 31 def elevation @elevation end |
#latitude ⇒ Astronoby::Angle (readonly)
Returns geodetic latitude.
25 26 27 |
# File 'lib/astronoby/coordinates/geodetic.rb', line 25 def latitude @latitude end |
#longitude ⇒ Astronoby::Angle (readonly)
Returns geodetic longitude.
28 29 30 |
# File 'lib/astronoby/coordinates/geodetic.rb', line 28 def longitude @longitude end |
Class Method Details
.from_ecef(position) ⇒ Astronoby::Coordinates::Geodetic
Converts ECEF Cartesian coordinates to geodetic coordinates using Bowring’s iterative method.
Source:
Title: Transformation from Spatial to Geographical Coordinates
Author: B. R. Bowring
Edition: Survey Review, Vol. 23, No. 181, 1976
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/astronoby/coordinates/geodetic.rb', line 53 def self.from_ecef(position) x = position.x.m y = position.y.m z = position.z.m a = Constants::WGS84_EARTH_EQUATORIAL_RADIUS_IN_METERS e2 = Constants::WGS84_ECCENTICITY_SQUARED p = Math.sqrt(x * x + y * y) longitude = Math.atan2(y, x) theta = Math.atan2(z * a, p * SEMI_MINOR_AXIS) latitude = Math.atan2( z + SECOND_ECCENTRICITY_SQUARED * SEMI_MINOR_AXIS * Math.sin(theta)**3, p - e2 * a * Math.cos(theta)**3 ) MAX_ITERATIONS.times do prev_latitude = latitude theta = Math.atan2( (1 - Constants::WGS84_FLATTENING) * Math.sin(latitude), Math.cos(latitude) ) latitude = Math.atan2( z + SECOND_ECCENTRICITY_SQUARED * SEMI_MINOR_AXIS * Math.sin(theta)**3, p - e2 * a * Math.cos(theta)**3 ) break if (latitude - prev_latitude).abs < CONVERGENCE_THRESHOLD end sin_lat = Math.sin(latitude) n = a / Math.sqrt(1 - e2 * sin_lat * sin_lat) elevation = if Math.cos(latitude).abs > 1e-10 p / Math.cos(latitude) - n else z / sin_lat - n * (1 - e2) end new( latitude: Angle.from_radians(latitude), longitude: Angle.from_radians(longitude), elevation: Distance.from_meters(elevation) ) end |