def _callname(name, class_name, self_name, up=1): # imported by .points '''(INTERNAL) Assemble the name for an invokation. ''' n, c = class_name, callername(up=up + 1) if c: n = _dot_(n, _item_ps(c, name)) if self_name: n = '%s %r' % (n, self_name) return n
def toRepr(self, **kwds): # PYCHOK expected '''(INTERNAL) I{Could be overloaded}. @kwarg kwds: Optional, keyword arguments. @return: C{toStr}() with keyword arguments (as C{str}). ''' t = self.toStr(**kwds).lstrip('([{').rstrip('}])') return _item_ps(self.classname, t) # XXX (self.named, t)
def _ll2datum(ll, datum, name): '''(INTERNAL) Convert datum if needed. ''' if datum not in (None, ll.datum): try: ll = ll.convertDatum(datum) except AttributeError: raise _TypeError(name, ll, txt=_item_ps(_no_convertDatum_, datum.name)) return ll
def unstr(name, *args, **kwds): '''Return the string representation of an invokation. @arg name: Function, method or class name (C{str}). @arg args: Optional positional arguments. @kwarg kwds: Optional keyword arguments. @return: Representation (C{str}). ''' t = reprs(args, fmt=_g) + pairs(sorted(kwds.items())) return _item_ps(name, _COMMA_SPACE_.join(t))
def toRepr(self, prec=6, sep=_COMMA_SPACE_, **unused): # PYCHOK signature '''Return the -Tuple items as C{name=value} string(s). @kwarg prec: The C{float} precision, number of decimal digits (0..9). Trailing zero decimals are stripped for B{C{prec}} values of 1 and above, but kept for negative B{C{prec}} values. @kwarg sep: Optional separator to join (C{str}). @return: Tuple items (C{str}). ''' return _item_ps(self.named, sep.join(pairs(self.items(), prec=prec)))
def _latlon3(self, LatLon, datum): '''(INTERNAL) Convert cached LatLon ''' ll = self._latlon if LatLon is None: if datum and datum != ll.datum: raise _TypeError(latlon=ll, txt=_item_ps(_no_convertDatum_, datum.name)) return _xnamed(LatLonDatum3Tuple(ll.lat, ll.lon, ll.datum), ll.name) else: _xsubclassof(_LLEB, LatLon=LatLon) ll = _xnamed(LatLon(ll.lat, ll.lon, datum=ll.datum), ll.name) return _ll2datum(ll, datum, _LatLon_)
def toLatLon(self, LatLon=None, datum=Datums.WGS84): '''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 ''' if self._latlon: return self._latlon3(LatLon, datum) E = self.datum.ellipsoid # _Datums_OSGB36.ellipsoid, Airy130 a_F0 = E.a * _F0 b_F0 = E.b * _F0 e, n = self.easting, self.northing n_N0 = n - _N0 a, m = _A0, n_N0 sa = Fsum(a) for self._iteration in range(1, _TRIPS): a = sa.fsum_(m / a_F0) m = n_N0 - b_F0 * _M(E.Mabcd, a) # meridional arc if abs(m) < _10um: break else: t = _dot_(_item_ps(self.classname, self.toStr(prec=-3)), self.toLatLon.__name__) raise OSGRError(_no_convergence_, txt=t) sa, ca = sincos2(a) s = E.e2s2(sa) # r, v = E.roc2_(sa, _F0) v = a_F0 / sqrt(s) # nu r = v * E.e12 / s # rho = a_F0 * E.e12 / pow(s, 1.5) == a_F0 * E.e12 / (s * sqrt(s)) vr = v / r # == s / E.e12 x2 = vr - 1 # η2 ta = tan(a) v3, v5, v7 = fpowers(v, 7, 3) # PYCHOK false! ta2, ta4, ta6 = fpowers(ta**2, 3) # PYCHOK false! tar = ta / r V4 = (a, tar / (2 * v), tar / (24 * v3) * fdot( (1, 3, -9), 5 + x2, ta2, ta2 * x2), tar / (720 * v5) * fdot( (61, 90, 45), 1, ta2, ta4)) csa = 1.0 / ca X5 = (_B0, csa / v, csa / (6 * v3) * fsum_(vr, ta2, ta2), csa / (120 * v5) * fdot( (5, 28, 24), 1, ta2, ta4), csa / (5040 * v7) * fdot( (61, 662, 1320, 720), 1, ta2, ta4, ta6)) d, d2, d3, d4, d5, d6, d7 = fpowers(e - _E0, 7) # PYCHOK false! a = fdot(V4, 1, -d2, d4, -d6) b = fdot(X5, 1, d, -d3, d5, -d7) r = _LLEB(degrees90(a), degrees180(b), datum=self.datum, name=self.name) r._iteration = self._iteration # only ellipsoidal LatLon self._latlon = r return self._latlon3(LatLon, datum)
def toRepr(self, prec=6, fmt=_Fmt): # PYCHOK _Named '''Like C{repr(dict)} but with C{name} and C{floats} formatting by C{fstr}. ''' t = pairs(self.items(), prec=prec, fmt=fmt, sep=_EQUAL_) return _item_ps(self.name, _COMMA_SPACE_.join(sorted(t)))
def __repr__(self): return _item_ps(self.named, int.__repr__(self))
def __str__(self): from pygeodesy.named import classname return _item_ps(classname(self, prefixed=True), NN)
def _error(fun, lat, lon, e): '''(INTERNAL) Format an error ''' return _item_cs(_item_ps(fun.__name__, fstr((lat, lon))), e)