Coverage for pygeodesy/osgr.py : 94%

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 -*-
and functions L{parseOSGR} and L{toOsgr}.
Pure Python implementation of OS Grid Reference functions using an ellipsoidal earth model, transcribed 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://Henrik-Seidel.GMXhome.DE/gausskrueger.pdf>}, 2006 and U{Transverse Mercator: Redfearn series <https://WikiPedia.org/wiki/Transverse_Mercator:_Redfearn_series>}.
@newfield example: Example, Examples ''' # make sure int/int division yields float quotient raise ImportError('%s 1/2 == %d' % ('division', division))
_xsubclassof, _xzipairs _dot_, _item_ps, _no_convergence_, \ _SPACE_, _SQUARE_, _1_0
'''(INTERNAL) Convert datum if needed. ''' except AttributeError: raise _TypeError(name, ll, txt=_item_ps(_no_convertDatum_, 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) != _Datums_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{0} 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_(_item_ps(self.classname, self.toStr(prec=-3)), self.toLatLon.__name__) raise OSGRError(_no_convergence_, txt=t)
tar / ( 2 * v), tar / ( 24 * v3) * fdot((1, 3, -9), 5 + x2, ta2, ta2 * x2), tar / (720 * v5) * fdot((61, 90, 45), _1_0, ta2, ta4))
csa / v, csa / ( 6 * v3) * fsum_(vr, ta2, ta2), csa / ( 120 * v5) * fdot((5, 28, 24), _1_0, ta2, ta4), csa / (5040 * v7) * fdot((61, 662, 1320, 720), _1_0, ta2, ta4, 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: Optional number of digits (C{int}). @kwarg fmt: Optional enclosing backets format (C{str}). @kwarg sep: Optional 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. ''' (fmt % (_COLON_.join((Osgr.__name__.upper(), t)),))
'''DEPRECATED, use method L{Osgr.toRepr}.'''
'''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 C{join} separator (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 fully 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
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 B{C{Osgr=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}} 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.convertDatum() raise OSGRError(lon=lon, txt='not %s' % (None,))
# if necessary, convert to OSGB36 first except AttributeError: a, b = map1(radians, ll.lat, ll.lon)
(vsa / 2) * ca, (vsa / 24) * ca3 * fsum_(5, -ta2, 9 * x2), (vsa / 720) * ca5 * fsum_(61, ta4, -58 * ta2))
(v * ca), (v / 6) * ca3 * (r - ta2), (v / 120) * ca5 * fdot((-18, 1, 14, -58), ta2, 5 + ta4, x2, ta2 * x2))
r = EasNor2Tuple(e, n) else:
# **) MIT License # # Copyright (C) 2016-2020 -- 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. |