コード例 #1
0
    def latlon2(self, datum=None):
        '''Convert this WM coordinate to a lat- and longitude.

           @kwarg datum: Optional, ellipsoidal datum (L{Datum},
                         L{Ellipsoid}, L{Ellipsoid2} or
                         L{a_f2Tuple}) or C{None}.

           @return: A L{LatLon2Tuple}C{(lat, lon)}.

           @raise TypeError: Invalid or non-ellipsoidal B{C{datum}}.

           @see: Method C{toLatLon}.
        '''
        r = self.radius
        x = self._x / r
        y = 2 * atan(exp(self._y / r)) - PI_2
        if datum is not None:
            E = _ellipsoidal_datum(datum, name=self.name).ellipsoid
            if not E.isEllipsoidal:
                raise _IsnotError(_ellipsoidal_, datum=datum)
            # <https://Earth-Info.NGA.mil/GandG/wgs84/web_mercator/
            #        %28U%29%20NGA_SIG_0011_1.0.0_WEBMERC.pdf>
            y = y / r
            if E.e:
                y -= E.e * atanh(E.e * tanh(y))  # == E.es_atanh(tanh(y))
            y *= E.a
            x *= E.a / r

        r = LatLon2Tuple(Lat(degrees90(y)), Lon(degrees180(x)))
        return self._xnamed(r)
コード例 #2
0
def flatLocal_(phi2, phi1, lam21, datum=Datums.WGS84):
    '''Compute the I{angular} distance between two (ellipsoidal) points using
       the U{ellipsoidal Earth to plane projection<https://WikiPedia.org/
       wiki/Geographical_distance#Ellipsoidal_Earth_projected_to_a_plane>}
       aka U{Hubeny<https://www.OVG.AT/de/vgi/files/pdf/3781/>} formula.

       @arg phi2: End latitude (C{radians}).
       @arg phi1: Start latitude (C{radians}).
       @arg lam21: Longitudinal delta, M{end-start} (C{radians}).
       @kwarg datum: Ellipsoidal datum to use (L{Datum}, L{Ellipsoid},
                     L{Ellipsoid2} or L{a_f2Tuple}).

       @return: Angular distance (C{radians}).

       @raise TypeError: Invalid B{C{datum}}.

       @note: The meridional and prime_vertical radii of curvature
              are taken and scaled I{at the mean of both latitude}.

       @see: Functions L{flatLocal}/L{hubeny}, L{cosineAndoyerLambert_},
             L{cosineForsytheAndoyerLambert_}, L{cosineLaw_},
             L{flatPolar_}, L{equirectangular_}, L{euclidean_},
             L{haversine_}, L{thomas_} and L{vincentys_} and U{local, flat
             earth approximation <https://www.EdWilliams.org/avform.htm#flat>}.
    '''
    E = _ellipsoidal_datum(datum, name=flatLocal_.__name__).ellipsoid
    m, n = E.roc2_((phi2 + phi1) * _0_5, scaled=True)
    return hypot(m * (phi2 - phi1), n * lam21)
コード例 #3
0
    def __init__(self,
                 easting,
                 northing,
                 band=NN,
                 datum=None,
                 falsed=True,
                 convergence=None,
                 scale=None):
        '''(INTERNAL) New L{UtmUpsBase}.
        '''
        E = self._Error
        if not E:
            notOverloaded(self, '_Error')

        self._easting = Easting(easting, Error=E)
        self._northing = Northing(northing, Error=E)

        if band:
            _xinstanceof(str, band=band)
            self._band = band

        if datum not in (None, self._datum):
            self._datum = _ellipsoidal_datum(datum)  # XXX name=band

        if not falsed:
            self._falsed = False

        if convergence is not self._convergence:
            self._convergence = Scalar(convergence,
                                       name=_convergence_,
                                       Error=E)
        if scale is not self._scale:
            self._scale = Scalar(scale, name=_scale_, Error=E)
コード例 #4
0
    def __init__(self, lat0, lon0, datum=Datums.WGS84, name=NN):
        '''New L{CassiniSoldner} projection.

           @arg lat0: Latitude of center point (C{degrees90}).
           @arg lon0: Longitude of center point (C{degrees180}).
           @kwarg datum: Optional datum or ellipsoid (L{Datum},
                         L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}).
           @kwarg name: Optional name (C{str}).

           @raise CSSError: Invalid B{C{lat}} or B{C{lon}}.

           @raise ImportError: Package U{geographiclib<https://PyPI.org/
                               project/geographiclib>} missing.

           @example:

           >>> p = CassiniSoldner(48 + 50/60.0, 2 + 20/60.0)  # Paris
           >>> p.forward(50.9, 1.8)  # Calais
           (-37518.854545, 230003.561828)

           >>> p.reverse4(-38e3, 230e3)
           (50.899937, 1.793161, 89.580797, 0.999982)
        '''
        if name:
            self.name = name

        if datum not in (None, self._datum):
            self._datum = _xellipsoidal(
                datum=_ellipsoidal_datum(datum, name=name))

        self.reset(lat0, lon0)
コード例 #5
0
ファイル: osgr.py プロジェクト: itzmejawad/PyGeodesy
    def __init__(self, easting, northing, datum=None, name=NN):
        '''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)
        '''
        self._easting = Easting(easting, Error=OSGRError, osgr=True)
        self._northing = Northing(northing, Error=OSGRError, osgr=True)

        if datum not in (None, _Datums_OSGB36):
            try:
                if _ellipsoidal_datum(datum) != _Datums_OSGB36:
                    raise ValueError
            except (TypeError, ValueError):
                raise OSGRError(datum=datum)
        if name:
            self.name = name
コード例 #6
0
ファイル: heights.py プロジェクト: itzmejawad/PyGeodesy
    def _datum_setter(self, datum, knots):
        '''(INTERNAL) Set the datum.

           @raise TypeError: Invalid B{C{datum}}.
        '''
        d = datum or getattr(knots[0], _datum_, datum)
        if d not in (None, self._datum):
            self._datum = _ellipsoidal_datum(d, name=self.name)
コード例 #7
0
def thomas_(phi2, phi1, lam21, datum=Datums.WGS84):
    '''Compute the I{angular} distance between two (ellipsoidal) points using
       U{Thomas'<https://apps.DTIC.mil/dtic/tr/fulltext/u2/703541.pdf>}
       formula.

       @arg phi2: End latitude (C{radians}).
       @arg phi1: Start latitude (C{radians}).
       @arg lam21: Longitudinal delta, M{end-start} (C{radians}).
       @kwarg datum: Ellipsoidal datum to use (L{Datum}, L{Ellipsoid},
                     L{Ellipsoid2} or L{a_f2Tuple}).

       @return: Angular distance (C{radians}).

       @raise TypeError: Invalid B{C{datum}}.

       @see: Functions L{thomas}, L{cosineAndoyerLambert_},
             L{cosineForsytheAndoyerLambert_}, L{cosineLaw_},
             L{equirectangular_}, L{euclidean_}, L{flatLocal_}/L{hubeny_},
             L{flatPolar_}, L{haversine_} and L{vincentys_} and U{Geodesy-PHP
             <https://GitHub.com/jtejido/geodesy-php/blob/master/src/Geodesy/
             Distance/ThomasFormula.php>}.
    '''
    s2, c2, s1, c1, _, c21 = sincos2(phi2, phi1, lam21)
    E = _ellipsoidal_datum(datum, name=thomas_.__name__).ellipsoid
    if E.f and abs(c1) > EPS and abs(c2) > EPS:
        r1 = atan(E.b_a * s1 / c1)
        r2 = atan(E.b_a * s2 / c2)

        j = (r2 + r1) * _0_5
        k = (r2 - r1) * _0_5
        sj, cj, sk, ck, sl_2, _ = sincos2(j, k, lam21 * _0_5)

        h = fsum_(sk**2, (ck * sl_2)**2, -(sj * sl_2)**2)
        if EPS < abs(h) < EPS1:
            u = _1_0 / (_1_0 - h)
            d = atan(sqrt(h * u)) * 2  # == acos(1 - 2 * h)
            sd, cd = sincos2(d)
            if abs(sd) > EPS:
                u = 2 * (sj * ck)**2 * u
                v = 2 * (sk * cj)**2 / h
                x = u + v
                y = u - v

                t = d / sd
                s = 4 * t**2
                e = 2 * cd
                a = s * e
                b = 2 * d
                c = t - (a - e) * _0_5

                s = fsum_(a * x,  c * x**2, -b * y, -e * y**2, s * x * y) * E.f / _16_0
                s = fsum_(t * x, -y, -s) * E.f * _0_25
                return d - s * sd
    # fall back to cosineLaw_
    return acos(s1 * s2 + c1 * c2 * c21)
コード例 #8
0
ファイル: etm.py プロジェクト: rbpdqdat/PyGeodesy
    def datum(self, datum):
        '''Set the datum and ellipsoid (L{Datum}, L{Ellipsoid},
           L{Ellipsoid2} or L{a_f2Tuple}).

           @raise EllipticError: No convergence.

           @raise TypeError: Invalid B{C{datum}}.
        '''
        d = _ellipsoidal_datum(datum, name=self.name, raiser=True)
        self._reset(d.ellipsoid)
        self._datum = d
コード例 #9
0
ファイル: lcc.py プロジェクト: rbpdqdat/PyGeodesy
    def toDatum(self, datum):
        '''Convert this conic to the given datum.

           @arg datum: Ellipsoidal datum to use (L{Datum}, L{Ellipsoid},
                       L{Ellipsoid2} or L{a_f2Tuple}).

           @return: Converted conic, unregistered (L{Conic}).

           @raise TypeError: Non-ellipsoidal B{C{datum}}.
        '''
        d = _ellipsoidal_datum(datum, name=self.name)
        E = d.ellipsoid
        if not E.isEllipsoidal:
            raise _IsnotError(_ellipsoidal_, datum=datum)

        c = self
        if c._e != E.e or c._datum != d:

            c = Conic(None, 0, name=self._name)
            self._dup2(c)
            c._datum = d
            c._e = E.e

            if abs(c._par1 - c._par2) < EPS:
                m1 = c._mdef(c._phi0)
                t1 = c._tdef(c._phi0)
                t0 = t1
                k = 1  # _1_0
                n = sin(c._phi0)
                sp = 1
            else:
                m1 = c._mdef(c._par1)
                m2 = c._mdef(c._par2)
                t1 = c._tdef(c._par1)
                t2 = c._tdef(c._par2)
                t0 = c._tdef(c._phi0)
                k = c._k0
                n  = (log(m1) - log(m2)) \
                   / (log(t1) - log(t2))
                sp = 2

            F = m1 / (n * pow(t1, n))

            c._aF = k * E.a * F
            c._n = n
            c._n_ = _1_0 / n
            c._r0 = c._rdef(t0)
            c._SP = sp

        return c
コード例 #10
0
    def __init__(self,
                 zone,
                 en100k,
                 easting,
                 northing,
                 band=NN,
                 datum=Datums.WGS84,
                 name=NN):
        '''New L{Mgrs} Military grid reference.

           @arg zone: 6° longitudinal zone (C{int}), 1..60 covering 180°W..180°E.
           @arg en100k: Two-letter EN digraph (C{str}), 100 km grid square.
           @arg easting: Easting (C{meter}), within 100 km grid square.
           @arg northing: Northing (C{meter}), within 100 km grid square.
           @kwarg band: Optional 8° latitudinal band (C{str}), C..X covering 80°S..84°N.
           @kwarg datum: Optional this reference's datum (L{Datum}, L{Ellipsoid},
                         L{Ellipsoid2} or L{a_f2Tuple}).
           @kwarg name: Optional name (C{str}).

           @raise MGRSError: Invalid MGRS grid reference, B{C{zone}}, B{C{en100k}},
                             B{C{easting}}, B{C{northing}} or B{C{band}}.

           @raise TypeError: Invalid B{C{datum}}.

           @example:

           >>> from pygeodesy import Mgrs
           >>> m = Mgrs('31U', 'DQ', 48251, 11932)  # 31U DQ 48251 11932
        '''
        if name:
            self.name = name

        self._zone, self._band, self._bandLat = _to3zBlat(
            zone, band, MGRSError)

        try:
            en = str(en100k).upper()
            if len(en) != 2:
                raise IndexError  # caught below
            self._en100k = en
            self._en100k2m()
        except IndexError:
            raise MGRSError(en100k=en100k)

        self._easting = Easting(easting, Error=MGRSError)
        self._northing = Northing(northing, Error=MGRSError)
        if datum not in (None, self._datum):
            self._datum = _ellipsoidal_datum(datum, name=name)
コード例 #11
0
ファイル: etm.py プロジェクト: itzmejawad/PyGeodesy
    def datum(self, datum):
        '''Set the datum and ellipsoid (L{Datum}, L{Ellipsoid},
           L{Ellipsoid2} or L{a_f2Tuple}).

           @raise EllipticError: No convergence.

           @raise TypeError: Invalid B{C{datum}}.
        '''
        d = _ellipsoidal_datum(datum, name=self.name)
        E = d.ellipsoid
        self._reset(E.e, E.e2)
        self._a = E.a
        self._f = E.f  # flattening = (a - b) / a

        self._datum = d
        self._E     = E
コード例 #12
0
def cosineForsytheAndoyerLambert_(phi2, phi1, lam21, datum=Datums.WGS84):
    '''Compute the I{angular} distance between two (ellipsoidal) points using the
       U{Forsythe-Andoyer-Lambert correction<https://www2.UNB.CA/gge/Pubs/TR77.pdf>} of
       the U{Law of Cosines<https://www.Movable-Type.co.UK/scripts/latlong.html#cosine-law>}
       formula.

       @arg phi2: End latitude (C{radians}).
       @arg phi1: Start latitude (C{radians}).
       @arg lam21: Longitudinal delta, M{end-start} (C{radians}).
       @kwarg datum: Ellipsoidal datum to use (L{Datum}, L{Ellipsoid},
                     L{Ellipsoid2} or L{a_f2Tuple}).

       @return: Angular distance (C{radians}).

       @raise TypeError: Invalid B{C{datum}}.

       @see: Functions L{cosineForsytheAndoyerLambert}, L{cosineAndoyerLambert_},
             L{cosineLaw_}, L{equirectangular_}, L{euclidean_}, L{flatLocal_}/L{hubeny_},
             L{flatPolar_}, L{haversine_}, L{thomas_} and L{vincentys_} and U{Geodesy-PHP
             <https://GitHub.com/jtejido/geodesy-php/blob/master/src/Geodesy/
             Distance/ForsytheCorrection.php>}.
    '''
    s2, c2, s1, c1, _, c21 = sincos2(phi2, phi1, lam21)
    r = acos(s1 * s2 + c1 * c2 * c21)
    E = _ellipsoidal_datum(datum, name=cosineForsytheAndoyerLambert_.__name__).ellipsoid
    if E.f:
        sr, cr, s2r, _ = sincos2(r, r * 2)
        if abs(sr) > EPS:
            r2 = r**2

            p = (s1 + s2)**2 / (1 + cr)
            q = (s1 - s2)**2 / (1 - cr)
            x = p + q
            y = p - q
            s = 8 * r2 / sr

            a = 64 * r + 2 * s * cr  # 16 * r2 / tan(r)
            d = 48 * sr + s  # 8 * r2 / tan(r)
            b = -2 * d
            e = 30 * s2r
            c = fsum_(30 * r, e / 2, s * cr)  # 8 * r2 / tan(r)

            d = fsum_(a * x, b * y, -c * x**2, d * x * y, e * y**2) * E.f / _32_0
            d = fsum_(d, -x * r, 3 * y * sr) * E.f * _0_25
            r += d
    return r
コード例 #13
0
    def __init__(self,
                 lat,
                 lon,
                 height=0,
                 datum=None,
                 reframe=None,
                 epoch=None,
                 name=NN):
        '''Create an ellipsoidal C{LatLon} point frome the given
           lat-, longitude and height on the given datum and with
           the given reference frame and epoch.

           @arg lat: Latitude (C{degrees} or DMS C{[N|S]}).
           @arg lon: Longitude (C{degrees} or DMS C{str[E|W]}).
           @kwarg height: Optional elevation (C{meter}, the same units
                          as the datum's half-axes).
           @kwarg datum: Optional, ellipsoidal datum to use (L{Datum},
                         L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}).
           @kwarg reframe: Optional reference frame (L{RefFrame}).
           @kwarg epoch: Optional epoch to observe for B{C{reframe}}
                         (C{scalar}), a non-zero, fractional calendar year.
           @kwarg name: Optional name (string).

           @raise RangeError: Value of B{C{lat}} or B{C{lon}} outside the valid
                              range and C{rangerrors} set to C{True}.

           @raise TypeError: B{C{datum}} is not a L{datum}, B{C{reframe}}
                             is not a L{RefFrame} or B{C{epoch}} is not
                             C{scalar} non-zero.

           @raise UnitError: Invalid B{C{lat}}, B{C{lon}} or B{C{height}}.

           @example:

           >>> p = LatLon(51.4778, -0.0016)  # height=0, datum=Datums.WGS84
        '''
        LatLonBase.__init__(self, lat, lon, height=height, name=name)
        if datum not in (None, self._datum):
            self.datum = _ellipsoidal_datum(datum, name=name)
        if reframe:
            self.reframe = reframe
            self.epoch = epoch
コード例 #14
0
    def convertDatum(self, datum2):
        '''Convert this point to an other datum.

           @arg datum2: Datum to convert I{to} (L{Datum}).

           @return: The converted point (ellipsoidal C{LatLon}).

           @raise TypeError: The B{C{datum2}} invalid.

           @example:

           >>> p = LatLon(51.4778, -0.0016)  # default Datums.WGS84
           >>> p.convertDatum(Datums.OSGB36)  # 51.477284°N, 000.00002°E
        '''
        d2 = _ellipsoidal_datum(datum2, name=self.name)
        if self.datum == d2:
            return self.copy()

        c = self.toCartesian().convertDatum(d2)
        return c.toLatLon(datum=d2, LatLon=self.classof)
コード例 #15
0
def cosineAndoyerLambert_(phi2, phi1, lam21, datum=Datums.WGS84):
    '''Compute the I{angular} distance between two (ellipsoidal) points using the
       U{Andoyer-Lambert correction<https://navlib.net/wp-content/uploads/2013/10/
       admiralty-manual-of-navigation-vol-1-1964-english501c.pdf>} of the U{Law
       of Cosines<https://www.Movable-Type.co.UK/scripts/latlong.html#cosine-law>}
       fromula.

       @arg phi2: End latitude (C{radians}).
       @arg phi1: Start latitude (C{radians}).
       @arg lam21: Longitudinal delta, M{end-start} (C{radians}).
       @kwarg datum: Ellipsoidal datum to use (L{Datum}, L{Ellipsoid},
                     L{Ellipsoid2} or L{a_f2Tuple}).

       @return: Angular distance (C{radians}).

       @raise TypeError: Invalid B{C{datum}}.

       @see: Functions L{cosineAndoyerLambert}, L{cosineForsytheAndoyerLambert_},
             L{cosineLaw_}, L{equirectangular_}, L{euclidean_}, L{flatLocal_}/L{hubeny_},
             L{flatPolar_}, L{haversine_}, L{thomas_} and L{vincentys_} and U{Geodesy-PHP
             <https://GitHub.com/jtejido/geodesy-php/blob/master/src/Geodesy/
             Distance/AndoyerLambert.php>}.
    '''
    s2, c2, s1, c1, _, c21 = sincos2(phi2, phi1, lam21)
    if c2 and c1:
        E = _ellipsoidal_datum(datum, name=cosineAndoyerLambert_.__name__).ellipsoid
        if E.f and abs(c1) > EPS and abs(c2) > EPS:
            r2 = atan(E.b_a * s2 / c2)
            r1 = atan(E.b_a * s1 / c1)
            s2, c2, s1, c1 = sincos2(r2, r1)
            r = acos(s1 * s2 + c1 * c2 * c21)
            sr, _, sr_2, cr_2 = sincos2(r, r * _0_5)
            if abs(sr_2) > EPS and abs(cr_2) > EPS:
                c  = (sr - r) * ((s1 + s2) / cr_2)**2
                s  = (sr + r) * ((s1 - s2) / sr_2)**2
                r += E.f * (c - s) * _0_125
            return r
    # fall back to cosineLaw_
    return acos(s1 * s2 + c1 * c2 * c21)
コード例 #16
0
    def __init__(self, xyz, y=None, z=None, datum=None, ll=None, name=NN):
        '''New C{Cartesian...}.

           @arg xyz: An L{Ecef9Tuple}, L{Vector3Tuple}, L{Vector4Tuple}
                     or the C{X} coordinate (C{scalar}).
           @arg y: The C{Y} coordinate (C{scalar}) if B{C{xyz}} C{scalar}.
           @arg z: The C{Z} coordinate (C{scalar}) if B{C{xyz}} C{scalar}.
           @kwarg datum: Optional datum (L{Datum}, L{Ellipsoid}, L{Ellipsoid2}
                         or L{a_f2Tuple}).
           @kwarg ll: Optional, original latlon (C{LatLon}).
           @kwarg name: Optional name (C{str}).

           @raise TypeError: Non-scalar B{C{xyz}}, B{C{y}} or B{C{z}}
                             coordinate or B{C{xyz}} not an L{Ecef9Tuple},
                             L{Vector3Tuple} or L{Vector4Tuple}.
        '''
        x, y, z, h, d, n = _xyzhdn6(xyz, y, z, None, datum, ll)
        Vector3d.__init__(self, x, y, z, ll=ll, name=name or n)
        if h:
            self._height = h
        if d:
            self.datum = _ellipsoidal_datum(d, name=name)
コード例 #17
0
    def __init__(self, x, y, z, h=0, datum=None, ll=None, name=NN):
        '''New n-vector normal to the earth's surface.

           @arg x: X component (C{meter}).
           @arg y: Y component (C{meter}).
           @arg z: Z component (C{meter}).
           @kwarg h: Optional height above model surface (C{meter}).
           @kwarg datum: Optional datum this n-vector is defined in
                         (L{Datum}, L{Ellipsoid}, L{Ellipsoid2} or
                         L{a_f2Tuple}).
           @kwarg ll: Optional, original latlon (C{LatLon}).
           @kwarg name: Optional name (C{str}).

           @raise TypeError: If B{C{datum}} is not a L{Datum}.

           @example:

           >>> from ellipsoidalNvector import Nvector
           >>> v = Nvector(0.5, 0.5, 0.7071, 1)
           >>> v.toLatLon()  # 45.0°N, 045.0°E, +1.00m
        '''
        NvectorBase.__init__(self, x, y, z, h=h, ll=ll, name=name)
        if datum not in (None, self._datum):
            self._datum = _ellipsoidal_datum(datum, name=name)
コード例 #18
0
    def toNvector(self,
                  Nvector=None,
                  datum=None,
                  **Nvector_kwds):  # PYCHOK Datums.WGS84
        '''Convert this cartesian to C{n-vector} components.

           @kwarg Nvector: Optional class to return the C{n-vector}
                           components (C{Nvector}) or C{None}.
           @kwarg datum: Optional datum (L{Datum}, L{Ellipsoid}, L{Ellipsoid2}
                         or L{a_f2Tuple}) overriding this cartesian's datum.
           @kwarg Nvector_kwds: Optional, additional B{C{Nvector}} keyword
                                arguments, ignored if B{C{Nvector=None}}.

           @return: The C{unit, n-vector} components (B{C{Nvector}}) or a
                    L{Vector4Tuple}C{(x, y, z, h)} if B{C{Nvector}} is C{None}.

           @raise TypeError: Invalid B{C{datum}}.

           @raise ValueError: The B{C{Cartesian}} at origin.

           @example:

           >>> c = Cartesian(3980581, 97, 4966825)
           >>> n = c.toNvector()  # (x=0.622818, y=0.00002, z=0.782367, h=0.242887)
        '''
        d = _ellipsoidal_datum(datum or self.datum, name=self.name)
        r = self._v4t
        if r is None or d != self.datum:
            # <https://www.Movable-Type.co.UK/scripts/geodesy/docs/
            #        latlon-nvector-ellipsoidal.js.html#line309>
            E = d.ellipsoid
            x, y, z = self.xyz

            # Kenneth Gade eqn 23
            p = hypot2(x, y) * E.a2_
            q = (z**2 * E.e12) * E.a2_
            r = fsum_(p, q, -E.e4) / 6
            s = (p * q * E.e4) / (4 * r**3)
            t = cbrt(fsum_(1, s, sqrt(s * (2 + s))))

            u = r * fsum_(_1_0, t, _1_0 / t)
            v = sqrt(u**2 + E.e4 * q)
            w = E.e2 * fsum_(u, v, -q) / (2 * v)

            k = sqrt(fsum_(u, v, w**2)) - w
            if abs(k) < EPS:
                raise _ValueError(origin=self)
            e = k / (k + E.e2)
            #           d = e * hypot(x, y)

            #           tmp = 1 / hypot(d, z) == 1 / hypot(e * hypot(x, y), z)
            t = hypot_(e * x, e * y, z)  # == 1 / tmp
            if t < EPS:
                raise _ValueError(origin=self)
            h = fsum_(k, E.e2, -_1_0) / k * t

            s = e / t  # == e * tmp
            r = Vector4Tuple(x * s, y * s, z / t, h)
            self._v4t = r if d == self.datum else None

        if Nvector is not None:
            r = Nvector(r.x, r.y, r.z, h=r.h, datum=d, **Nvector_kwds)
        return self._xnamed(r)
コード例 #19
0
ファイル: utm.py プロジェクト: itzmejawad/PyGeodesy
def toUtm8(latlon, lon=None, datum=None, Utm=Utm, falsed=True, name=NN,
                                         zone=None, **cmoff):
    '''Convert a lat-/longitude point to a UTM coordinate.

       @arg latlon: Latitude (C{degrees}) or an (ellipsoidal)
                    geodetic C{LatLon} point.
       @kwarg lon: Optional longitude (C{degrees}) or C{None}.
       @kwarg datum: Optional datum for this UTM coordinate,
                     overriding B{C{latlon}}'s datum (L{Datum},
                     L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}).
       @kwarg Utm: Optional class to return the UTM coordinate
                   (L{Utm}) or C{None}.
       @kwarg falsed: False both easting and northing (C{bool}).
       @kwarg name: Optional B{C{Utm}} name (C{str}).
       @kwarg zone: Optional UTM zone to enforce (C{int} or C{str}).
       @kwarg cmoff: DEPRECATED, use B{C{falsed}}.  Offset longitude
                     from the zone's central meridian (C{bool}).

       @return: The UTM coordinate (B{C{Utm}}) or if B{C{Utm}} is
                C{None} or not B{C{falsed}}, a L{UtmUps8Tuple}C{(zone,
                hemipole, easting, northing, band, datum, convergence,
                scale)}.  The C{hemipole} is the C{'N'|'S'} hemisphere.

       @raise RangeError: If B{C{lat}} outside the valid UTM bands or
                          if B{C{lat}} or B{C{lon}} outside the valid
                          range and L{rangerrors} set to C{True}.

       @raise TypeError: Invalid B{C{datum}} or B{C{latlon}} not ellipsoidal.

       @raise UTMError: Invalid B{C{zone}}.

       @raise ValueError: If B{C{lon}} value is missing or if
                          B{C{latlon}} is invalid.

       @note: Implements Karney’s method, using 8-th order Krüger series,
              giving results accurate to 5 nm (or better) for distances
              up to 3900 km from the central meridian.

       @example:

       >>> p = LatLon(48.8582, 2.2945)  # 31 N 448251.8 5411932.7
       >>> u = toUtm(p)  # 31 N 448252 5411933
       >>> p = LatLon(13.4125, 103.8667) # 48 N 377302.4 1483034.8
       >>> u = toUtm(p)  # 48 N 377302 1483035
    '''
    z, B, lat, lon, d, f, name = _to7zBlldfn(latlon, lon, datum,
                                             falsed, name, zone,
                                             UTMError, **cmoff)
    d = _ellipsoidal_datum(d, name=name)
    E = d.ellipsoid

    a, b = radians(lat), radians(lon)
    # easting, northing: Karney 2011 Eq 7-14, 29, 35
    sb, cb = sincos2(b)

    T = tan(a)
    T12 = hypot1(T)
    S = sinh(E.e * atanh(E.e * T / T12))

    T_ = T * hypot1(S) - S * T12
    H = hypot(T_, cb)

    y = atan2(T_, cb)  # ξ' ksi
    x = asinh(sb / H)  # η' eta

    A0 = E.A * getattr(Utm, '_scale0', _K0)  # Utm is class or None

    K = _Kseries(E.AlphaKs, x, y)  # Krüger series
    y = K.ys(y) * A0  # ξ
    x = K.xs(x) * A0  # η

    # convergence: Karney 2011 Eq 23, 24
    p_ = K.ps(1)
    q_ = K.qs(0)
    c = degrees(atan(T_ / hypot1(T_) * tan(b)) + atan2(q_, p_))

    # scale: Karney 2011 Eq 25
    k = E.e2s(sin(a)) * T12 / H * (A0 / E.a * hypot(p_, q_))

    return _toXtm8(Utm, z, lat, x, y,
                        B, d, c, k, f, name, latlon, EPS)
コード例 #20
0
    def __init__(self, sa1, ca1, sa2, ca2, k, datum, name):
        '''(INTERNAL) New C{AlbersEqualArea...} instance.
        '''
        if datum not in (None, self._datum):
            self._datum = _ellipsoidal_datum(datum, name=name)
        if name:
            self.name = name

        E = self.datum.ellipsoid
        b_a = E.b_a  # fm  = 1 - E.f
        e2 = E.e2
        e12 = E.e12  # e2m = 1 - E.e2

        self._qZ = qZ = _1_0 + e12 * self._atanhee(1)
        self._qZa2 = qZ * E.a2
        self._qx = qZ / (_2_0 * e12)

        c = min(ca1, ca2)
        if c < 0:
            raise AlbersError(clat1=ca1, clat2=ca2)
        polar = c < _EPS__2  # == 0
        # determine hemisphere of tangent latitude
        if sa1 < 0:  # and sa2 < 0:
            self._sign = -1
            # internally, tangent latitude positive
            sa1, sa2 = -sa1, neg(sa2)
        if sa1 > sa2:  # make phi1 < phi2
            sa1, sa2 = sa2, sa1
            ca1, ca2 = ca2, ca1
        if sa1 < 0:  # or sa2 < 0:
            raise AlbersError(slat1=sa1, slat2=sa2)
        # avoid singularities at poles
        ca1, ca2 = max(_EPS__2, ca1), max(_EPS__2, ca2)
        ta1, ta2 = sa1 / ca1, sa2 / ca2

        par1 = abs(ta1 - ta2) < _EPS__4  # ta1 == ta2
        if par1 or polar:
            C, ta0 = _1_0, ta2
        else:
            s1_qZ, C = self._s1_qZ_C2(ca1, sa1, ta1, ca2, sa2, ta2)

            ta0 = (ta2 + ta1) * _0_5
            Ta0 = Fsum(ta0)
            tol = _tol(_TOL0, ta0)
            for self._iteration in range(1, _NUMIT0):
                ta02 = ta0**2
                sca02 = ta02 + _1_0
                sca0 = sqrt(sca02)
                sa0 = ta0 / sca0
                sa01 = sa0 + _1_0
                sa02 = sa0**2
                # sa0m = 1 - sa0 = 1 / (sec(a0) * (tan(a0) + sec(a0)))
                sa0m = _1_0 / (sca0 * (ta0 + sca0))  # scb0^2 * sa0
                g = (_1_0 + (b_a * ta0)**2) * sa0
                dg = e12 * sca02 * (_1_0 + 2 * ta02) + e2
                D = sa0m * (_1_0 - e2 *
                            (_1_0 + sa01 * 2 * sa0)) / (e12 * sa01)  # dD/dsa0
                dD = -2 * (_1_0 - e2 * sa02 *
                           (_3_0 + 2 * sa0)) / (e12 * sa01**2)
                sa02_ = _1_0 - e2 * sa02
                sa0m_ = sa0m / (_1_0 - e2 * sa0)
                BA = sa0m_ * (self._atanhx1(e2 * sa0m_**2) * e12 - e2 * sa0m) \
                   - sa0m**2 * e2 * (2 + (_1_0 + e2) * sa0) / (e12 * sa02_)  # == B + A
                dAB = 2 * e2 * (2 - e2 *
                                (_1_0 + sa02)) / (e12 * sa02_**2 * sca02)
                u_du = fsum_(s1_qZ *  g,  -D,  g * BA) \
                     / fsum_(s1_qZ * dg, -dD, dg * BA, g * dAB)  # == u/du
                ta0, d = Ta0.fsum2_(-u_du * (sca0 * sca02))
                if abs(d) < tol:
                    break
            else:
                raise AlbersError(iteration=_NUMIT0,
                                  txt=_no_(Fmt.convergence(tol)))

        self._txi0 = txi0 = self._txif(ta0)
        self._scxi0 = hypot1(txi0)
        self._sxi0 = sxi0 = txi0 / self._scxi0
        self._m02 = m02 = _1_0 / (_1_0 + (b_a * ta0)**2)
        self._n0 = n0 = ta0 / hypot1(ta0)
        if polar:
            self._polar = True
            self._nrho0 = self._m0 = _0_0
        else:
            self._m0 = sqrt(m02)  # == nrho0 / E.a
            self._nrho0 = E.a * self._m0  # == E.a * sqrt(m02)
        self._k0_(_1_0 if par1 else (k * sqrt(C / (m02 + n0 * qZ * sxi0))))
        self._lat0 = _Lat(lat0=self._sign * atand(ta0))
コード例 #21
0
ファイル: ups.py プロジェクト: itzmejawad/PyGeodesy
def toUps8(latlon, lon=None, datum=None, Ups=Ups, pole=NN,
                             falsed=True, strict=True, name=NN):
    '''Convert a lat-/longitude point to a UPS coordinate.

       @arg latlon: Latitude (C{degrees}) or an (ellipsoidal)
                    geodetic C{LatLon} point.
       @kwarg lon: Optional longitude (C{degrees}) or C{None} if
                   B{C{latlon}} is a C{LatLon}.
       @kwarg datum: Optional datum for this UPS coordinate,
                     overriding B{C{latlon}}'s datum (C{Datum},
                     L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}).
       @kwarg Ups: Optional class to return the UPS coordinate
                   (L{Ups}) or C{None}.
       @kwarg pole: Optional top/center of (stereographic) projection
                    (C{str}, C{'N[orth]'} or C{'S[outh]'}).
       @kwarg falsed: False both easting and northing (C{bool}).
       @kwarg strict: Restrict B{C{lat}} to UPS ranges (C{bool}).
       @kwarg name: Optional B{C{Ups}} name (C{str}).

       @return: The UPS coordinate (B{C{Ups}}) or a
                L{UtmUps8Tuple}C{(zone, hemipole, easting, northing,
                band, datum, convergence, scale)} if B{C{Ups}} is
                C{None}.  The C{hemipole} is the C{'N'|'S'} pole,
                the UPS projection top/center.

       @raise RangeError: If B{C{strict}} and B{C{lat}} outside the
                          valid UPS bands or if B{C{lat}} or B{C{lon}}
                          outside the valid range and L{rangerrors}
                          set to C{True}.

       @raise TypeError: If B{C{latlon}} is not ellipsoidal or
                         B{C{datum}} invalid.

       @raise ValueError: If B{C{lon}} value is missing or if B{C{latlon}}
                          is invalid.

       @see: I{Karney}'s C++ class U{UPS
             <https://GeographicLib.SourceForge.io/html/classGeographicLib_1_1UPS.html>}.
    '''
    lat, lon, d, name = _to4lldn(latlon, lon, datum, name)
    z, B, p, lat, lon = upsZoneBand5(lat, lon, strict=strict)  # PYCHOK UtmUpsLatLon5Tuple

    d = _ellipsoidal_datum(d, name=name)
    E = d.ellipsoid

    p = str(pole or p)[:1].upper()
    N = p == _N_  # is north

    a = lat if N else -lat
    A = abs(a - 90) < _TOL  # at pole

    t = tan(radians(a))
    T = E.es_taupf(t)
    r = hypot1(T) + abs(T)
    if T >= 0:
        r = 0 if A else 1 / r

    k0 = getattr(Ups, '_scale0', _K0)  # Ups is class or None
    r *= 2 * k0 * E.a / E.es_c

    k = k0 if A else _scale(E, r, t)
    c = lon  # [-180, 180) from .upsZoneBand5
    x, y = sincos2d(c)
    x *= r
    y *= r
    if N:
        y = -y
    else:
        c = -c

    if falsed:
        x += _Falsing
        y += _Falsing

    if Ups is None:
        r = UtmUps8Tuple(z, p, x, y, B, d, c, k, Error=UPSError)
    else:
        if z != _UPS_ZONE and not strict:
            z = _UPS_ZONE  # ignore UTM zone
        r = Ups(z, p, x, y, band=B, datum=d, falsed=falsed,
                                    convergence=c, scale=k)
        r._hemisphere = _hemi(lat)
        if isinstance(latlon, _LLEB) and d is latlon.datum:
            r._latlon_to(latlon, falsed)  # XXX weakref(latlon)?
    return _xnamed(r, name)