Coverage for pygeodesy/mgrs.py : 88%

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 -*-
L{MGRSError} and functions L{parseMGRS} and L{toMgrs}.
Pure Python implementation of MGRS / UTM conversion functions using an ellipsoidal earth model, transcribed from JavaScript originals by I{(C) Chris Veness 2014-2016} published under the same MIT Licence**, see U{MGRS<https://www.Movable-Type.co.UK/scripts/latlong-utm-mgrs.html>} and U{Module mgrs<https://www.Movable-Type.co.UK/scripts/geodesy/docs/module-mgrs.html>}.
The MGRS/NATO grid references provides geocoordinate references covering the entire globe, based on UTM projections.
MGRS references comprise a grid zone designation, a 100 km square identification, and an easting and northing (in metres).
Depending on requirements, some parts of the reference may be omitted (implied), and easting/northing may be given to varying resolution.
See also U{United States National Grid <https://www.FGDC.gov/standards/projects/FGDC-standards-projects/usng/fgdc_std_011_2001_usng.pdf>} and U{Military Grid Reference System<https://WikiPedia.org/wiki/Military_grid_reference_system>}.
@newfield example: Example, Examples '''
UtmUps4Tuple, _xattrs, _xnamed
# all public contants, classes and functions
# 100 km grid square column (‘e’) letters repeat every third zone # 100 km grid square row (‘n’) letters repeat every other zone
# split an MGRS string "12ABC1235..." into 3 parts
'''Military Grid Reference System (MGRS) parse or other L{Mgrs} issue. '''
'''Military Grid Reference System (MGRS/NATO) references, with method to convert to UTM coordinates. '''
band='', datum=Datums.WGS84, name=''): '''New L{Mgrs} Military grid reference.
@param zone: 6° longitudinal zone (C{int}), 1..60 covering 180°W..180°E. @param en100k: Two-letter EN digraph (C{str}), 100 km grid square. @param easting: Easting (C{meter}), within 100 km grid square. @param northing: Northing (C{meter}), within 100 km grid square. @keyword band: Optional 8° latitudinal band (C{str}), C..X covering 80°S..84°N. @keyword datum: Optional this reference's datum (L{Datum}). @keyword name: Optional name (C{str}).
@raise MGRSError: Invalid MGRS grid reference, B{C{zone}}, B{C{en100k}} or B{C{band}}.
@example:
>>> from pygeodesy import Mgrs >>> m = Mgrs('31U', 'DQ', 48251, 11932) # 31U DQ 48251 11932 ''' self.name = name
raise IndexError # caught below except IndexError: raise MGRSError('%s invalid: %r' % ('en100k', en100k))
self._datum = datum
# check and convert grid letters to meter # get easting specified by e100k (note, +1 because # eastings start at 166e3 due to 500 km false origin) # similarly, get northing specified by n100k
'''(INTERNAL) Make copy with add'l, subclass attributes. ''' return _xattrs(self.classof(self.zone, self.en100k, self.easting, self.northing, band=self.band, datum=self.datum), self, *attrs)
def band(self): '''Get the latitudinal band (C{str, 'A'|'B'..'Y'|'Z'}). '''
def bandLatitude(self): '''Get the band latitude (C{degrees90} or C{None}). '''
'''Copy this MGRS reference.
@return: The copy (L{Mgrs} or subclass thereof). ''' return self._xcopy()
def datum(self): '''Get the datum (L{Datum}). '''
def en100k(self): '''Get the 2-character grid EN digraph (C{str}). ''' return self._en100k
def easting(self): '''Gets the easting (C{meter}). ''' return self._easting
def northing(self): '''Get the northing (C{meter}). ''' return self._northing
'''Parse a string to a MGRS grid reference.
@param strMGRS: MGRS grid reference (C{str}).
@return: MGRS reference (L{Mgrs}).
@raise MGRSError: Invalid B{C{strMGRS}}.
@see: Function L{parseMGRS} in this module L{mgrs}. ''' return parseMGRS(strMGRS, datum=self.datum, Mgrs=self.classof)
'''Return a string representation of this MGRS grid reference.
Note that MGRS grid references are truncated, not rounded (unlike UTM coordinates).
@keyword prec: Optional number of digits (C{int}), 4:km, 10:m. @keyword sep: Optional separator to join (C{str}).
@return: This Mgrs as "00B EN easting northing" (C{str}).
@raise ValueError: Invalid B{C{prec}}.
@example:
>>> m = Mgrs(31, 'DQ', 48251, 11932, band='U') >>> m.toStr() # '31U DQ 48251 11932' ''' '%02d%s' % (self._zone, self._band), self._en100k)
'''Return a string representation of this MGRS grid reference.
@keyword prec: Optional number of digits (C{int}), 4:km, 10:m. @keyword fmt: Optional enclosing backets format (C{str}). @keyword sep: Optional separator between name:values (C{str}).
@return: This Mgrs as "[Z:00B, G:EN, E:meter, N:meter]" (C{str}). '''
'''Convert this MGRS grid reference to a UTM coordinate.
@keyword Utm: Optional (sub-)class to return the UTM coordinate (L{Utm}) or C{None}.
@return: The UTM coordinate (L{Utm}) or a L{UtmUps4Tuple}C{(zone, hemipole, easting, northing)} if B{C{Utm}} is C{None}.
@example:
>>> m = Mgrs('31U', 'DQ', 448251, 11932) >>> u = m.toUtm() # 31 N 448251 5411932 ''' # get northing of the band bottom, extended to # include entirety of bottom-most 100 km square
# 100 km grid square row letters repeat every 2,000 km north; # add enough 2,000 km blocks to get into required band
r = UtmUps4Tuple(self.zone, h, e, n) else:
def zone(self): '''Get the longitudal zone (C{int}, 1..60). '''
'''Parse a string representing a MGRS grid reference, consisting of zoneBand, grid, easting and northing.
@param strMGRS: MGRS grid reference (C{str}). @keyword datum: Optional datum to use (L{Datum}). @keyword Mgrs: Optional (sub-)class to return the MGRS grid reference (L{Mgrs}) or C{None}. @keyword name: Optional B{C{Mgrs}} name (C{str}).
@return: The MGRS grid reference (B{L{Mgrs}}) or an L{Mgrs4Tuple}C{(zone, digraph, easting, northing)} if B{C{Mgrs}} is C{None}.
@raise MGRSError: Invalid B{C{strMGRS}}.
@example:
>>> m = parseMGRS('31U DQ 48251 11932') >>> str(m) # 31U DQ 48251 11932 >>> m = parseMGRS('31UDQ4825111932') >>> repr(m) # [Z:31U, G:DQ, E:48251, N:11932] >>> m = mgrs.parseMGRS('42SXD0970538646') >>> str(m) # 42S XD 09705 38646 >>> m = mgrs.parseMGRS('42SXD9738') # Km >>> str(m) # 42S XD 97000 38000 ''' raise ValueError
# convert to meter if less than 5 digits
m = _mg(_GZDre, m[0]) + halfs2(m[1]) m = _mg(_GZDre, m[0]) + m[1:] raise ValueError except (TypeError, ValueError): raise MGRSError('%s invalid: %r' % ('strMGRS', strMGRS))
Mgrs(z, EN, e, n, datum=datum)
'''Convert a UTM coordinate to an MGRS grid reference.
@param utm: A UTM coordinate (L{Utm} or L{Etm}). @keyword Mgrs: Optional (sub-)class to return the MGRS grid reference (L{Mgrs}) or C{None}. @keyword name: Optional B{C{Mgrs}} name (C{str}).
@return: The MGRS grid reference (B{L{Mgrs}}) or an L{Mgrs6Tuple}C{(zone, digraph, easting, northing, band, datum)} if B{L{Mgrs}} is C{None}.
@raise TypeError: If B{C{utm}} is not L{Utm} nor L{Etm}.
@raise MGRSError: Invalid B{C{utm}}.
@example:
>>> u = Utm(31, 'N', 448251, 5411932) >>> m = u.toMgrs() # 31U DQ 48251 11932 '''
# truncate east-/northing to within 100 km grid square # XXX add rounding to nm precision?
# columns in zone 1 are A-H, zone 2 J-R, zone 3 S-Z, then # repeating every 3rd zone (note -1 because eastings start # at 166e3 due to 500km false origin) # rows in even zones are A-V, in odd zones are F-E _Ln100k[z % 2][int(N) % len(_Ln100k[0])])
r = Mgrs6Tuple(utm.zone, en, e, n, utm.band, utm.datum) 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. |