コード例 #1
0
    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 C{B{LatLon}=None}.  Use
                                            B{C{LatLon=...}} to override this
                                            L{LatLon} class or set C{B{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
コード例 #2
0
    def toLatLon(self,
                 datum=None,
                 LatLon=None,
                 **LatLon_kwds):  # see .ecef.Ecef9Tuple.convertDatum
        '''Convert this cartesian to a geodetic (lat-/longitude) point.

           @kwarg datum: Optional datum (L{Datum}, L{Ellipsoid}, L{Ellipsoid2}
                         or L{a_f2Tuple}).
           @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
                               C{B{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}}.
        '''
        d = self.datum
        if datum in (None, d):
            r = self.toEcef()
        else:
            c = self.convertDatum(datum)
            d = c.datum
            r = c.Ecef(d).reverse(c, M=True)

        if LatLon is not None:  # class or .classof
            kwds = _xkwds(LatLon_kwds, datum=r.datum, height=r.height)
            r = LatLon(r.lat, r.lon, **kwds)
        _datum_datum(r.datum, d)
        return self._xnamed(r)
コード例 #3
0
    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)
コード例 #4
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
                             invalid or 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)
コード例 #5
0
def _triangulate(point1,
                 bearing1,
                 point2,
                 bearing2,
                 height=None,
                 **LatLon_LatLon_kwds):
    # (INTERNAL)Locate a point given two known points and initial
    # bearings from those points, see LatLon.triangulate above

    def _gc(p, b, _i_):
        n = p.toNvector()
        de = NorthPole.cross(n, raiser=_pole_).unit()  # east vector @ n
        dn = n.cross(de)  # north vector @ n
        s, c = sincos2d(Bearing(b, name=_bearing_ + _i_))
        dest = de.times(s)
        dnct = dn.times(c)
        d = dnct.plus(dest)  # direction vector @ n
        return n.cross(d)  # great circle point + bearing

    if point1.isequalTo(point2, EPS):
        raise _ValueError(points=point2, txt=_coincident_)

    gc1 = _gc(point1, bearing1, _1_)  # great circle p1 + b1
    gc2 = _gc(point2, bearing2, _2_)  # great circle p2 + b2

    n = gc1.cross(gc2, raiser=_points_)  # n-vector of intersection point

    h = point1._havg(point2) if height is None else Height(height)
    kwds = _xkwds(LatLon_LatLon_kwds, height=h)
    return n.toLatLon(**kwds)  # Nvector(n.x, n.y, n.z).toLatLon(...)
コード例 #6
0
ファイル: css.py プロジェクト: rbpdqdat/PyGeodesy
    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 C{B{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)
コード例 #7
0
    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
コード例 #8
0
    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)
コード例 #9
0
ファイル: vector3d.py プロジェクト: rbpdqdat/PyGeodesy
def _V_n(v, name, Vector, Vector_kwds):
    # return a named Vector instance
    if Vector is None:
        v = _xnamed(v, name)
    else:
        kwds = _xkwds(Vector_kwds, name=name)
        v = Vector(v.x, v.y, v.z, **kwds)
    return v
コード例 #10
0
ファイル: azimuthal.py プロジェクト: rbpdqdat/PyGeodesy
 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
コード例 #11
0
def _LatLon4Tuple(lat, lon, height, datum, LatLon, LatLon_kwds):
    '''(INTERNAL) Return a L{LatLon4Tuple} or an B{C{LatLon}} instance.
    '''
    if LatLon is None:
        r = LatLon4Tuple(lat, lon, height, datum)
    else:
        kwds = _xkwds(LatLon_kwds, datum=datum, height=height)
        r = LatLon(lat, lon, **kwds)
    return r
コード例 #12
0
ファイル: named.py プロジェクト: rbpdqdat/PyGeodesy
 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)
コード例 #13
0
ファイル: utmupsBase.py プロジェクト: rbpdqdat/PyGeodesy
 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)
コード例 #14
0
def toWm(latlon, lon=None, radius=R_MA, Wm=Wm, name=NN, **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 = r * radians(lon)
    n = r * y
    r = EasNorRadius3Tuple(e, n, r) if Wm is None else \
                        Wm(e, n, **_xkwds(Wm_kwds, radius=r))
    return _xnamed(r, name)
コード例 #15
0
    def toLatLon(self, **LatLon_datum_kwds):  # PYCHOK LatLon=LatLon
        '''Convert this cartesian to an C{Nvector}-based geodetic point.

           @kwarg LatLon_datum_kwds: Optional L{LatLon}, B{C{datum}} and
                  other keyword arguments, ignored if C{B{LatLon}=None}.
                  Use B{C{LatLon=...}} to override the L{LatLon} class
                  or specify C{B{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)
コード例 #16
0
ファイル: mgrs.py プロジェクト: rbpdqdat/PyGeodesy
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.eastingnorthing2(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)
コード例 #17
0
    def toCartesian(self, **Cartesian_h_kwds):  # PYCHOK Cartesian=Cartesian
        '''Convert this n-vector to C{Nvector}-based cartesian
           (ECEF) coordinates.

           @kwarg Cartesian_h_kwds: Optional L{Cartesian}, B{C{h}} 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}} or other
                             B{C{Cartesian_h_kwds}}.
        '''
        kwds = _xkwds(Cartesian_h_kwds, h=self.h, Cartesian=Cartesian)
        return NvectorBase.toCartesian(self, **kwds)  # class or .classof
コード例 #18
0
    def toLatLon(self, **LatLon_height_kwds):  # PYCHOK height=None, LatLon=LatLon
        '''Convert this n-vector to an C{Nvector}-based geodetic point.

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

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

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

           @raise ValueError: Invalid B{C{height}}.
        '''
        kwds = _xkwds(LatLon_height_kwds, height=self.h, LatLon=LatLon)
        return NvectorBase.toLatLon(self, **kwds)  # class or .classof
コード例 #19
0
    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 the 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_datum_kwds}}.
        '''
        # ll = CartesianBase.toLatLon(self, LatLon=LatLon,
        #                                    datum=datum or self.datum)
        # kwds = _xkwds(kwds, Nvector=Nvector)
        # return ll.toNvector(**kwds)
        kwds = _xkwds(Nvector_datum_kwds, Nvector=Nvector, datum=self.datum)
        return CartesianSphericalBase.toNvector(self, **kwds)
コード例 #20
0
    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 set B{C{Cartesian=None}}.

           @return: The cartesian (ECEF) coordinates (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{datum}} or other
                             B{C{Cartesian_datum_kwds}}.
        '''
        kwds = _xkwds(Cartesian_datum_kwds,
                      Cartesian=Cartesian,
                      datum=self.datum)
        return LatLonEllipsoidalBase.toCartesian(self, **kwds)
コード例 #21
0
def meanOf(points, height=None, LatLon=LatLon, **LatLon_kwds):
    '''Compute the geographic mean of the supplied points.

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

       @return: Point at geographic mean and mean height (B{C{LatLon}}).

       @raise PointsError: Insufficient number of B{C{points}}.

       @raise TypeError: Some B{C{points}} are not C{LatLon}.
    '''
    n, points = _Nvll.points2(points, closed=False)
    # geographic mean
    m = sumOf(points[i]._N_vector for i in range(n))
    kwds = _xkwds(LatLon_kwds, height=height, LatLon=LatLon)
    return m.toLatLon(**kwds)
コード例 #22
0
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
                           C{B{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__)
コード例 #23
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 C{B{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 = Meter(x=x)
        y = Meter(y=y)

        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_0 * y_ * nrho0, y_ * ny) * k0 / den
        # dsxia = scxi0 * dsxi
        dsxia = -self._scxi0 * (_2_0 * nrho0 + n0 * drho) * drho / self._qZa2
        t = _1_0 - dsxia * (_2_0 * txi0 + dsxia)
        txi = (txi0 + dsxia) / (sqrt(t) if t > _EPS__4 else _EPS__2)

        ta = self._tanf(txi)
        lat = atand(ta * self._sign)

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

        if LatLon is None:
            g = degrees360(self._sign * th)
            if den:
                k0 = self._azik(nrho0 + n0 * drho, ta)
            r = Albers7Tuple(x, y, lat, lon, g, k0, self.datum)
        else:
            kwds = _xkwds(LatLon_kwds, datum=self.datum)
            r = LatLon(lat, lon, **kwds)
        return self._xnamed(r, name=name)
コード例 #24
0
def _trilaterate(point1,
                 distance1,
                 point2,
                 distance2,
                 point3,
                 distance3,
                 radius=R_M,
                 height=None,
                 useZ=False,
                 **LatLon_LatLon_kwds):
    # (INTERNAL) Locate a point at given distances from
    # three other points, see LatLon.triangulate above

    def _nd2(p, d, r, _i_, *qs):  # .toNvector and angular distance squared
        for q in qs:
            if p.isequalTo(q, EPS):
                raise _ValueError(points=p, txt=_coincident_)
        return p.toNvector(), (Scalar(d, name=_distance_ + _i_) / r)**2

    r = Radius_(radius)

    n1, r12 = _nd2(point1, distance1, r, _1_)
    n2, r22 = _nd2(point2, distance2, r, _2_, point1)
    n3, r32 = _nd2(point3, distance3, r, _3_, point1, point2)

    # the following uses x,y coordinate system with origin at n1, x axis n1->n2
    y = n3.minus(n1)
    x = n2.minus(n1)
    z = None

    d = x.length  # distance n1->n2
    if d > EPS_2:  # and y.length > EPS_2:
        X = x.unit()  # unit vector in x direction n1->n2
        i = X.dot(y)  # signed magnitude of x component of n1->n3
        Y = y.minus(X.times(i)).unit()  # unit vector in y direction
        j = Y.dot(y)  # signed magnitude of y component of n1->n3
        if abs(j) > EPS_2:
            # courtesy Carlos Freitas <https://GitHub.com/mrJean1/PyGeodesy/issues/33>
            x = fsum_(r12, -r22, d**2) / (2 * d)  # n1->intersection x- and ...
            y = fsum_(r12, -r32, i**2, j**2, -2 * x * i) / (
                2 * j)  # ... y-component
            # courtesy AleixDev <https://GitHub.com/mrJean1/PyGeodesy/issues/43>
            z = fsum_(max(r12, r22, r32), -(x**2),
                      -(y**2))  # XXX not just r12!
            if z > EPS:
                n = n1.plus(X.times(x)).plus(Y.times(y))
                if useZ:  # include Z component
                    Z = X.cross(Y)  # unit vector perpendicular to plane
                    n = n.plus(Z.times(sqrt(z)))
                if height is None:
                    h = fidw((point1.height, point2.height, point3.height),
                             map1(fabs, distance1, distance2, distance3))
                else:
                    h = Height(height)
                kwds = _xkwds(LatLon_LatLon_kwds, height=h)
                return n.toLatLon(**
                                  kwds)  # Nvector(n.x, n.y, n.z).toLatLon(...)

    # no intersection, d < EPS_2 or abs(j) < EPS_2 or z < EPS
    t = NN(_no_, _intersection_, _SPACE_)
    raise IntersectionError(point1=point1,
                            distance1=distance1,
                            point2=point2,
                            distance2=distance2,
                            point3=point3,
                            distance3=distance3,
                            txt=unstr(t, z=z, useZ=useZ))
コード例 #25
0
def intersection(start1, end1, start2, end2,
                 height=None, LatLon=LatLon, **LatLon_kwds):
    '''Locate the intersection of two paths each defined by two
       points or by a start point and an initial bearing.

       @arg start1: Start point of the first path (L{LatLon}).
       @arg end1: End point of the first path (L{LatLon}) or the
                  initial bearing at the first start point
                  (compass C{degrees360}).
       @arg start2: Start point of the second path (L{LatLon}).
       @arg end2: End point of the second path (L{LatLon}) or the
                  initial bearing at the second start point
                  (compass C{degrees360}).
       @kwarg height: Optional height at the intersection point,
                      overriding the mean height (C{meter}).
       @kwarg LatLon: Optional class to return the intersection
                      point (L{LatLon}).
       @kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword
                           arguments, ignored if C{B{LatLon}=None}.

       @return: The intersection point (B{C{LatLon}}) or 3-tuple
                (C{degrees90}, C{degrees180}, height) if B{C{LatLon}}
                is C{None} or C{None} if no unique intersection
                exists.

       @raise TypeError: If B{C{start*}} or B{C{end*}} is not L{LatLon}.

       @raise ValueError: Intersection is ambiguous or infinite or
                          the paths are parallel, coincident or null.

       @example:

       >>> p = LatLon(51.8853, 0.2545)
       >>> q = LatLon(49.0034, 2.5735)
       >>> i = intersection(p, 108.55, q, 32.44)  # 50.9076°N, 004.5086°E
    '''
    _Nvll.others(start1=start1)
    _Nvll.others(start2=start2)

    # If gc1 and gc2 are great circles through start and end points
    # (or defined by start point and bearing), then the candidate
    # intersections are simply gc1 × gc2 and gc2 × gc1.  Most of the
    # work is deciding the correct intersection point to select!  If
    # bearing is given, that determines the intersection, but if both
    # paths are defined by start/end points, take closer intersection.
    gc1, s1, e1 = _Nvll._gc3(start1, end1, 'end1')
    gc2, s2, e2 = _Nvll._gc3(start2, end2, 'end2')

    hs = start1.height, start2.height
    # there are two (antipodal) candidate intersection
    # points ... we have to choose the one to return
    i1 = gc1.cross(gc2, raiser=_paths_)
    # postpone computing i2 until needed
    # i2 = gc2.cross(gc1, raiser=_paths_)

    # selection of intersection point depends on how
    # paths are defined (by bearings or endpoints)
    if e1 and e2:  # endpoint+endpoint
        d = sumOf((s1, s2, e1, e2)).dot(i1)
        hs += end1.height, end2.height
    elif e1 and not e2:  # endpoint+bearing
        # gc2 x v2 . i1 +ve means v2 bearing points to i1
        d = gc2.cross(s2).dot(i1)
        hs += end1.height,
    elif e2 and not e1:  # bearing+endpoint
        # gc1 x v1 . i1 +ve means v1 bearing points to i1
        d = gc1.cross(s1).dot(i1)
        hs += end2.height,
    else:  # bearing+bearing
        # if gc x v . i1 is +ve, initial bearing is
        # towards i1, otherwise towards antipodal i2
        d1 = gc1.cross(s1).dot(i1)  # +ve means p1 bearing points to i1
        d2 = gc2.cross(s2).dot(i1)  # +ve means p2 bearing points to i1
        if d1 > 0 and d2 > 0:
            d = 1  # both point to i1
        elif d1 < 0 and d2 < 0:
            d = -1  # both point to i2
        else:  # d1, d2 opposite signs
            # intersection is at further-away intersection
            # point, take opposite intersection from mid-
            # point of v1 and v2 [is this always true?]
            d = neg(s1.plus(s2).dot(i1))

    i = i1 if d > 0 else gc2.cross(gc1, raiser=_paths_)

    h = fmean(hs) if height is None else height
    kwds = _xkwds(LatLon_kwds, height=h, LatLon=LatLon)
    return i.toLatLon(**kwds)  # Nvector(i.x, i.y, i.z).toLatLon(...)