Coverage for pygeodesy/osgr.py : 96%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# -*- coding: utf-8 -*-
Classes L{Osgr} and L{OSGRError} and functions L{parseOSGR} and L{toOsgr}.
Pure Python implementation of OS Grid Reference functions using an ellipsoidal earth model, transcoded from JavaScript originals by I{(C) Chris Veness 2005-2016} published under the same MIT Licence**, see U{OS National Grid<https://www.Movable-Type.co.UK/scripts/latlong-os-gridref.html>} and U{Module osgridref <https://www.Movable-Type.co.UK/scripts/geodesy/docs/module-osgridref.html>}.
OSGR provides geocoordinate references for UK mapping purposes, converted in 2015 to work with WGS84 datum by default or OSGB36 as option.
See U{Guide<https://www.OrdnanceSurvey.co.UK/docs/support/guide-coordinate-systems-great-britain.pdf>}, U{Proposed Changes<https://www.OrdnanceSurvey.co.UK/blog/2014/09/proposed-changes-to-latitude-and-longitude-representation-on-paper-maps-tell-us-your-thoughts>}, U{Confirmation<https://www.OrdnanceSurvey.co.UK/blog/2014/12/confirmation-on-changes-to-latitude-and-longitude>} and U{Ordnance Survey National Grid<https://WikiPedia.org/wiki/Ordnance_Survey_National_Grid>}.
See also Karney U{'Transverse Mercator with an accuracy of a few nanometers' <https://Arxiv.org/pdf/1002.1417v3.pdf>}, 2011 (building on Krüger U{'Konforme Abbildung des Erdellipsoids in der Ebene' <https://bib.GFZ-Potsdam.DE/pub/digi/krueger2.pdf>}, 1912), Seidel U{'Die Mathematik der Gauß-Krueger-Abbildung' <https://DE.WikiPedia.org/wiki/Gauß-Krüger-Koordinatensystem>}, 2006 and U{Transverse Mercator: Redfearn series <https://WikiPedia.org/wiki/Transverse_Mercator:_Redfearn_series>}. ''' # make sure int/int division yields float quotient, see .basics
_convergence_, _float, _latlon_, _no_, \ _not_, _SPACE_, _1_0, _2_0, _6_0, \ _24_0, _120_0, _720_0 _10um, _100km
'''(INTERNAL) Convert datum if needed. ''' except AttributeError: raise _TypeError(name, ll, txt=Fmt.PAREN(_no_toDatum_, datum.name))
'''(INTERNAL) Compute meridional arc. ''' sin(a_ * 2) * cos(_a * 2), -sin(a_ * 3) * cos(_a * 3))
'''Ordinance Survey Grid References (OSGR) parse or other L{Osgr} issue. '''
'''Ordinance Survey Grid References (OSGR) coordinate. '''
'''New L{Osgr} National Grid Reference.
@arg easting: Easting from OS false easting (C{meter}). @arg northing: Northing from from OS false northing (C{meter}). @kwarg datum: Default datum (C{Datums.OSGB36}). @kwarg name: Optional name (C{str}).
@raise OSGRError: Invalid or negative B{C{easting}} or B{C{northing}} or B{C{datum}} not C{Datums.OSBG36}.
@example:
>>> from pygeodesy import Osgr >>> r = Osgr(651409, 313177) '''
try: if _ellipsoidal_datum(datum) != _OSGB36: raise ValueError except (TypeError, ValueError): raise OSGRError(datum=datum) self.name = name
'''Get the datum (L{Datum}). '''
'''Get the easting (C{meter}). '''
'''Get the most recent C{Osgr.toLatLon} iteration number (C{int}) or C{None} if not available/applicable. '''
'''Get the northing (C{meter}). '''
'''Parse a string to a similar L{Osgr} instance.
@arg strOSGR: The OSGR reference (C{str}), see function L{parseOSGR}. @kwarg name: Optional instance name (C{str}), overriding this name.
@return: The similar instance (L{Osgr})
@raise OSGRError: Invalid B{C{strOSGR}}. '''
'''Convert this OSGR coordinate to an (ellipsoidal) geodetic point.
While OS grid references are based on the OSGB36 datum, the I{Ordnance Survey} have deprecated the use of OSGB36 for lat-/longitude coordinates (in favour of WGS84). Hence, this method returns WGS84 by default with OSGB36 as an option, U{see<https://www.OrdnanceSurvey.co.UK/blog/2014/12/2>}.
I{Note formulation implemented here due to Thomas, Redfearn, etc. is as published by OS, but is inferior to Krüger as used by e.g. Karney 2011.}
@kwarg LatLon: Optional ellipsoidal class to return the geodetic point (C{LatLon}) or C{None}. @kwarg datum: Optional datum to convert to (L{Datum}, L{Ellipsoid}, L{Ellipsoid2}, L{Ellipsoid2} or L{a_f2Tuple}).
@return: The geodetic point (B{C{LatLon}}) or a L{LatLonDatum3Tuple}C{(lat, lon, datum)} if B{C{LatLon}} is C{None}.
@raise OSGRError: No convergence.
@raise TypeError: If B{C{LatLon}} is not ellipsoidal or B{C{datum}} is invalid or conversion failed.
@example:
>>> from pygeodesy import ellipsoidalVincenty as eV >>> g = Osgr(651409.903, 313177.270) >>> p = g.toLatLon(eV.LatLon) # 52°39′28.723″N, 001°42′57.787″E >>> # to obtain (historical) OSGB36 lat-/longitude point >>> p = g.toLatLon(eV.LatLon, datum=Datums.OSGB36) # 52°39′27.253″N, 001°43′04.518″E '''
else: t = _DOT_(Fmt.PAREN(self.classname, self.toStr(prec=-3)), self.toLatLon.__name__) raise OSGRError(_no_(_convergence_), txt=t)
-d2 * t / ( _2_0 * v), d4 * t / ( _24_0 * v3) * fsum_(5, x2, 3 * ta2, -9 * ta2 * x2), -d6 * t / (_720_0 * v5) * fsum_(61, 90 * ta2, 45 * ta4))
d1 * t / v, -d3 * t / ( _6_0 * v3) * fsum_(vr, ta2, ta2), d5 * t / ( _120_0 * v5) * fsum_(5, 28 * ta2, 24 * ta4), -d7 * t / (_5040_0 * v7) * fsum_(61, 662 * ta2, 1320 * ta4, 720 * ta6))
'''(INTERNAL) Convert cached latlon to C{LatLon} ''' r = _ll2datum(ll, datum, LatLonDatum3Tuple.__name__) r = LatLonDatum3Tuple(r.lat, r.lon, r.datum) else: # must be ellipsoidal
'''Return a string representation of this OSGR coordinate.
@kwarg prec: Number of digits (C{int}). @kwarg fmt: Enclosing backets format (C{str}). @kwarg sep: Separator to join (C{str}).
@return: This OSGR (C{str}) "[G:00B, E:meter, N:meter]" or "[OSGR:meter,meter]" if B{C{prec}} is non-positive. ''' else:
'''Return a string representation of this OSGR coordinate.
Note that OSGR coordinates are truncated, not rounded (unlike UTM grid references).
@kwarg prec: Optional number of digits (C{int}). @kwarg sep: Optional separator to join (C{str}) or C{None} to return an unjoined C{tuple} of C{str}s.
@return: This OSGR as C{"EN easting northing"} or as C{"easting,northing"} if B{C{prec}} is non-positive (C{str}).
@raise ValueError: Invalid B{C{prec}}.
@example:
>>> r = Osgr(651409, 313177) >>> str(r) # TG 5140 1317 >>> r.toStr(prec=0) # 651409,313177 '''
0 > N or N > 12: return NN _i2c((N * 5) % 25 + (E % 5))
else:
'''Parse a string representing an OSGR grid reference, consisting of C{"[grid] easting northing"}.
Accepts standard OS Grid References like 'SU 387 148', with or without whitespace separators, from 2- up to 10-digit references (1 m × 1 m square), or all-numeric, comma-separated references in meters, for example '438700,114800'.
@arg strOSGR: An OSGR coordinate (C{str}). @kwarg Osgr: Optional class to return the OSGR coordinate (L{Osgr}) or C{None}. @kwarg name: Optional B{C{Osgr}} name (C{str}).
@return: The OSGR coordinate (B{C{Osgr}}) or an L{EasNor2Tuple}C{(easting, northing)} if B{C{Osgr}} is C{None}.
@raise OSGRError: Invalid B{C{strOSGR}}.
@example:
>>> g = parseOSGR('TG 51409 13177') >>> str(g) # TG 51409 13177 >>> g = parseOSGR('TG5140913177') >>> str(g) # TG 51409 13177 >>> g = parseOSGR('TG51409 13177') >>> str(g) # TG 51409 13177 >>> g = parseOSGR('651409,313177') >>> str(g) # TG 51409 13177 >>> g.toStr(prec=0) # 651409,313177 '''
raise ValueError
else: # "GR easting northing"
0 > N or N > 12: raise ValueError
else: raise ValueError
_xnamed(Osgr(e, n), name)
strOSGR=strOSGR, Error=OSGRError)
**Osgr_kwds): '''Convert a lat-/longitude point to an OSGR coordinate.
@arg latlon: Latitude (C{degrees}) or an (ellipsoidal) geodetic C{LatLon} point. @kwarg lon: Optional longitude in degrees (scalar or C{None}). @kwarg datum: Optional datum to convert B{C{lat, lon}} from (L{Datum}, L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}). @kwarg Osgr: Optional class to return the OSGR coordinate (L{Osgr}) or C{None}. @kwarg name: Optional B{C{Osgr}} name (C{str}). @kwarg Osgr_kwds: Optional, additional B{C{Osgr}} keyword arguments, ignored if C{B{Osgr} is None}.
@return: The OSGR coordinate (B{C{Osgr}}) or an L{EasNor2Tuple}C{(easting, northing)} if B{C{Osgr}} is C{None}.
@raise OSGRError: Invalid B{C{latlon}} or B{C{lon}}.
@raise TypeError: Non-ellipsoidal B{C{latlon}} or invalid B{C{datum}}, B{C{Osgr}}, B{C{Osgr_kwds}} argument or conversion failed.
@example:
>>> p = LatLon(52.65798, 1.71605) >>> r = toOsgr(p) # TG 51409 13177 >>> # for conversion of (historical) OSGB36 lat-/longitude: >>> r = toOsgr(52.65757, 1.71791, datum=Datums.OSGB36) ''' # XXX fix failing _LLEB.toDatum() raise OSGRError(lon=lon, txt=_not_(None))
# if necessary, convert to OSGB36 first except AttributeError: a, b = map1(radians, ll.lat, ll.lon)
d1 * v * ca, d3 * v / _6_0 * ca3 * (r - ta2), d5 * v / _120_0 * ca5 * t)
_F0 * E.b * _M(E.Mabcd, a), d2 * t / _2_0 * ca, d4 * t / _24_0 * ca3 * fsum_(5, -ta2, 9 * x2), d6 * t / _720_0 * ca5 * fsum_(61, ta4, -58 * ta2))
r = EasNor2Tuple(e, n) else:
# **) MIT License # # Copyright (C) 2016-2022 -- mrJean1 at Gmail -- All Rights Reserved. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. |