Documentation ¶
Overview ¶
Example ¶
// Parse the OS Grid Reference for Newlyn Harbour gridRef, err := ParseOsGridRef("SW 46760 28548") if err != nil { panic(err) } // Print it as an 8-digit reference: fmt.Println(gridRef.StringN(8)) // Or without spaces: fmt.Println(gridRef.StringNCompact(8)) // Or as an Eastings / Northings pair: fmt.Println(gridRef.NumericString()) // Now convert to Lat / Lon (using the "standard" mapping, WGS84) lat, lon := gridRef.ToLatLon() fmt.Printf("%.4f,%.4f\n", lat, lon) // The returned lat/lon could now be pasted into, for example, Google maps: // https://www.google.com/maps/@50.1026075,-5.5457719,17z // Convert the lat, lon back into a grid ref latLon, err := ParseLatLon(fmt.Sprintf("%f,%f", lat, lon), 0, WGS84) if err != nil { panic(err) } fmt.Printf("%s\n", latLon.ToOsGridRef().StringNCompact(8))
Output: SW 4676 2854 SW46762854 146760,28548 50.1029,-5.5428 SW46762854
Index ¶
- Constants
- Variables
- func AreaOf(polygon []LatLon) float64
- func ParseDegrees(s string) (float64, error)
- func Wrap180(degrees float64) float64
- func Wrap360(degrees float64) float64
- func Wrap90(degrees float64) float64
- type Cartesian
- type Datum
- type Ellipseoid
- type LatLon
- func (ll LatLon) DestinationPoint(distance float64, bearing float64) LatLon
- func (ll LatLon) DistanceTo(point LatLon) float64
- func (ll LatLon) FinalBearingTo(point LatLon) float64
- func (ll LatLon) InitialBearingTo(point LatLon) float64
- func (ll LatLon) IsEnclosedBy(polygon []LatLon) bool
- func (ll LatLon) String() string
- type LatLonEllipsoidalDatum
- type NvectorSpherical
- type OsGridRef
- type Vector3d
- func (v Vector3d) AngleTo(other Vector3d, extraPlanar bool, n Vector3d) float64
- func (v Vector3d) Cross(other Vector3d) Vector3d
- func (v Vector3d) DividedBy(value float64) Vector3d
- func (v Vector3d) Dot(other Vector3d) float64
- func (v Vector3d) Length() float64
- func (v Vector3d) Minus(other Vector3d) Vector3d
- func (v Vector3d) Negate() Vector3d
- func (v Vector3d) Plus(other Vector3d) Vector3d
- func (v Vector3d) RotateAround(axis Vector3d, angle float64) Vector3d
- func (v Vector3d) String() string
- func (v Vector3d) Times(value float64) Vector3d
- func (v Vector3d) Unit() Vector3d
Examples ¶
Constants ¶
const ( // NatGrid scale factor on central meridian F0 = 0.9996012717 // northing & easting of true origin, metres N0 = -100e3 E0 = 400e3 )
Variables ¶
var ( OSGB36 = Datums["OSGB36"] WGS84 = Datums["WGS84"] )
var Datums = map[string]Datum{ "ED50": {Name: "ED50", Ellipsoid: ellipsoids["Intl1924"], Transform: [7]float64{89.5, 93.8, 123.1, -1.2, 0.0, 0.0, 0.156}}, "ETRS89": {Name: "ETRS89", Ellipsoid: ellipsoids["GRS80"], Transform: [7]float64{0, 0, 0, 0, 0, 0, 0}}, "Irl1975": {Name: "Irl1975", Ellipsoid: ellipsoids["AiryModified"], Transform: [7]float64{-482.530, 130.596, -564.557, -8.150, 1.042, 0.214, 0.631}}, "NAD27": {Name: "NAD27", Ellipsoid: ellipsoids["Clarke1866"], Transform: [7]float64{8, -160, -176, 0, 0, 0, 0}}, "NAD83": {Name: "NAD83", Ellipsoid: ellipsoids["GRS80"], Transform: [7]float64{0.9956, -1.9103, -0.5215, -0.00062, 0.025915, 0.009426, 0.011599}}, "NTF": {Name: "NTF", Ellipsoid: ellipsoids["Clarke1880IGN"], Transform: [7]float64{168, 60, -320, 0, 0, 0, 0}}, "OSGB36": {Name: "OSGB36", Ellipsoid: ellipsoids["Airy1830"], Transform: [7]float64{-446.448, 125.157, -542.060, 20.4894, -0.1502, -0.2470, -0.8421}}, "Potsdam": {Name: "Potsdam", Ellipsoid: ellipsoids["Bessel1841"], Transform: [7]float64{-582, -105, -414, -8.3, 1.04, 0.35, -3.08}}, "TokyoJapan": {Name: "TokyoJapan", Ellipsoid: ellipsoids["Bessel1841"], Transform: [7]float64{148, -507, -685, 0, 0, 0, 0}}, "WGS72": {Name: "WGS72", Ellipsoid: ellipsoids["WGS72"], Transform: [7]float64{0, 0, -4.5, -0.22, 0, 0, 0.554}}, "WGS84": {Name: "WGS84", Ellipsoid: ellipsoids["WGS84"], Transform: [7]float64{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}, }
Functions ¶
func AreaOf ¶ added in v1.2.0
*
- Calculates the area of a spherical polygon where the sides of the polygon are great circle
- arcs joining the vertices. *
- @param {LatLon[]} polygon - Array of points defining vertices of the polygon.
- @param {number} [radius=6371e3] - (Mean) radius of earth (defaults to radius in metres).
- @returns {number} The area of the polygon in the same units as radius. *
- @example
- const polygon = [new LatLon(0,0), new LatLon(1,0), new LatLon(0,1)];
- const area = LatLon.areaOf(polygon); // 6.18e9 m²
func ParseDegrees ¶
ParseDegrees parses a string representing degrees/minutes/seconds into numeric degrees.
This is very flexible on formats, allowing signed decimal degrees, or deg-min-sec optionally suffixed by compass direction (NSEW); a variety of separators are accepted. Examples -3.62, '3 37 12W', '3°37′12″W'.
Thousands/decimal separators must be comma/dot; use Dms.fromLocale to convert locale-specific thousands/decimal separators.
example
lat = ParseDegrees(`51° 28′ 40.37″ N`); lon = ParseDegrees(`000° 00′ 05.29″ W`);
func Wrap180 ¶
Wrap90 constrains degrees to range -180..+180 (for longitude); e.g. -181 => 179, 181 => -179.
Types ¶
type Cartesian ¶
Cartesian coordinate representing ECEF (earth-centric earth-fixed) point, on a given datum. The datum will identify the primary meridian (for the x-coordinate), and is also useful in transforming to/from geodetic (lat/lon) coordinates.
func (Cartesian) ConvertDatum ¶
Converts ‘this’ cartesian coordinate to new datum using Helmert 7-parameter transformation.
example
c = Cartesian{... ... ..., LatLon.datums.OSGB36} c.convertDatum(Datums["Irl1975"]);
func (Cartesian) ToLatLon ¶
func (c Cartesian) ToLatLon() LatLonEllipsoidalDatum
Converts ‘this’ (geocentric) cartesian (x/y/z) coordinate to (geodetic) latitude/longitude point (based on the same datum).
Uses Bowring’s (1985) formulation for μm precision in concise form; ‘The accuracy of geodetic latitude and height equations’, B R Bowring, Survey Review vol 28, 218, Oct 1985.
returns Latitude/longitude point defined by cartesian coordinates.
example
c = Cartesian{X: 4027893.924, Y: 307041.993, Z: 4919474.294, WGS84); p = c.ToLatLon(); // 50.7978°N, 004.3592°E
type Datum ¶
type Datum struct { Name string Ellipsoid Ellipseoid Transform [7]float64 }
Datums, with associated ellipsoid, and Helmert transform parameters to convert from WGS-84 into given datum.
Note that precision of various datums will vary, and WGS-84 (original) is not defined to be accurate to better than ±1 metre. No transformation should be assumed to be accurate to better than a metre, for many datums somewhat less.
type Ellipseoid ¶
type Ellipseoid struct {
// contains filtered or unexported fields
}
Ellipsoid parameters.
type LatLon ¶ added in v1.2.0
type LatLon struct {
Lat, Lon float64
}
*
- Latitude/longitude points on a spherical model earth, and methods for calculating distances,
- bearings, destinations, etc on (orthodromic) great-circle paths and (loxodromic) rhumb lines.
func Intersection ¶ added in v1.2.0
*
- Returns the point of intersection of two paths defined by point and bearing. *
- @param {LatLon} p1 - First point.
- @param {number} brng1 - Initial bearing from first point.
- @param {LatLon} p2 - Second point.
- @param {number} brng2 - Initial bearing from second point.
- @returns {LatLon|null} Destination point (null if no unique intersection defined). *
- @example
- const p1 = new LatLon(51.8853, 0.2545), brng1 = 108.547;
- const p2 = new LatLon(49.0034, 2.5735), brng2 = 32.435;
- const pInt = LatLon.intersection(p1, brng1, p2, brng2); // 50.9078°N, 004.5084°E
func (LatLon) DestinationPoint ¶ added in v1.2.0
*
- Returns the destination point from ‘this’ point having travelled the given distance on the
- given initial bearing (bearing normally varies around path followed). *
- @param {number} distance - Distance travelled, in same units as earth radius (default: metres).
- @param {number} bearing - Initial bearing in degrees from north.
- @param {number} [radius=6371e3] - (Mean) radius of earth (defaults to radius in metres).
- @returns {LatLon} Destination point. *
- @example
- const p1 = new LatLon(51.47788, -0.00147);
- const p2 = p1.destinationPoint(7794, 300.7); // 51.5136°N, 000.0983°W
func (LatLon) DistanceTo ¶ added in v1.2.0
*
- Returns the distance along the surface of the earth from ‘this’ point to destination point. *
- Uses haversine formula: a = sin²(Δφ/2) + cosφ1·cosφ2 · sin²(Δλ/2); d = 2 · atan2(√a, √(a-1)). *
- @param {LatLon} point - Latitude/longitude of destination point.
- @param {number} [radius=6371e3] - Radius of earth (defaults to mean radius in metres).
- @returns {number} Distance between this point and destination point, in same units as radius.
- @throws {TypeError} Invalid radius. *
- @example
- const p1 = new LatLon(52.205, 0.119);
- const p2 = new LatLon(48.857, 2.351);
- const d = p1.distanceTo(p2); // 404.3×10³ m
- const m = p1.distanceTo(p2, 3959); // 251.2 miles
func (LatLon) FinalBearingTo ¶ added in v1.2.0
*
- Returns final bearing arriving at destination point from ‘this’ point; the final bearing will
- differ from the initial bearing by varying degrees according to distance and latitude. *
- @param {LatLon} point - Latitude/longitude of destination point.
- @returns {number} Final bearing in degrees from north (0°..360°). *
- @example
- const p1 = new LatLon(52.205, 0.119);
- const p2 = new LatLon(48.857, 2.351);
- const b2 = p1.finalBearingTo(p2); // 157.9°
func (LatLon) InitialBearingTo ¶ added in v1.2.0
*
- Returns the initial bearing from ‘this’ point to destination point. *
- @param {LatLon} point - Latitude/longitude of destination point.
- @returns {number} Initial bearing in degrees from north (0°..360°). *
- @example
- const p1 = new LatLon(52.205, 0.119);
- const p2 = new LatLon(48.857, 2.351);
- const b1 = p1.initialBearingTo(p2); // 156.2°
func (LatLon) IsEnclosedBy ¶ added in v1.3.0
*
- Tests whether ‘this’ point is enclosed by the polygon defined by a set of points. *
- @param {LatLon[]} polygon - Ordered array of points defining vertices of polygon.
- @returns {bool} Whether this point is enclosed by polygon. *
- @example
- const bounds = [ new LatLon(45,1), new LatLon(45,2), new LatLon(46,2), new LatLon(46,1) ];
- const p = new LatLon(45.1, 1.1);
- const inside = p.IsEnclosedBy(bounds); // true
func (LatLon) String ¶ added in v1.2.0
*
- Returns a string representation of ‘this’ point, formatted as degrees, degrees+minutes, or
- degrees+minutes+seconds. *
- @param {string} [format=d] - Format point as 'd', 'dm', 'dms', or 'n' for signed numeric.
- @param {number} [dp=4|2|0] - Number of decimal places to use: default 4 for d, 2 for dm, 0 for dms.
- @returns {string} Comma-separated formatted latitude/longitude.
- @throws {RangeError} Invalid format. *
- @example
- const greenwich = new LatLon(51.47788, -0.00147);
- const d = greenwich.toString(); // 51.4779°N, 000.0015°W
- const dms = greenwich.toString('dms', 2); // 51°28′40.37″N, 000°00′05.29″W
- const [lat, lon] = greenwich.toString('n').split(','); // 51.4779, -0.0015
type LatLonEllipsoidalDatum ¶
Latitude/longitude points on an ellipsoidal model earth, with ellipsoid parameters and methods for converting between datums and to geocentric (ECEF) cartesian coordinates.
func ParseLatLon ¶
func ParseLatLon(latLon string, height float64, datum Datum) (LatLonEllipsoidalDatum, error)
Parses a latitude/longitude point from a variety of formats.
Latitude & longitude (in degrees) can be supplied as a single comma-separated lat/lon string.
The latitude/longitude values may be numeric or strings; they may be signed decimal or deg-min-sec (hexagesimal) suffixed by compass direction (NSEW); a variety of separators are accepted. Examples -3.62, '3 37 12W', '3°37′12″W'.
example
p1 = LatLon.parse('51.47736, 0.0000', 0, OSGB36); p2 = LatLon.parse('51°28′40″N, 000°00′05″W', 17, WGS84);
func (LatLonEllipsoidalDatum) ConvertDatum ¶
func (l LatLonEllipsoidalDatum) ConvertDatum(toDatum Datum) LatLonEllipsoidalDatum
Converts ‘this’ lat/lon coordinate to new coordinate system.
@param toDatum - Datum this coordinate is to be converted to. returns {LatLon} This point converted to new datum.
example
pWGS84 = LatLonEllipsoidalDatum{Lat: 51.47788, Lon: -0.00147, Height: 0, Datum: WGS84); pOSGB = pWGS84.convertDatum(OSGB36); // 51.4773°N, 000.0001°E
func (LatLonEllipsoidalDatum) ToCartesian ¶
func (l LatLonEllipsoidalDatum) ToCartesian() Cartesian
Converts ‘this’ point from (geodetic) latitude/longitude coordinates to (geocentric) cartesian (x/y/z) coordinates, based on the same datum.
returns Cartesian point equivalent to lat/lon point, with x, y, z in metres from earth centre, augmented with reference frame conversion methods and properties.
func (LatLonEllipsoidalDatum) ToLatLon ¶ added in v1.3.0
func (l LatLonEllipsoidalDatum) ToLatLon() LatLon
func (LatLonEllipsoidalDatum) ToOsGridRef ¶
func (l LatLonEllipsoidalDatum) ToOsGridRef() OsGridRef
ToOsGridRef returns the OS grid reference equivalent to this LatLon.
type NvectorSpherical ¶ added in v1.3.0
type NvectorSpherical Vector3d
/** * Calculates the area of a spherical polygon where the sides of the polygon are great circle * arcs joining the vertices. * * Uses Girard’s theorem: A = [Σθᵢ − (n−2)·π]·R² * * @param {LatLon[]} polygon - Array of points defining vertices of the polygon. * @param {number} [radius=6371e3] - (Mean) radius of earth (defaults to radius in metres). * @returns {number} The area of the polygon in the same units as radius. * * @example * const polygon = [ new LatLon(0,0), new LatLon(1,0), new LatLon(0,1) ]; * const area = LatLon.areaOf(polygon); // 6.18e9 m² */ static areaOf(polygon, radius=6371e3) { const R = Number(radius);
// close the polygon so that the last point equals the first point const closed = polygon[0].equals(polygon[polygon.length-1]); if (!closed) polygon.push(polygon[0]);
const n = polygon.length - 1; // number of vertices
// get great-circle vector for each segment const c = []; for (let v=0; v<n; v++) { const i = polygon[v].toNvector(); const j = polygon[v+1].toNvector(); c[v] = i.cross(j); // great circle for segment v..v+1 } c.push(c[0]);
// sum interior angles; depending on whether polygon is cw or ccw, angle between edges is // π−α or π+α, where α is angle between great-circle vectors; so sum α, then take n·π − |Σα| // (cannot use Σ(π−|α|) as concave polygons would fail); use vector to 1st point as plane // normal for sign of α const n1 = polygon[0].toNvector(); let Σα = 0; for (let v=0; v<n; v++) Σα += c[v].angleTo(c[v+1], n1); const Σθ = n*π - Math.abs(Σα);
// note: angle between two sides of a spherical triangle is acos(c₁·c₂) where cₙ is the // plane normal vector to the great circle representing the triangle side - use this instead // of angleTo()?
const E = (Σθ - (n-2)*π); // spherical excess (in steradians) const A = E * R*R; // area in units of R²
if (!closed) polygon.pop(); // restore polygon to pristine condition
return A; }
/** * Returns point representing geographic mean of supplied points. * * @param {LatLon[]} points - Array of points to be averaged. * @returns {LatLon} Point at the geographic mean of the supplied points. * * @example * const p = LatLon.meanOf([ new LatLon(1, 1), new LatLon(4, 2), new LatLon(1, 3) ]); // 02.0001°N, 002.0000°E */ static meanOf(points) { let m = new NvectorSpherical(0, 0, 0); // null vector
// add all vectors for (let p = 0; p < points.length; p++) { m = m.plus(points[p].toNvector()); } // m is now geographic mean
return new NvectorSpherical(m.x, m.y, m.z).toLatLon(); }
/** * Checks if another point is equal to ‘this’ point. * * @param {LatLon} point - Point to be compared against this point. * @returns {bool} True if points have identical latitude and longitude values. * @throws {TypeError} Invalid point. * * @example * const p1 = new LatLon(52.205, 0.119); * const p2 = new LatLon(52.205, 0.119); * const equal = p1.equals(p2); // true */ equals(point) { if (!(point instanceof LatLonNvectorSpherical)) throw new TypeError(`invalid point ‘${point}’`);
if (Math.abs(this.lat - point.lat) > Number.EPSILON) return false; if (Math.abs(this.lon - point.lon) > Number.EPSILON) return false;
return true; }
/** * Converts ‘this’ point to a GeoJSON object. * * @returns {Object} this point as a GeoJSON ‘Point’ object. */ toGeoJSON() { return { type: 'Point', coordinates: [ this.lon, this.lat ] }; }
/** * Returns a string representation of ‘this’ point, formatted as degrees, degrees+minutes, or * degrees+minutes+seconds. * * @param {string} [format=d] - Format point as 'd', 'dm', 'dms', or 'n' for signed numeric. * @param {number} [dp=4|2|0] - Number of decimal places to use: default 4 for d, 2 for dm, 0 for dms. * @returns {string} Comma-separated formatted latitude/longitude. * * @example * const greenwich = new LatLon(51.47788, -0.00147); * const d = greenwich.toString(); // 51.4778°N, 000.0015°W * const dms = greenwich.toString('dms', 2); // 51°28′40.37″N, 000°00′05.29″W * const [lat, lon] = greenwich.toString('n').split(','); // 51.4778, -0.0015 */ toString(format='d', dp=undefined) { // note: explicitly set dp to undefined for passing through to toLat/toLon if (![ 'd', 'dm', 'dms', 'n' ].includes(format)) throw new RangeError(`invalid format ‘${format}’`);
if (format == 'n') { // signed numeric degrees if (dp == undefined) dp = 4; return `${this.lat.toFixed(dp)},${this.lon.toFixed(dp)}`; } const lat = Dms.toLat(this.lat, format, dp); const lon = Dms.toLon(this.lon, format, dp); return `${lat}, ${lon}`; }
}
/* Nvector - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
* * An n-vector is a (unit) vector normal to the Earth's surface (a non-singular position * representation). * * For many applications, n-vectors are more convenient to work with than other position * representations such as latitude/longitude, UTM coordinates, etc. * * On a spherical model earth, an n-vector is equivalent to a (normalised) earth-centred earth-fixed * (ECEF) vector. * * @extends Vector3d
type OsGridRef ¶
type OsGridRef struct {
Easting, Northing int
}
OsGridRef represents an Ordnance Survey grid reference.
func ParseOsGridRef ¶
ParseOsGridRef parses a string into an OsGridRef. The string may be in comma-separated Easting,Northing format, or with grid letters.
func (OsGridRef) NumericString ¶
Returns a string representation in Easting,Northing format.
func (OsGridRef) StringN ¶
Returns a string representation in the normal grid-letter format, with the requested number of digits in the numeric part. The grid letters, easting and northing parts will be separated by spaces.
func (OsGridRef) StringNCompact ¶
Returns a string representation in the normal grid-letter format, with the requested number of digits in the numeric part. The string will not contain any spaces.
type Vector3d ¶
type Vector3d struct {
X, Y, Z float64
}
Functions for manipulating generic 3-d vectors.
Functions return vectors as return results, so that operations can be chained.
example
v = v1.cross(v2).dot(v3) // ≡ v1×v2⋅v3
func (Vector3d) AngleTo ¶
Calculates the angle between ‘this’ vector and supplied vector atan2(|p₁×p₂|, p₁·p₂) (or if (extra-planar) ‘n’ supplied then atan2(n·p₁×p₂, p₁·p₂).
@param {Vector3d} v - Vector whose angle is to be determined from ‘this’ vector. @param {Vector3d} [n] - Plane normal: if supplied, angle is signed +ve if this->v is
clockwise looking along n, -ve in opposite direction.
returns {number} Angle (in radians) between this vector and supplied vector (in range 0..π
if n not supplied, range -π..+π if n supplied).
func (Vector3d) Cross ¶
Multiplies ‘this’ vector by the supplied vector using cross (vector) product.
@param {Vector3d} v - Vector to be crossed with this vector. returns {Vector3d} Cross product of ‘this’ and v.
func (Vector3d) DividedBy ¶
Divides ‘this’ vector by a scalar value.
@param {number} x - Factor to divide this vector by. returns {Vector3d} Vector divided by x.
func (Vector3d) Dot ¶
Multiplies ‘this’ vector by the supplied vector using dot (scalar) product.
@param {Vector3d} v - Vector to be dotted with this vector. returns {number} Dot product of ‘this’ and v.
func (Vector3d) Length ¶
Length (magnitude or norm) of ‘this’ vector.
returns {number} Magnitude of this vector.
func (Vector3d) Minus ¶
Subtracts supplied vector from ‘this’ vector.
@param {Vector3d} v - Vector to be subtracted from this vector. returns {Vector3d} Vector representing difference between this and v.
func (Vector3d) Negate ¶
Negates a vector to point in the opposite direction.
returns {Vector3d} Negated vector.
func (Vector3d) Plus ¶
Adds supplied vector to ‘this’ vector.
@param {Vector3d} v - Vector to be added to this vector. returns {Vector3d} Vector representing sum of this and v.
func (Vector3d) RotateAround ¶
Rotates ‘this’ point around an axis by a specified angle.
@param {Vector3d} axis - The axis being rotated around. @param {number} angle - The angle of rotation (in degrees). returns {Vector3d} The rotated point.
func (Vector3d) String ¶
String representation of vector.
@param {number} [dp=3] - Number of decimal places to be used. returns {string} Vector represented as [x,y,z].