// examples/01-geometric_geodesy.rs // Using Rust Geodesy for simple geodetic computations. // Run with: // cargo run --example 01-geometric_geodesy // Geodetic naming conventions conflict somewhat with // Rust's (otherwise sensible) conventions, so we turn // snake case warnings of for this entire file. #![allow(non_snake_case)] use geodesy::prelude::*; fn main() -> Result<(), Error> { // In example 00, we saw that the `Context` data structure is the // coordinating element for all things related to transformations // in Rust Geodesy. For generic geometric geodesy the same can be // said about the `Ellipsoid`. So to do anything, we must first // instantiate an `Ellipsoid`. We can do that in two ways - either // by asking, by name, for one of the built in ellipsoids, or by // providing our own ellipsoid parameters: // The GRS 1980 ellipsoid is built in, so we use the ::named function. let GRS80 = Ellipsoid::named("GRS80")?; // The Maupertuis 1738 ellipsoid is not built in, so we provide `a`, // the semimajor axis, and `f`, the flattening to the `new()` // constructor. let Mau38 = Ellipsoid::new(6_397_300., 1.0 / 191.); // Now, let's compute som ancillary ellipsoidal parameters: let E = GRS80.linear_eccentricity(); let b = GRS80.semiminor_axis(); let c = GRS80.polar_radius_of_curvature(); let n = GRS80.third_flattening(); let es = GRS80.eccentricity_squared(); println!("GRS80 - Ellipsoid parameters"); println!(" E = {E:.4}"); println!(" b = {b:.4}"); println!(" c = {c:.4}"); println!(" n = {n}"); println!(" es = {es}"); println!(); // A geodesic is the shortest line between two points on the // surface of the ellipsoid. Let's compute the distance and // azimuth between the approximate locations of the airports // of Copenhagen (CPH) and Paris (CDG). let CPH = Coor2D::geo(55., 12.); let CDG = Coor2D::geo(49., 2.); // By historical convention the "from A to B" situation is considered // the inverse sense of the geodesic problem - hence `geodesic_inv`: let d = GRS80.geodesic_inv(&CPH, &CDG); let dd = d.to_degrees(); // Note the '.to_degrees()' above: This Coord method attacks // the first two elements of the coordinate only. The output from the // geodesic routines is organized to fit this pattern. println!("GRS80 - Copenhagen->Paris, inv algorithm"); println!(" Distance: {:.3} km", dd[2] / 1000.); println!(" Azimuth at departure: {:.1} deg", dd[0]); println!(" Azimuth at destination: {:.1} deg", dd[1]); println!(); // Now we have the azimuth from CPH to CDG - so let's take the same trip // again, this time using the "forward" version: let b = GRS80.geodesic_fwd(&CPH, d[0], d[2]).to_degrees(); // In this case, output is [longitude, latitude, 0, 0] println!("GRS80 - Copenhagen->Paris, fwd algorithm"); println!(" Location: {} {}", b[0], b[1]); println!(); // We assert to hit the spot within a nanometer assert!((b[0] - 2.).abs() < 1e-9); assert!((b[1] - 49.).abs() < 1e-9); // Let's try going back using the azimuth at the destination. // We need to swap its direction to get us back to Copenhagen. let az_back = (dd[1] + 180.0).to_radians(); let b = GRS80.geodesic_fwd(&CDG, az_back, d[2]).to_degrees(); println!("GRS80 - Paris->Copenhagen, fwd algorithm, with swapped azimuth"); println!(" Location: {} {}", b[0], b[1]); println!(); let d = GRS80.geodesic_inv(&CDG, &CPH); let dd = d.to_degrees(); // Note the '.to_degrees()' above: This Coord method attacks // the first two elements of the coordinate only. The output from the // geodesic routines is organized to fit this pattern. println!("GRS80 - Paris->Copenhagen"); println!(" Distance: {:.3} km", dd[2] / 1000.); println!(" Azimuth at departure: {:.1} deg", dd[0]); println!(" Azimuth at destination: {:.1} deg", dd[1]); println!(); // But how would it be, if we were not handling a Boeing 737 on the // GRS80 ellipsoid in 2021, but a Montgolfière on the Maupertuis // ellipsoid in 1783? let dd = Mau38.geodesic_inv(&CPH, &CDG).to_degrees(); println!("Mau38 - Copenhagen->Paris, inv algorithm"); println!(" Distance: {:.3} km", dd[2] / 1000.); println!(" Azimuth at departure: {:.1} deg", dd[0]); println!(" Azimuth at destination: {:.1} deg", dd[1]); println!(); // So the Montgolfier brothers would have thought they had flown // approximately 3 km longer than the modern day airline pilot. Ok(()) }