Expand description
§Jord - Geographical Position Calculations
Jord (Swedish) is Earth (English)
jord is a Rust crate for exact geodetic, geocentric and great-circle position
calculations on both spherical and ellipsoidal Earth models — ECEF/n-vector
conversions, local reference frames (NED, ENU, body, wander-azimuth), great
circle navigation, kinematics, and spherical polygon (“Loop”) geometry.
If you’re looking for planar/projected geometry and boolean operations on
generic 2D shapes, see the geo crate instead
— jord focuses specifically on accurate positions and geometry on the
Earth (geodesic/great-circle math, not straight-edge planar math), and
provides optional interop with geo-types/geo-traits for the pieces that
do overlap.
For ellipsoidal geodesic distance/bearing (Vincenty/Karney), see geographiclib-rs (pure Rust) or geographiclib (C++ bindings, faster) - jord’s GeodeticPosition converts to their plain lat/lon/metres inputs via .latitude().as_degrees() etc…
§Table of contents
§Installation
cargo add jordor add it to Cargo.toml directly:
[dependencies]
jord = "0.20.0"To enable an optional feature, e.g. geo-types:
cargo add jord --features geo-types§Capabilities
- Conversions between ECEF (earth-centred, earth-fixed), latitude/longitude and n-vector positions, for both spherical and ellipsoidal models.
- Local reference frames:
- Body, local-level/wander-azimuth, NED (north, east, down) and ENU (east, north, up).
- Delta between two positions, destination position from a reference position and a delta.
- Frame transformation (translation and/or rotation).
- Great circle (spherical) navigation: surface distance, initial & final bearing, interpolated position, mean position, minor arc intersection, cross track distance, angle turned, side of position, projection on minor arc & great circle, …
- Kinematics (spherical): closest point of approach between tracks, minimum speed for intercept, time to intercept.
- Spherical Loops (“simple polygon”): convex/concave, clockwise/anti-clockwise, contains position, spherical excess, topological relationship, minimum bounding rectangle, triangulation, spherical excess, …
- Spherical Caps and Rectangular Regions.
- Location-dependent radii of ellipsoids.
§Literature
The following references provide the theoretical basis of most of the algorithms:
- Non-singular Horizontal Position Representation; Gade, K.; 2010
- Some Tactical Algorithms for Spherical Geometry
- Triangulation by Ear Clipping
- A simple linear time algorithm for smallest enclosing circles on the (hemi)sphere
§Cargo features
All of the following are disabled by default:
serde: serialization/deserialization support via serde.uom: interoperability between jord measurement types and uom types.geo-typesandgeo-traits: interoperability between jordLatLongand geo-types/geo-traits.
§Solutions to the 10 examples from NavLab
§Example 1: A and B to delta
Given two positions A and B. Find the exact vector from A to B in meters north, east and down, and find the direction (azimuth/bearing) to B, relative to north. Use WGS-84 ellipsoid.
use jord::{Angle, GeodeticPosition, Length, NVector, PositionVector, Surface};
use jord::local::NedFrame;
use jord::ellipsoidal::Ellipsoid;
let a = GeodeticPosition::new(
NVector::from_lat_long_degrees(1.0, 2.0),
Length::from_metres(3.0)
);
let b = GeodeticPosition::new(
NVector::from_lat_long_degrees(4.0, 5.0),
Length::from_metres(6.0)
);
let e = Ellipsoid::WGS84;
let ned = NedFrame::from_geodetic(a, e);
let delta = ned.local_vector_to(e.geodetic_to_geocentric_position(b));
assert_eq!(Length::from_metres(331730.863), delta.x().round_mm()); // north
assert_eq!(Length::from_metres(332998.501), delta.y().round_mm()); // east
assert_eq!(Length::from_metres(17398.304), delta.z().round_mm()); // down
assert_eq!(Length::from_metres(470357.384), delta.slant_range().round_mm());
assert_eq!(Angle::from_degrees(45.10926), delta.bearing().round_d5());
assert_eq!(Angle::from_degrees(-2.11983), delta.elevation().round_d5());§Example 2: B and delta to C
Given the position of vehicle B and a bearing and distance to an object C. Find the exact position of C. Use WGS-72 ellipsoid.
use jord::{Angle, GeodeticPosition, LatLong, Length, NVector,PositionVector, Surface, Vec3};
use jord::local::{BodyFrame, BodyVector};
use jord::ellipsoidal::Ellipsoid;
let b = GeodeticPosition::new(
NVector::new(Vec3::new_unit(1.0, 2.0, 3.0)),
Length::from_metres(400.0)
);
let e = Ellipsoid::WGS72;
let yaw = Angle::from_degrees(10.0);
let pitch = Angle::from_degrees(20.0);
let roll = Angle::from_degrees(30.0);
let body = BodyFrame::from_geodetic(yaw, pitch, roll, b, e);
let delta = BodyVector::from_metres(3000.0, 2000.0, 100.0);
let c = e.geocentric_to_geodetic_position(body.destination_position(delta));
let c_ll = LatLong::from_nvector(c.horizontal_position());
assert_eq!(Angle::from_degrees(53.32638), c_ll.latitude().round_d5());
assert_eq!(Angle::from_degrees(63.46812), c_ll.longitude().round_d5());
assert_eq!(Length::from_metres(406.007), c.height().round_mm());§Example 3: ECEF-vector to geodetic latitude
Given an ECEF-vector of a position. Find geodetic latitude, longitude and height (using WGS-84 ellipsoid).
use jord::{Angle, GeocentricPosition, LatLong, Length, Surface};
use jord::ellipsoidal::Ellipsoid;
let c = GeocentricPosition::from_metres(0.9*6371e3, -1.0*6371e3, 1.1*6371e3);
let p = Ellipsoid::WGS84.geocentric_to_geodetic_position(c);
let p_ll = LatLong::from_nvector(p.horizontal_position());
assert_eq!(Angle::from_degrees(39.37875), p_ll.latitude().round_d5());
assert_eq!(Angle::from_degrees(-48.01279), p_ll.longitude().round_d5());
assert_eq!(Length::from_metres(4702059.834), p.height().round_mm());§Example 4: Geodetic latitude to ECEF-vector
Given geodetic latitude, longitude and height. Find the ECEF-vector (using WGS-84 ellipsoid).
use jord::{GeocentricPosition, GeodeticPosition, Length, NVector, PositionVector, Surface};
use jord::ellipsoidal::Ellipsoid;
let p = GeodeticPosition::new(
NVector::from_lat_long_degrees(1.0, 2.0),
Length::from_metres(3.0)
);
let c = Ellipsoid::WGS84.geodetic_to_geocentric_position(p);
assert_eq!(
GeocentricPosition::from_metres(6_373_290.277, 222_560.201, 110_568.827),
c.round_mm(),
);The following examples assume a spherical Earth model
§Example 5: Surface distance
Given position A and B. Find the surface distance (i.e. great circle distance).
use jord::{Length, NVector};
use jord::spherical::Sphere;
let a = NVector::from_lat_long_degrees(88.0, 0.0);
let b = NVector::from_lat_long_degrees(89.0, -170.0);
assert_eq!(
Length::from_kilometres(332.456),
Sphere::EARTH.distance(a, b).round_m()
);§Example 6: Interpolated position
Given the position of B at time t0 and t1. Find an interpolated position at time ti.
use jord::{LatLong, NVector};
use jord::spherical::Sphere;
let a = NVector::from_lat_long_degrees(89.9, -150.0);
let b = NVector::from_lat_long_degrees(89.9, 150.0);
let t0 = 10.0;
let t1 = 20.0;
let ti = 16.0;
let f = (ti - t0) / (t1 - t0);
let pi = Sphere::interpolated_position(a, b, f);
assert!(pi.is_some());
assert_eq!(
LatLong::from_degrees(89.91282, 173.41323),
LatLong::from_nvector(pi.unwrap()).round_d5()
);§Example 7: Mean position/center
Given three positions A, B, and C. Find the mean position (center/midpoint).
use jord::{LatLong, NVector};
use jord::spherical::Sphere;
let ps = vec![
NVector::from_lat_long_degrees(90.0, 0.0),
NVector::from_lat_long_degrees(60.0, 10.0),
NVector::from_lat_long_degrees(50.0, -20.0)
];
let m = Sphere::mean_position(&ps);
assert!(m.is_some());
assert_eq!(
LatLong::from_degrees(67.23615, -6.91751),
LatLong::from_nvector(m.unwrap()).round_d5()
);§Example 8: A and azimuth/distance to B
Given position A and an azimuth/bearing and a (great circle) distance. Find the destination point B.
use jord::{Angle, LatLong, Length, NVector};
use jord::spherical::Sphere;
let p = NVector::from_lat_long_degrees(80.0, -90.0);
let azimuth = Angle::from_degrees(200.0);
let distance = Length::from_metres(1000.0);
let d = Sphere::EARTH.destination_position(p, azimuth, distance);
assert_eq!(
LatLong::from_degrees(79.99155, -90.01770),
LatLong::from_nvector(d).round_d5()
);§Example 9: Intersection of two paths / triangulation
Given path A going through A1 and A2, and path B going through B1 and B2. Find the intersection of the two paths.
use jord::{LatLong, NVector};
use jord::spherical::MinorArc;
let a = MinorArc::new(
NVector::from_lat_long_degrees(50.0, 180.0),
NVector::from_lat_long_degrees(90.0, 180.0)
);
let b = MinorArc::new(
NVector::from_lat_long_degrees(60.0, 160.0),
NVector::from_lat_long_degrees(80.0, -140.0)
);
let i = a.intersection(b);
assert!(i.is_some());
assert_eq!(
LatLong::from_degrees(74.16345, 180.0),
LatLong::from_nvector(i.unwrap()).round_d5()
);§Example 10: Cross track distance (cross track error)
Given path A going through A1 and A2, and a point B. Find the cross track distance/cross track error between B and the path.
use jord::{LatLong, Length, NVector};
use jord::spherical::{GreatCircle, Sphere};
let a = GreatCircle::new(
NVector::from_lat_long_degrees(0.0, 0.0),
NVector::from_lat_long_degrees(10.0, 0.0)
);
let b = NVector::from_lat_long_degrees(1.0, 0.1);
let d = Sphere::EARTH.cross_track_distance(b, a);
assert_eq!(Length::from_metres(11117.8), d.round_dm());§Contributing
Issues and pull requests are welcome on GitHub.
§License
jord is licensed under the MIT license.
Modules§
- ellipsoidal
- Geographical position calculations assuming an ellipsoidal model.
- local
- Local (topocentric) reference frames and the vectors within them.
- spherical
- Geographical position calculations assuming a spherical model.
Macros§
- impl_
measurement - Macro that creates the code to implement operator overrides.
Structs§
- Angle
- A one-dimensional angle.
- Geocentric
Position - A geocentric position or Earth Centred Earth Fixed (ECEF) vector.
- Geodetic
Position - A geodetic position: the horiztonal coordinates (as a
NVector) and height above the surface. - LatLong
- An horizontal position represented by a pair of latitude-longitude.
- Length
- A length.
- Mat33
- A 3*3 matrix.
- NVector
- An horizontal position represented by a n-vector: the unit and normal vector to the surface.
- Speed
- A speed.
- Vec3
- A 3-element vector.
- Vehicle
- The state of a vehicle: its horizontal position and velocity (bearing and speed).
Traits§
- Measurement
- Trait implemented by all measurable quantities.
- Position
Vector - Position vector: allows to represent the position of a general coordinate frame B relative to a reference coordinate frame A as the position vector from A to B.
- Surface
- The reference surface for a celestial body (e.g. Earth) on which calculations are done.