def toCartesian(self, **Cartesian_h_datum_kwds):  # PYCHOK Cartesian=Cartesian
        '''Convert this n-vector to C{Nvector}-based cartesian
           (ECEF) coordinates.

           @kwarg Cartesian_h_datum_kwds: Optional L{Cartesian}, B{C{h}},
                  B{C{datum}} and other keyword arguments, ignored if
                  B{C{Cartesian=None}}.  Use B{C{Cartesian=...}}
                  to override this L{Cartesian} class or specify
                  B{C{Cartesian=None}}.

           @return: The cartesian point (L{Cartesian}) or if B{C{Cartesian}}
                    is C{None}, an L{Ecef9Tuple}C{(x, y, z, lat, lon, height,
                    C, M, datum)} with C{C} and C{M} if available.

           @raise TypeError: Invalid B{C{Cartesian}}, B{C{h}}, B{C{datum}} or
                             other B{C{Cartesian_h_datum_kwds}}.

           @example:

           >>> v = Nvector(0.5, 0.5, 0.7071)
           >>> c = v.toCartesian()  # [3194434, 3194434, 4487327]
           >>> p = c.toLatLon()  # 45.0°N, 45.0°E
        '''
        kwds = _xkwds(Cartesian_h_datum_kwds, h=self.h, Cartesian=Cartesian,
                                                            datum=self.datum)
        return NvectorBase.toCartesian(self, **kwds)  # class or .classof
def meanOf(points, datum=Datums.WGS84, height=None, LatLon=LatLon,
                                                  **LatLon_kwds):
    '''Compute the geographic mean of several points.

       @arg points: Points to be averaged (L{LatLon}[]).
       @kwarg datum: Optional datum to use (L{Datum}).
       @kwarg height: Optional height at mean point, overriding
                      the mean height (C{meter}).
       @kwarg LatLon: Optional class to return the mean point
                      (L{LatLon}) or C{None}.
       @kwarg LatLon_kwds: Optional, additional B{C{LatLon}}
                           keyword arguments, ignored if
                           B{C{LatLon=None}}.

       @return: Geographic mean point and mean height (B{C{LatLon}})
                or a L{LatLon3Tuple}C{(lat, lon, height)} if
                B{C{LatLon}} is C{None}.

       @raise ValueError: Insufficient number of B{C{points}}.
    '''
    _, points = _Nvll.points2(points, closed=False)
    # geographic mean
    m = sumOf(p._N_vector for p in points)
    lat, lon, h = m._N_vector.latlonheight

    if height is not None:
        h = height
    if LatLon is None:
        r = LatLon3Tuple(lat, lon, h)
    else:
        kwds = _xkwds(LatLon_kwds, height=h, datum=datum)
        r = LatLon(lat, lon, **kwds)
    return _xnamed(r, meanOf.__name__)
Example #3
0
    def toLatLon(self, LatLon=None, **LatLon_height_datum_kwds):
        '''Return the geodetic C{(lat, lon, height[, datum])} coordinates.

           @kwarg LatLon: Optional class to return C{(lat, lon, height[,
                          datum])} or C{None}.
           @kwarg LatLon_height_datum_kwds: Optional B{C{LatLon}}, B{C{height}},
                                            B{C{datum}} and other keyword arguments.

           @return: An instance of C{LatLon}C{(lat, lon, **_height_datum_kwds)}
                    or if B{C{LatLon}} is C{None}, a L{LatLon3Tuple}C{(lat, lon,
                    height)} respectively L{LatLon4Tuple}C{(lat, lon, height,
                    datum)} whether C{datum} is un-/available.

           @raise TypeError: Invalid B{C{LatLon}} or B{C{LatLon_height_datum_kwds}}.
        '''
        kwds = _xkwds(LatLon_height_datum_kwds,
                      height=self.height,
                      datum=self.datum)  # PYCHOK Ecef9Tuple
        d = kwds['datum']
        if LatLon is None:
            r = LatLon3Tuple(self.lat, self.lon,
                             kwds['height'])  # PYCHOK Ecef9Tuple
            if d:
                r = r.to4Tuple(d)  # checks type(d)
        else:
            if d is None:
                d = kwds.pop['datum']
            r = LatLon(self.lat, self.lon, **kwds)  # PYCHOK Ecef9Tuple
        return self._xnamed(r)
    def toNvector(self, **Nvector_datum_kwds):  # PYCHOK Datums.WGS84
        '''Convert this cartesian to L{Nvector} components,
           I{including height}.

           @kwarg Nvector_datum_kwds: Optional L{Nvector}, B{C{datum}} and
                                      other keyword arguments, ignored if
                                      B{C{Nvector=None}}.  Use
                                      B{C{Nvector=...}} to override this
                                      L{Nvector} class or specify
                                      B{C{Nvector=None}}.

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

           @raise TypeError: Invalid B{C{Nvector}}, B{C{datum}} or other
                             B{C{Nvector_datum_kwds}}.

           @example:

           >>> from ellipsoidalNvector import LatLon
           >>> c = Cartesian(3980581, 97, 4966825)
           >>> n = c.toNvector()  # (0.62282, 0.000002, 0.78237, +0.24)
        '''
        kwds = _xkwds(Nvector_datum_kwds, Nvector=Nvector, datum=self.datum)
        return CartesianEllipsoidalBase.toNvector(self, **kwds)
Example #5
0
    def toLatLon(self, datum=None, LatLon=None, **LatLon_kwds):
        '''Convert this cartesian to a geodetic (lat-/longitude) point.

           @kwarg datum: Optional datum (L{Datum}) or C{None}.
           @kwarg LatLon: Optional class to return the geodetic point
                          (C{LatLon}) or C{None}.
           @kwarg LatLon_kwds: Optional, additional B{C{LatLon}}
                               keyword arguments, ignored if
                               B{C{LatLon=None}}.

           @return: The geodetic point (B{C{LatLon}}) or if B{C{LatLon}}
                    is C{None}, an L{Ecef9Tuple}C{(x, y, z, lat, lon,
                    height, C, M, datum)} with C{C} and C{M} if available.

           @raise TypeError: Invalid B{C{datum}} or B{C{LatLon_kwds}}.
        '''
        if datum in (None, self.datum):
            r = self.toEcef()
        else:
            _xinstanceof(Datum, datum=datum)
            c = self.convertDatum(datum)
            r = c.Ecef(c.datum).reverse(c, M=True)

        if LatLon is not None:  # class or .classof
            r = LatLon(r.lat, r.lon,
                       **_xkwds(LatLon_kwds, datum=r.datum, height=r.height))
        _datum_datum(r.datum, datum or self.datum)
        return self._xnamed(r)
    def toLatLon(
            self,
            **LatLon_height_datum_kwds):  # PYCHOK height=None, LatLon=LatLon
        '''Convert this n-vector to an C{Nvector}-based geodetic point.

           @kwarg LatLon_height_datum_kwds: Optional L{LatLon}, B{C{height}},
                                            B{C{datum}} and other keyword arguments,
                                            ignored if B{C{LatLon=None}}.  Use
                                            B{C{LatLon=...}} to override this
                                            L{LatLon} class or set B{C{LatLon=None}}.

           @return: The geodetic point (L{LatLon}) or a L{LatLon3Tuple}C{(lat,
                    lon, height)} if B{C{LatLon}} is C{None}.

           @raise TypeError: Invalid B{C{LatLon}}, B{C{height}}, B{C{datum}}
                             or other B{C{LatLon_height_datum_kwds}}.

           @example:

           >>> v = Nvector(0.5, 0.5, 0.7071)
           >>> p = v.toLatLon()  # 45.0°N, 45.0°E
        '''
        kwds = _xkwds(LatLon_height_datum_kwds,
                      height=self.h,
                      LatLon=LatLon,
                      datum=self.datum)
        return NvectorBase.toLatLon(self, **kwds)  # class or .classof
    def toNvector(self, **Nvector_datum_kwds):  # PYCHOK signature
        '''Convert this point to L{Nvector} components, I{including
           height}.

           @kwarg Nvector_datum_kwds: Optional L{Nvector}, B{C{datum}} or
                                      other keyword arguments, ignored if
                                      B{C{Nvector=None}}.  Use
                                      B{C{Nvector=...}} to override this
                                      L{Nvector} class or specify
                                      B{C{Nvector=None}}.

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

           @raise TypeError: Invalid B{C{Nvector}}, B{C{datum}} or other
                             B{C{Nvector_datum_kwds}}.

           @example:

           >>> p = LatLon(45, 45)
           >>> n = p.toNvector()
           >>> n.toStr()  # [0.50, 0.50, 0.70710]
        '''
        kwds = _xkwds(Nvector_datum_kwds, Nvector=Nvector, datum=self.datum)
        return LatLonNvectorBase.toNvector(self, **kwds)
Example #8
0
    def reverse(self, easting, northing, LatLon=None, **LatLon_kwds):
        '''Convert a Cassini-Soldner location to (ellipsoidal) geodetic
           lat- and longitude.

           @arg easting: Easting of the location (C{meter}).
           @arg northing: Northing of the location (C{meter}).
           @kwarg LatLon: Optional, ellipsoidal class to return the
                          geodetic location as (C{LatLon}) or C{None}.
           @kwarg LatLon_kwds: Optional (C{LatLon}) keyword arguments,
                               ignored if B{C{LatLon=None}}.

           @return: Geodetic location B{C{LatLon}} or if B{C{LatLon}}
                    is C{None}, a L{LatLon2Tuple}C{(lat, lon)}.

           @raise CSSError: Ellipsoidal mismatch of B{C{LatLon}} and this projection.

           @raise TypeError: Invalid B{C{LatLon}} or B{C{LatLon_kwds}}.

           @see: Method L{CassiniSoldner.reverse4}, L{CassiniSoldner.forward}
                 and L{CassiniSoldner.forward4}.
        '''
        r = self.reverse4(easting, northing)
        if LatLon is None:
            r = LatLon2Tuple(r.lat, r.lon)  # PYCHOK expected
        else:
            _xsubclassof(_LLEB, LatLon=LatLon)
            kwds = _xkwds(LatLon_kwds, datum=self.datum)
            r = LatLon(r.lat, r.lon, **kwds)  # PYCHOK expected
            self._datumatch(r)
        return self._xnamed(r)
Example #9
0
    def toLatLon(self, LatLon, datum=None, **LatLon_kwds):
        '''Convert this WM coordinate to a geodetic point.

           @arg LatLon: Ellipsoidal class to return the geodetic
                        point (C{LatLon}).
           @kwarg datum: Optional datum for ellipsoidal or C{None}
                         for spherical B{C{LatLon}} (C{Datum}).
           @kwarg LatLon_kwds: Optional, additional B{C{LatLon}}
                               keyword arguments.

           @return: Point of this WM coordinate (B{C{LatLon}}).

           @raise TypeError: If B{C{LatLon}} and B{C{datum}} are
                             incompatible or if B{C{datum}} is not
                             ellipsoidal.

           @example:

           >>> w = Wm(448251.795, 5411932.678)
           >>> from pygeodesy import sphericalTrigonometry as sT
           >>> ll = w.toLatLon(sT.LatLon)  # 43°39′11.58″N, 004°01′36.17″E
        '''
        e = issubclassof(LatLon, _LLEB)
        if e and datum:
            kwds = _xkwds(LatLon_kwds, datum=datum)
        elif not (e or datum):  # and LatLon
            kwds = LatLon_kwds
            datum = None
        else:
            raise _TypeError(LatLon=LatLon, datum=datum)

        r = self.latlon2(datum=datum)
        r = LatLon(r.lat, r.lon, **kwds)
        return self._xnamed(r)
Example #10
0
 def _Vector(x, y, z):
     n = intersections2.__name__
     if Vector is None:
         v = Vector3d(x, y, z, name=n)
     else:
         kwds = _xkwds(Vector_kwds, name=n)
         v = Vector(x, y, z, **kwds)
     return v
Example #11
0
 def _latlon4(t, h, n):
     if LatLon is None:
         r = LatLon4Tuple(t.lat, t.lon, h, t.datum)
     else:
         kwds = _xkwds(LatLon_kwds, datum=t.datum, height=h)
         r = LatLon(t.lat, t.lon, **kwds)
     r._iteration = t.iteration  # ._iteration for tests
     return _xnamed(r, n)
Example #12
0
 def _toLatLon(self, lat, lon, LatLon, LatLon_kwds):
     '''(INTERNAL) Check B{C{LatLon}} and return an instance.
     '''
     kwds = _xkwds(LatLon_kwds, datum=self.datum)
     r = LatLon(lat, lon, **kwds)  # handle .classof
     B = _LLEB if self.datum.isEllipsoidal else _LLB
     _xinstanceof(B, LatLon=r)
     return r
Example #13
0
 def __init__(self, *args, **kwds):
     if args:  # args override kwds
         if len(args) != 1:
             t = unstr(self.classname, *args, **kwds)
             raise _ValueError(args=len(args), txt=t)
         kwds = _xkwds(dict(args[0]), **kwds)
     if _name_ in kwds:
         _Named.name.fset(self, kwds.pop(_name_))  # see _Named.name
     dict.__init__(self, kwds)
Example #14
0
def _latlon3(lat, lon, height, func, LatLon, **LatLon_kwds):
    '''(INTERNAL) Helper for L{intersection} and L{meanof}.
    '''
    if LatLon is None:
        r = LatLon3Tuple(lat, lon, height)
    else:
        kwds = _xkwds(LatLon_kwds, height=height)
        r = LatLon(lat, lon, **kwds)
    return _xnamed(r, func.__name__)
Example #15
0
def toWm(latlon, lon=None, radius=R_MA, Wm=Wm, name='', **Wm_kwds):
    '''Convert a lat-/longitude point to a WM coordinate.

       @arg latlon: Latitude (C{degrees}) or an (ellipsoidal or
                    spherical) geodetic C{LatLon} point.
       @kwarg lon: Optional longitude (C{degrees} or C{None}).
       @kwarg radius: Optional earth radius (C{meter}).
       @kwarg Wm: Optional class to return the WM coordinate
                  (L{Wm}) or C{None}.
       @kwarg name: Optional name (C{str}).
       @kwarg Wm_kwds: Optional, additional B{C{Wm}} keyword
                       arguments, ignored if B{C{Wm=None}}.

       @return: The WM coordinate (B{C{Wm}}) or an
                L{EasNorRadius3Tuple}C{(easting, northing, radius)}
                if B{C{Wm}} is C{None}.

       @raise ValueError: If B{C{lon}} value is missing, if B{C{latlon}}
                          is not scalar, if B{C{latlon}} is beyond the
                          valid WM range and L{rangerrors} is set
                          to C{True} or if B{C{radius}} is invalid.

       @example:

       >>> p = LatLon(48.8582, 2.2945)  # 448251.8 5411932.7
       >>> w = toWm(p)  # 448252 5411933
       >>> p = LatLon(13.4125, 103.8667)  # 377302.4 1483034.8
       >>> w = toWm(p)  # 377302 1483035
    '''
    e, r = None, Radius(radius)
    try:
        lat, lon = latlon.lat, latlon.lon
        if isinstance(latlon, _LLEB):
            r = latlon.datum.ellipsoid.a
            e = latlon.datum.ellipsoid.e
            if not name:  # use latlon.name
                name = nameof(latlon)
        lat = clipDegrees(lat, _LatLimit)
    except AttributeError:
        lat, lon = parseDMS2(latlon, lon, clipLat=_LatLimit)

    s = sin(radians(lat))
    y = atanh(s)  # == log(tan((90 + lat) / 2)) == log(tanPI_2_2(radians(lat)))
    if e:
        y -= e * atanh(e * s)

    e, n = r * radians(lon), r * y
    if Wm is None:
        r = EasNorRadius3Tuple(e, n, r)
    else:
        kwds = _xkwds(Wm_kwds, radius=r)
        r = Wm(e, n, **kwds)
    return _xnamed(r, name)
Example #16
0
 def _latlon5(self, LatLon, **LatLon_kwds):
     '''(INTERNAL) Convert cached LatLon
     '''
     ll = self._latlon
     if LatLon is None:
         r = LatLonDatum5Tuple(ll.lat, ll.lon, ll.datum, ll.convergence,
                               ll.scale)
     else:
         _xsubclassof(_LLEB, LatLon=LatLon)
         kwds = _xkwds(LatLon_kwds, datum=ll.datum)
         r = _xattrs(LatLon(ll.lat, ll.lon, **kwds), ll, '_convergence',
                     '_scale')
     return _xnamed(r, ll.name)
Example #17
0
def toMgrs(utm, Mgrs=Mgrs, name=NN, **Mgrs_kwds):
    '''Convert a UTM coordinate to an MGRS grid reference.

       @arg utm: A UTM coordinate (L{Utm} or L{Etm}).
       @kwarg Mgrs: Optional class to return the MGRS grid
                    reference (L{Mgrs}) or C{None}.
       @kwarg name: Optional B{C{Mgrs}} name (C{str}).
       @kwarg Mgrs_kwds: Optional, additional B{C{Mgrs}} keyword
                         arguments, ignored if B{C{Mgrs=None}}.

       @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
    '''
    _xinstanceof(Utm, utm=utm)  # Utm, Etm

    e, n = utm.to2en(falsed=True)
    # truncate east-/northing to within 100 km grid square
    # XXX add rounding to nm precision?
    E, e = divmod(e, _100km)
    N, n = divmod(n, _100km)

    # 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)
    z = utm.zone - 1
    en = (
        _Le100k[z % 3][int(E) - 1] +
        # rows in even zones are A-V, in odd zones are F-E
        _Ln100k[z % 2][int(N) % len(_Ln100k[0])])

    if Mgrs is None:
        r = Mgrs4Tuple(utm.zone, en, e, n).to6Tuple(utm.band, utm.datum)
    else:
        kwds = _xkwds(Mgrs_kwds, band=utm.band, datum=utm.datum)
        r = Mgrs(utm.zone, en, e, n, **kwds)
    return _xnamed(r, name or utm.name)
Example #18
0
    def toLatLon(self, **LatLon_datum_kwds):  # PYCHOK LatLon=LatLon
        '''Convert this cartesian point to an C{Nvector}-based
           geodetic point.

           @kwarg LatLon_datum_kwds: Optional L{LatLon}, B{C{datum}} and
                                     other keyword arguments, ignored if
                                     B{C{LatLon=None}}.  Use
                                     B{C{LatLon=...}} to override this
                                     L{LatLon} class or specify
                                     B{C{LatLon=None}}.

           @return: The geodetic point (L{LatLon}) or if B{C{LatLon}}
                    is C{None}, an L{Ecef9Tuple}C{(x, y, z, lat, lon,
                    height, C, M, datum)} with C{C} and C{M} if available.

           @raise TypeError: Invalid B{C{LatLon_datum_kwds}}.
        '''
        kwds = _xkwds(LatLon_datum_kwds, LatLon=LatLon, datum=self.datum)
        return CartesianSphericalBase.toLatLon(self, **kwds)
    def toCartesian(self, **Cartesian_datum_kwds):  # PYCHOK Cartesian=Cartesian, datum=None
        '''Convert this point to C{Karney}-based cartesian (ECEF)
           coordinates.

           @kwarg Cartesian_datum_kwds: Optional L{Cartesian}, B{C{datum}}
                                        and other keyword arguments, ignored
                                        if B{C{Cartesian=None}}.  Use
                                        B{C{Cartesian=...}} to override
                                        this L{Cartesian} class or specify
                                        B{C{Cartesian=None}}.

           @return: The cartesian point (L{Cartesian}) or if B{C{Cartesian}}
                    is C{None}, an L{Ecef9Tuple}C{(x, y, z, lat, lon, height,
                    C, M, datum)} with C{C} and C{M} if available.

           @raise TypeError: Invalid B{C{Cartesian_datum_kwds}}.
        '''
        kwds = _xkwds(Cartesian_datum_kwds, Cartesian=Cartesian, datum=self.datum)
        return LatLonSphericalBase.toCartesian(self, **kwds)
Example #20
0
 def __init__(self, **kwds):  # PYCHOK no *args
     kwds = _xkwds(kwds, **_Neighbors8Defaults)
     _NamedDict.__init__(self, **kwds)  # name=...
Example #21
0
    def reverse(self, x, y, lon0=0, name=NN, LatLon=None, **LatLon_kwds):
        '''Convert an east- and northing location to geodetic lat- and longitude.

           @arg x: Easting of the location (C{meter}).
           @arg y: Northing of the location (C{meter}).
           @kwarg lon0: Optional central meridian longitude (C{degrees}).
           @kwarg name: Optional name for the location (C{str}).
           @kwarg LatLon: Class to use (C{LatLon}) or C{None}.
           @kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword
                               arguments, ignored if B{C{LatLon=None}}.

           @return: The geodetic (C{LatLon}) or if B{C{LatLon}} is C{None} an
                    L{Albers7Tuple}C{(x, y, lat, lon, gamma, scale, datum)}.

           @note: The origin latitude is returned by C{property lat0}.  No
                  false easting or northing is added.  The returned value of
                  C{lon} is in the range C{[-180..180] degrees} and C{lat}
                  is in the range C{[-90..90] degrees}.  If the given
                  B{C{x}} or B{C{y}} point is outside the valid projected
                  space the nearest pole is returned.
        '''
        x = Scalar(x, name=_x_)
        y = Scalar(y, name=_y_)
        E = self.datum.ellipsoid

        k0 = self._k0
        n0 = self._n0
        k0n0 = self._k0n0
        nrho0 = self._nrho0
        txi0 = self._txi0

        y_ = self._sign * y
        nx = k0n0 * x
        ny = k0n0 * y_
        y1 = nrho0 - ny

        drho = den = nrho0 + hypot(nx,
                                   y1)  # 0 implies origin with polar aspect
        if den:
            drho = fsum_(x * nx, -2 * y_ * nrho0, y_ * ny) * k0 / den
        # dsxia = scxi0 * dsxi
        dsxia = -self._scxi0 * (2 * nrho0 + n0 * drho) * drho / self._qZa2
        t = 1 - dsxia * (2 * txi0 + dsxia)
        txi = (txi0 + dsxia) / (sqrt(t) if t > _EPSX2 else _EPSX)

        ta = self._tanf(txi)
        lat = degrees(atan(ta * self._sign))

        b = atan2(nx, y1)
        lon = degrees(b / self._k02n0 if n0 else x / (y1 * k0))
        if lon0:
            lon += _norm180(_Lon_(lon0, name=_lon0_))
        lon = _norm180(lon)

        if LatLon is None:
            g = degrees360(self._sign * b)
            if den:
                k0 *= (nrho0 + n0 * drho) * hypot1(E.b_a * ta) / E.a
            r = Albers7Tuple(x, y, lat, lon, g, k0, self.datum)
        else:
            kwds = _xkwds(LatLon_kwds, datum=self.datum)
            r = LatLon(lat, lon, **kwds)
        return _xnamed(r, name or self.name)