コード例 #1
0
ファイル: heights.py プロジェクト: tranngocphu/PyGeodesy
 def _distances(self, x, y):  # (x, y) degrees
     g = self._geodesic
     for ll in self._lls:
         # see .ellipsoidalKarney.LatLon._inverse
         _, lon = unroll180(x, ll.lon, wrap=self._wrap)  # g.LONG_UNROLL
         # XXX g.DISTANCE needed for 's12', distance in meters?
         yield abs(g.Inverse(y, x, ll.lat, lon)['a12'])
コード例 #2
0
def cosineAndoyerLambert(lat1, lon1, lat2, lon2, datum=Datums.WGS84, wrap=False):
    '''Compute the 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 lat1: Start latitude (C{degrees}).
       @arg lon1: Start longitude (C{degrees}).
       @arg lat2: End latitude (C{degrees}).
       @arg lon2: End longitude (C{degrees}).
       @kwarg datum: Ellipsoidal datum to use (L{Datum}, L{Ellipsoid},
                     L{Ellipsoid2} or L{a_f2Tuple}).
       @kwarg wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: Distance (C{meter}, same units as the B{C{datum}}'s
                ellipsoid axes).

       @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 method
             L{Ellipsoid.distance2}.
    '''
    d, _ = unroll180(lon1, lon2, wrap=wrap)
    r = cosineAndoyerLambert_(Phi_(lat2=lat2),
                              Phi_(lat1=lat1), radians(d), datum=datum)
    return r * datum.ellipsoid.a
コード例 #3
0
def flatLocal(lat1, lon1, lat2, lon2, datum=Datums.WGS84, wrap=False):
    '''Compute the 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 lat1: Start latitude (C{degrees}).
       @arg lon1: Start longitude (C{degrees}).
       @arg lat2: End latitude (C{degrees}).
       @arg lon2: End longitude (C{degrees}).
       @kwarg datum: Ellipsoidal datum to use (L{Datum}, L{Ellipsoid},
                     L{Ellipsoid2} or L{a_f2Tuple}).
       @kwarg wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: Distance (C{meter}, same units as the B{C{datum}}'s
                ellipsoid axes).

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

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

       @see: Functions L{flatLocal_}/L{hubeny_}, L{cosineLaw},
             L{flatPolar}, L{cosineAndoyerLambert}, L{cosineForsytheAndoyerLambert},
             L{equirectangular}, L{euclidean}, L{haversine}, L{thomas}, L{vincentys},
             method L{Ellipsoid.distance2} and U{local, flat earth approximation
             <https://www.EdWilliams.org/avform.htm#flat>}.
    '''
    d, _ = unroll180(lon1, lon2, wrap=wrap)
    return flatLocal_(Phi_(lat2=lat2),
                      Phi_(lat1=lat1), radians(d), datum=datum)
コード例 #4
0
ファイル: formy.py プロジェクト: dholle2/cs411-project
def vincentys(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
    '''Compute the distance between two (spherical) points using
       U{Vincenty's<https://WikiPedia.org/wiki/Great-circle_distance>}
       spherical formula.

       @arg lat1: Start latitude (C{degrees}).
       @arg lon1: Start longitude (C{degrees}).
       @arg lat2: End latitude (C{degrees}).
       @arg lon2: End longitude (C{degrees}).
       @kwarg radius: Mean earth radius (C{meter}).
       @kwarg wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: Distance (C{meter}, same units as B{C{radius}}).

       @see: Functions L{vincentys_}, L{cosineLaw}, L{equirectangular},
             L{euclidean}, L{flatLocal}, L{flatPolar}, L{haversine} and
             methods L{Ellipsoid.distance2}, C{LatLon.distanceTo*} and
             C{LatLon.equirectangularTo}.

       @note: See note at function L{vincentys_}.
    '''
    r = Radius(radius)
    if r:
        d, _ = unroll180(lon1, lon2, wrap=wrap)
        r *= vincentys_(Phi_(lat2, name='lat2'), Phi_(lat1, name='lat1'),
                        radians(d))
    return r
コード例 #5
0
ファイル: formy.py プロジェクト: baris-ekici/PyGeodesy
def thomas(lat1, lon1, lat2, lon2, datum=Datums.WGS84, wrap=False):
    '''Compute the distance between two (ellipsoidal) points using
       U{Thomas'<https://apps.DTIC.mil/dtic/tr/fulltext/u2/703541.pdf>}
       formula.

       @arg lat1: Start latitude (C{degrees}).
       @arg lon1: Start longitude (C{degrees}).
       @arg lat2: End latitude (C{degrees}).
       @arg lon2: End longitude (C{degrees}).
       @kwarg datum: Ellipsoidal datum to use (L{Datum}).
       @kwarg wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: Distance (C{meter}, same units as the B{C{datum}}'s
                ellipsoid axes).

       @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}, L{vincentys} and method L{Ellipsoid.distance2}.
    '''
    d, _ = unroll180(lon1, lon2, wrap=wrap)
    r = thomas_(Phi_(lat2, name=_lat2_),
                Phi_(lat1, name=_lat1_),
                radians(d),
                datum=datum)
    return r * datum.ellipsoid.a
コード例 #6
0
ファイル: formy.py プロジェクト: dholle2/cs411-project
def cosineLaw(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
    '''Compute the distance between two points using the
       U{spherical Law of Cosines
       <https://www.Movable-Type.co.UK/scripts/latlong.html#cosine-law>}
       fromula.

       @arg lat1: Start latitude (C{degrees}).
       @arg lon1: Start longitude (C{degrees}).
       @arg lat2: End latitude (C{degrees}).
       @arg lon2: End longitude (C{degrees}).
       @kwarg radius: Mean earth radius (C{meter}).
       @kwarg wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: Distance (C{meter}, same units as B{C{radius}}).

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

       @see: Functions L{cosineLaw_}, L{equirectangular}, L{euclidean},
             L{flatLocal}, L{flatPolar}, L{haversine}, L{vincentys} and
             method L{Ellipsoid.distance2}.

       @note: See note at function L{vincentys_}.
    '''
    r = Radius(radius)
    if r:
        d, _ = unroll180(lon1, lon2, wrap=wrap)
        r *= cosineLaw_(Phi_(lat2, name='lat2'), Phi_(lat1, name='lat1'),
                        radians(d))
    return r
コード例 #7
0
ファイル: formy.py プロジェクト: dholle2/cs411-project
def compassAngle(lat1, lon1, lat2, lon2, adjust=True, wrap=False):
    '''Return the angle from North for the direction vector
       M{(lon2 - lon1, lat2 - lat1)} between two points.

       Suitable only for short, non-near-polar vectors up to a few
       hundred Km or Miles.  Use function L{bearing} for longer
       vectors.

       @arg lat1: From latitude (C{degrees}).
       @arg lon1: From longitude (C{degrees}).
       @arg lat2: To latitude (C{degrees}).
       @arg lon2: To longitude (C{degrees}).
       @kwarg adjust: Adjust the longitudinal delta by the
                      cosine of the mean latitude (C{bool}).
       @kwarg wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: Compass angle from North (C{degrees360}).

       @note: Courtesy Martin Schultz.

       @see: U{Local, flat earth approximation
             <https://www.EdWilliams.org/avform.htm#flat>}.
    '''
    d_lon, _ = unroll180(lon1, lon2, wrap=wrap)
    if adjust:  # scale delta lon
        d_lon *= _scaled(lat1, lat2)
    return degrees360(atan2(d_lon, lat2 - lat1))
コード例 #8
0
ファイル: formy.py プロジェクト: dholle2/cs411-project
def euclidean(lat1, lon1, lat2, lon2, radius=R_M, adjust=True, wrap=False):
    '''Approximate the C{Euclidian} distance between two (spherical) points.

       @arg lat1: Start latitude (C{degrees}).
       @arg lon1: Start longitude (C{degrees}).
       @arg lat2: End latitude (C{degrees}).
       @arg lon2: End longitude (C{degrees}).
       @kwarg radius: Mean earth radius (C{meter}).
       @kwarg adjust: Adjust the longitudinal delta by the cosine
                      of the mean latitude (C{bool}).
       @kwarg wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: Distance (C{meter}, same units as B{C{radius}}).

       @see: U{Distance between two (spherical) points
             <https://www.EdWilliams.org/avform.htm#Dist>}, functions
             L{euclidean_}, L{cosineLaw}, L{equirectangular}, L{flatLocal},
             L{flatPolar}, L{haversine}, L{vincentys} and methods
             L{Ellipsoid.distance2}, C{LatLon.distanceTo*} and
             C{LatLon.equirectangularTo}.
    '''
    r = Radius(radius)
    if r:
        d, _ = unroll180(lon1, lon2, wrap=wrap)
        r *= euclidean_(Phi_(lat2, name='lat2'),
                        Phi_(lat1, name='lat1'),
                        radians(d),
                        adjust=adjust)
    return r
コード例 #9
0
def haversine(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
    '''Compute the distance between two (spherical) points using the
       U{Haversine<https://www.Movable-Type.co.UK/scripts/latlong.html>}
       formula.

       @param lat1: Start latitude (C{degrees}).
       @param lon1: Start longitude (C{degrees}).
       @param lat2: End latitude (C{degrees}).
       @param lon2: End longitude (C{degrees}).
       @keyword radius: Optional, mean earth radius (C{meter}).
       @keyword wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: Distance (C{meter}, same units as B{C{radius}}).

       @see: U{Distance between two (spherical) points
             <https://www.EdWilliams.org/avform.htm#Dist>}, functions
             L{equirectangular}, L{euclidean} and L{vincentys} and
             methods L{Ellipsoid.distance2}, C{LatLon.distanceTo*}
             and C{LatLon.equirectangularTo}.

       @note: See note under L{vincentys_}.
    '''
    d, _ = unroll180(lon1, lon2, wrap=wrap)
    r = haversine_(radians(lat2), radians(lat1), radians(d))
    return r * float(radius)
コード例 #10
0
ファイル: formy.py プロジェクト: dholle2/cs411-project
def flatLocal(lat1, lon1, lat2, lon2, datum=Datums.WGS84, wrap=False):
    '''Compute the 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>}
       fromula.

       @arg lat1: Start latitude (C{degrees}).
       @arg lon1: Start longitude (C{degrees}).
       @arg lat2: End latitude (C{degrees}).
       @arg lon2: End longitude (C{degrees}).
       @kwarg datum: Optional, (ellipsoidal) datum to use (L{Datum}).
       @kwarg wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: Distance (C{meter}, same units as the B{C{datum}}'s
                ellipsoid axes).

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

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

       @see: Functions L{flatLocal_}, L{cosineLaw}, L{flatPolar},
             L{equirectangular}, L{euclidean}, L{haversine},
             L{vincentys}, method L{Ellipsoid.distance2} and
             U{local, flat earth approximation
             <https://www.edwilliams.org/avform.htm#flat>}.
    '''
    d, _ = unroll180(lon1, lon2, wrap=wrap)
    return flatLocal_(Phi_(lat2, name='lat2'),
                      Phi_(lat1, name='lat1'),
                      radians(d),
                      datum=datum)
コード例 #11
0
ファイル: formy.py プロジェクト: dholle2/cs411-project
def flatPolar(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
    '''Compute the distance between two (spherical) points using
       the U{polar coordinate flat-Earth
       <https://WikiPedia.org/wiki/Geographical_distance#Polar_coordinate_flat-Earth_formula>}
       formula.

       @arg lat1: Start latitude (C{degrees}).
       @arg lon1: Start longitude (C{degrees}).
       @arg lat2: End latitude (C{degrees}).
       @arg lon2: End longitude (C{degrees}).
       @kwarg radius: Mean earth radius (C{meter}).
       @kwarg wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: Distance (C{meter}, same units as B{C{radius}}).

       @see: Functions L{flatPolar_}, L{cosineLaw}, L{flatLocal},
             L{equirectangular}, L{euclidean}, L{haversine} and
             L{vincentys}.
    '''
    r = Radius(radius)
    if r:
        d, _ = unroll180(lon1, lon2, wrap=wrap)
        r *= flatPolar_(Phi_(lat2, name='lat2'), Phi_(lat1, name='lat1'),
                        radians(d))
    return r
コード例 #12
0
ファイル: formy.py プロジェクト: dholle2/cs411-project
def haversine(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
    '''Compute the distance between two (spherical) points using the
       U{Haversine<https://www.Movable-Type.co.UK/scripts/latlong.html>}
       formula.

       @arg lat1: Start latitude (C{degrees}).
       @arg lon1: Start longitude (C{degrees}).
       @arg lat2: End latitude (C{degrees}).
       @arg lon2: End longitude (C{degrees}).
       @kwarg radius: Mean earth radius (C{meter}).
       @kwarg wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: Distance (C{meter}, same units as B{C{radius}}).

       @see: U{Distance between two (spherical) points
             <https://www.EdWilliams.org/avform.htm#Dist>}, functions
             L{cosineLaw}, L{equirectangular}, L{euclidean},
             L{flatLocal}, L{flatPolar}, L{vincentys} and methods
             L{Ellipsoid.distance2}, C{LatLon.distanceTo*} and
             C{LatLon.equirectangularTo}.

       @note: See note at function L{vincentys_}.
    '''
    r = Radius(radius)
    if r:
        d, _ = unroll180(lon1, lon2, wrap=wrap)
        r *= haversine_(Phi_(lat2, name='lat2'), Phi_(lat1, name='lat1'),
                        radians(d))
    return r
コード例 #13
0
ファイル: hausdorff.py プロジェクト: tranngocphu/PyGeodesy
 def distance(self, p1, p2):
     '''Return the non-negative I{angular} distance in C{degrees}.
     '''
     # see .ellipsoidalKarney.LatLon._inverse
     _, lon2 = unroll180(p1.lon, p2.lon, wrap=self._wrap)  # g.LONG_UNROLL
     # XXX g.DISTANCE needed for 's12', distance in meters?
     return abs(self._Inverse(p1.lat, p1.lon, p2.lat, lon2)['a12'])
コード例 #14
0
ファイル: formy.py プロジェクト: baris-ekici/PyGeodesy
def cosineForsytheAndoyerLambert(lat1,
                                 lon1,
                                 lat2,
                                 lon2,
                                 datum=Datums.WGS84,
                                 wrap=False):
    '''Compute the 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 lat1: Start latitude (C{degrees}).
       @arg lon1: Start longitude (C{degrees}).
       @arg lat2: End latitude (C{degrees}).
       @arg lon2: End longitude (C{degrees}).
       @kwarg datum: Ellipsoidal datum to use (L{Datum}).
       @kwarg wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: Distance (C{meter}, same units as the B{C{datum}}'s
                ellipsoid axes).

       @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 method
             L{Ellipsoid.distance2}.
    '''
    d, _ = unroll180(lon1, lon2, wrap=wrap)
    r = cosineForsytheAndoyerLambert_(Phi_(lat2, name=_lat2_),
                                      Phi_(lat1, name=_lat1_),
                                      radians(d),
                                      datum=datum)
    return r * datum.ellipsoid.a
コード例 #15
0
ファイル: formy.py プロジェクト: baris-ekici/PyGeodesy
def equirectangular_(lat1,
                     lon1,
                     lat2,
                     lon2,
                     adjust=True,
                     limit=45,
                     wrap=False):
    '''Compute the distance between two points using
       the U{Equirectangular Approximation / Projection
       <https://www.Movable-Type.co.UK/scripts/latlong.html#equirectangular>}.

       This approximation is valid for short distance of several
       hundred Km or Miles, see the B{C{limit}} keyword argument and
       the L{LimitError}.

       @arg lat1: Start latitude (C{degrees}).
       @arg lon1: Start longitude (C{degrees}).
       @arg lat2: End latitude (C{degrees}).
       @arg lon2: End longitude (C{degrees}).
       @kwarg adjust: Adjust the wrapped, unrolled longitudinal delta
                      by the cosine of the mean latitude (C{bool}).
       @kwarg limit: Optional limit for lat- and longitudinal deltas
                     (C{degrees}) or C{None} or C{0} for unlimited.
       @kwarg wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: A L{Distance4Tuple}C{(distance2, delta_lat, delta_lon,
                unroll_lon2)}.

       @raise LimitError: If the lat- and/or longitudinal delta exceeds
                          the B{C{-limit..+limit}} range and L{limiterrors}
                          set to C{True}.

       @see: U{Local, flat earth approximation
             <https://www.EdWilliams.org/avform.htm#flat>}, functions
             L{equirectangular}, L{cosineAndoyerLambert},
             L{cosineForsytheAndoyerLambert}, L{cosineLaw}, L{euclidean},
             L{flatLocal}/L{hubeny}, L{flatPolar}, L{haversine}, L{thomas}
             and L{vincentys} and methods L{Ellipsoid.distance2},
             C{LatLon.distanceTo*} and C{LatLon.equirectangularTo}.
    '''
    d_lat = lat2 - lat1
    d_lon, ulon2 = unroll180(lon1, lon2, wrap=wrap)

    if limit and _limiterrors \
             and max(abs(d_lat), abs(d_lon)) > limit > 0:
        t = unstr(equirectangular_.__name__,
                  lat1,
                  lon1,
                  lat2,
                  lon2,
                  limit=limit)
        raise LimitError('delta exceeds limit', txt=t)

    if adjust:  # scale delta lon
        d_lon *= _scale_deg(lat1, lat2)

    d2 = hypot2(d_lat, d_lon)  # degrees squared!
    return Distance4Tuple(d2, d_lat, d_lon, ulon2 - lon2)
コード例 #16
0
 def Inverse1(self, lat1, lon1, lat2, lon2, wrap=False):
     '''Return the non-negative I{angular} distance in C{degrees}.
     '''
     # see .FrechetKarney.distance, .HausdorffKarney._distance
     # and .HeightIDWkarney._distances
     _, lon2 = unroll180(lon1, lon2,
                         wrap=wrap)  # self.LONG_UNROLL
     d = self.Inverse(lat1, lon1, lat2, lon2)
     # XXX self.DISTANCE needed for 'a12'?
     return abs(d.a12)
コード例 #17
0
ファイル: formy.py プロジェクト: qi704169722/PyGeodesy
def equirectangular_(lat1,
                     lon1,
                     lat2,
                     lon2,
                     adjust=True,
                     limit=45,
                     wrap=False):
    '''Compute the distance between two points using
       the U{Equirectangular Approximation / Projection
       <https://www.Movable-Type.co.UK/scripts/latlong.html>}.

       This approximation is valid for short distance of several
       hundred Km or Miles, see the B{C{limit}} keyword argument and
       the L{LimitError}.

       @param lat1: Start latitude (C{degrees}).
       @param lon1: Start longitude (C{degrees}).
       @param lat2: End latitude (C{degrees}).
       @param lon2: End longitude (C{degrees}).
       @keyword adjust: Adjust the wrapped, unrolled longitudinal
                        delta by the cosine of the mean latitude (C{bool}).
       @keyword limit: Optional limit for lat- and longitudinal deltas
                       (C{degrees}) or C{None} or C{0} for unlimited.
       @keyword wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: A L{Distance4Tuple}C{(distance2, delta_lat, delta_lon,
                unroll_lon2)}.

       @raise LimitError: If the lat- and/or longitudinal delta exceeds
                          the B{C{-limit..+limit}} range and L{limiterrors}
                          set to C{True}.

       @see: U{Local, flat earth approximation
             <https://www.EdWilliams.org/avform.htm#flat>}, functions
             L{equirectangular}, L{euclidean}, L{haversine} and
             L{vincentys} and methods L{Ellipsoid.distance2},
             C{LatLon.distanceTo*} and C{LatLon.equirectangularTo}.
    '''
    d_lat = lat2 - lat1
    d_lon, ulon2 = unroll180(lon1, lon2, wrap=wrap)

    if limit and _limiterrors \
             and max(abs(d_lat), abs(d_lon)) > limit > 0:
        t = fStr((lat1, lon1, lat2, lon2), prec=4)
        raise LimitError('%s(%s, limit=%s) delta exceeds limit' %
                         ('equirectangular_', t, fStr(limit, prec=2)))

    if adjust:  # scale delta lon
        d_lon *= _scaled(lat1, lat2)

    d2 = d_lat**2 + d_lon**2  # degrees squared!
    return Distance4Tuple(d2, d_lat, d_lon, ulon2 - lon2)
コード例 #18
0
    def _inverse(self, other, wrap):
        '''(INTERNAL) Karney's C{Inverse} method.

           @return: A L{Distance3Tuple}C{(distance, initial, final)}.

           @raise TypeError: The B{C{other}} point is not L{LatLon}.

           @raise ValueError: If this and the B{C{other}} point's
                              L{Datum} ellipsoids are not compatible.
        '''
        g = self.ellipsoids(other).geodesic
        _, lon = unroll180(self.lon, other.lon, wrap=wrap)
        return g.Inverse3(self.lat, self.lon, other.lat, lon)
コード例 #19
0
ファイル: ellipsoidalKarney.py プロジェクト: mhuyha/PyGeodesy
    def _inverse(self, other, azis, wrap):
        '''(INTERNAL) Inverse Karney method.

           @raise TypeError: The B{C{other}} point is not L{LatLon}.

           @raise ValueError: If this and the B{C{other}} point's L{Datum}
                              ellipsoids are not compatible.
        '''
        g = self.ellipsoids(other).geodesic
        m = g.DISTANCE
        if azis:
            m |= g.AZIMUTH
        _, lon = unroll180(self.lon, other.lon, wrap=wrap)
        r = g.Inverse(self.lat, self.lon, other.lat, lon, m)
        t = r['s12']
        if azis:  # forward and reverse azimuth
            t = t, wrap360(r['azi1']), wrap360(r['azi2'])
        return t
コード例 #20
0
def euclidean(lat1, lon1, lat2, lon2, radius=R_M, adjust=True, wrap=False):
    '''Approximate the C{Euclidian} distance between two (spherical) points.

       @param lat1: Start latitude (C{degrees}).
       @param lon1: Start longitude (C{degrees}).
       @param lat2: End latitude (C{degrees}).
       @param lon2: End longitude (C{degrees}).
       @keyword radius: Optional, mean earth radius (C{meter}).
       @keyword adjust: Adjust the longitudinal delta by the
                        cosine of the mean latitude (C{bool}).
       @keyword wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: Distance (C{meter}, same units as B{C{radius}}).

       @see: U{Distance between two (spherical) points
             <https://www.EdWilliams.org/avform.htm#Dist>}, functions
             L{equirectangular}, L{haversine} and L{vincentys} and
             methods L{Ellipsoid.distance2}, C{LatLon.distanceTo*}
             and C{LatLon.equirectangularTo}.
    '''
    d, _ = unroll180(lon1, lon2, wrap=wrap)
    r = euclidean_(radians(lat2), radians(lat1), radians(d), adjust=adjust)
    return r * float(radius)
コード例 #21
0
def vincentys(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
    '''Compute the distance between two (spherical) points using
       U{Vincenty's<https://WikiPedia.org/wiki/Great-circle_distance>}
       spherical formula.

       @param lat1: Start latitude (C{degrees}).
       @param lon1: Start longitude (C{degrees}).
       @param lat2: End latitude (C{degrees}).
       @param lon2: End longitude (C{degrees}).
       @keyword radius: Optional, mean earth radius (C{meter}).
       @keyword wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: Distance (C{meter}, same units as B{C{radius}}).

       @see: Functions L{equirectangular}, L{euclidean} and L{haversine}
             and methods L{Ellipsoid.distance2}, C{LatLon.distanceTo*}
             and C{LatLon.equirectangularTo}.

       @note: See note under L{vincentys_}.
    '''
    d, _ = unroll180(lon1, lon2, wrap=wrap)
    r = vincentys_(radians(lat2), radians(lat1), radians(d))
    return r * float(radius)
コード例 #22
0
def _unrollon(p1, p2):  # unroll180 == .karney._unroll2
    # wrap, unroll and replace longitude if different
    _, lon = unroll180(p1.lon, p2.lon, wrap=True)
    if abs(lon - p2.lon) > EPS:
        p2 = p2.classof(p2.lat, lon, p2.height, datum=p2.datum)
    return p2
コード例 #23
0
def _intersects2(
        c1,
        r1,
        c2,
        r2,
        height=None,
        wrap=True,  # MCCABE 16
        equidistant=None,
        tol=_TOL_M,
        LatLon=None,
        **LatLon_kwds):
    # (INTERNAL) Intersect two spherical circles, see L{_intersections2}
    # above, separated to allow callers to embellish any exceptions

    from pygeodesy.formy import _euclidean, _radical2
    from pygeodesy.sphericalTrigonometry import _intersects2 as _si2, LatLon as _LLS
    from pygeodesy.utily import m2degrees, unroll180
    from pygeodesy.vector3d import _intersects2 as _vi2

    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)

    if r1 < r2:
        c1, c2 = c2, c1
        r1, r2 = r2, r1

    E = c1.ellipsoids(c2)
    if r1 > (E.b * PI):
        raise ValueError(_exceed_PI_radians_)

    if wrap:  # unroll180 == .karney._unroll2
        _, lon2 = unroll180(c1.lon, c2.lon, wrap=True)
        if lon2 != c2.lon:
            c2 = c2.classof(c2.lat, lon2, c2.height, datum=c2.datum)

    # distance between centers and radii are
    # measured along the ellipsoid's surface
    m = c1.distanceTo(c2, wrap=False)  # meter
    if m < max(r1 - r2, EPS):
        raise ValueError(_near_concentric_)
    if fsum_(r1, r2, -m) < 0:
        raise ValueError(_too_distant_fmt_ % (m, ))

    f = _radical2(m, r1, r2).ratio  # "radical lat"
    r = E.rocMean(favg(c1.lat, c2.lat, f=f))
    e = max(m2degrees(tol, radius=r), EPS)

    # get the azimuthal equidistant projection
    if equidistant is None:
        from pygeodesy.azimuthal import equidistant as A
    else:
        A = equidistant  # preferably EquidistantKarney
    A = A(0, 0, datum=c1.datum)

    # gu-/estimate initial intersections, spherically ...
    t1, t2 = _si2(_LLS(c1.lat, c1.lon, height=c1.height),
                  r1,
                  _LLS(c2.lat, c2.lon, height=c2.height),
                  r2,
                  radius=r,
                  height=height,
                  wrap=False,
                  too_d=m)
    h, n = t1.height, t1.name

    # ... and then iterate like Karney suggests to find
    # tri-points of median lines, @see: references above
    ts, ta = [], None
    for t in ((t1, ) if t1 is t2 else (t1, t2)):
        p = None  # force d == p False
        for i in range(_TRIPS):
            A.reset(t.lat, t.lon)  # gu-/estimate as origin
            # convert centers to projection space
            t1 = A.forward(c1.lat, c1.lon)
            t2 = A.forward(c2.lat, c2.lon)
            # compute intersections in projection space
            v1, v2 = _vi2(
                t1,
                r1,  # XXX * t1.scale?,
                t2,
                r2,  # XXX * t2.scale?,
                sphere=False,
                too_d=m)
            # convert intersections back to geodetic
            t1 = A.reverse(v1.x, v1.y)
            t2 = A.reverse(v2.x, v2.y)
            # consider only the closer intersection
            d1 = _euclidean(t1.lat - t.lat, t1.lon - t.lon)
            d2 = _euclidean(t2.lat - t.lat, t2.lon - t.lon)
            # break if below tolerance or if unchanged
            t, d = (t1, d1) if d1 < d2 else (t2, d2)
            if d < e or d == p:
                t._iteration = i + 1  # _NamedTuple._iteration
                ts.append(t)
                if v1 is v2:  # abutting
                    ta = t
                break
            p = d
        else:
            raise ValueError(_no_convergence_fmt_ % (tol, ))

    if ta:  # abutting circles
        r = _latlon4(ta, h, n)
    elif len(ts) == 2:
        return _latlon4(ts[0], h, n), _latlon4(ts[1], h, n)
    elif len(ts) == 1:  # XXX assume abutting
        r = _latlon4(ts[0], h, n)
    else:
        raise _AssertionError(ts=ts)
    return r, r
コード例 #24
0
    def _inverse(self, other, azis, wrap):
        '''(INTERNAL) Inverse Vincenty method.

           @raise TypeError: The B{C{other}} point is not L{LatLon}.

           @raise ValueError: If this and the B{C{other}} point's L{Datum}
                              ellipsoids are not compatible.

           @raise VincentyError: Vincenty fails to converge for the current
                                 L{LatLon.epsilon} and L{LatLon.iterations}
                                 limit and/or if this and the B{C{other}}
                                 point are coincident or near-antipodal.
        '''
        E = self.ellipsoids(other)

        c1, s1, _ = _r3(self.lat, E.f)
        c2, s2, _ = _r3(other.lat, E.f)

        c1c2, s1c2 = c1 * c2, s1 * c2
        c1s2, s1s2 = c1 * s2, s1 * s2

        dl, _ = unroll180(self.lon, other.lon, wrap=wrap)
        ll = dl = radians(dl)
        for self._iteration in range(1, self._iterations + 1):
            ll_ = ll
            sll, cll = sincos2(ll)

            ss = hypot(c2 * sll, c1s2 - s1c2 * cll)
            if ss < EPS:  # coincident or antipodal, ...
                if self.isantipodeTo(other, eps=self._epsilon):
                    t = '%r %sto %r' % (self, _antipodal_, other)
                    raise VincentyError(_ambiguous_, txt=t)
                # return zeros like Karney, but unlike Veness
                return Distance3Tuple(0.0, 0, 0)

            cs = s1s2 + c1c2 * cll
            s = atan2(ss, cs)

            sa = c1c2 * sll / ss
            c2a = 1 - sa**2
            if abs(c2a) < EPS:
                c2a = 0  # equatorial line
                ll = dl + E.f * sa * s
            else:
                c2sm = cs - 2 * s1s2 / c2a
                ll = dl + _dl(E.f, c2a, sa, s, cs, ss, c2sm)

            if abs(ll - ll_) < self._epsilon:
                break


#           # omitted and applied only after failure to converge below, see footnote
#           # under Inverse at <https://WikiPedia.org/wiki/Vincenty's_formulae>
#           # <https://GitHub.com/ChrisVeness/geodesy/blob/master/latlon-vincenty.js>
#           elif abs(ll) > PI and self.isantipodeTo(other, eps=self._epsilon):
#              raise VincentyError('%s, %r %sto %r' % ('ambiguous', self,
#                                  _antipodal_, other))
        else:
            t = _antipodal_ if self.isantipodeTo(other,
                                                 eps=self._epsilon) else NN
            t = _SPACE_(repr(self), NN(t, _to_), repr(other))
            raise VincentyError(_no_(_convergence_), txt=t)

        if c2a:  # e22 == (a / b)**2 - 1
            A, B = _p2(c2a * E.e22)
            s = A * (s - _ds(B, cs, ss, c2sm))

        b = E.b
        #       if self.height or other.height:
        #           b += self._havg(other)
        d = b * s

        if azis:  # forward and reverse azimuth
            sll, cll = sincos2(ll)
            f = atan2b(c2 * sll, c1s2 - s1c2 * cll)
            r = atan2b(c1 * sll, -s1c2 + c1s2 * cll)
        else:
            f = r = 0
        return Distance3Tuple(d, f, r)
コード例 #25
0
def intersections2(lat1, lon1, radius1,
                   lat2, lon2, radius2, datum=None, wrap=True):
    '''Conveniently compute the intersections of two circles each defined
       by (geodetic/-centric) center point and a radius, using either ...

       1) L{vector3d.intersections2} for small distances or if no B{C{datum}}
       is specified, or ...

       2) L{sphericalTrigonometry.intersections2} for a spherical B{C{datum}}
       or if B{C{datum}} is a C{scalar} representing the earth radius, or ...

       3) L{ellipsoidalKarney.intersections2} for an ellipsoidal B{C{datum}}
       and if I{Karney}'s U{geographiclib<https://PyPI.org/project/geographiclib/>}
       is installed, or ...

       4) L{ellipsoidalVincenty.intersections2} if B{C{datum}} is ellipsoidal
       otherwise.

       @arg lat1: Latitude of the first circle center (C{degrees}).
       @arg lon1: Longitude of the first circle center (C{degrees}).
       @arg radius1: Radius of the first circle (C{meter}, conventionally).
       @arg lat2: Latitude of the second circle center (C{degrees}).
       @arg lon2: Longitude of the second circle center (C{degrees}).
       @arg radius2: Radius of the second circle (C{meter}, same units as B{C{radius1}}).
       @kwarg datum: Optional ellipsoidal or spherical datum (L{Datum},
                     L{Ellipsoid}, L{Ellipsoid2}, L{a_f2Tuple} or
                     C{scalar} earth radius in C{meter}, same units as
                     B{C{radius1}} and B{C{radius2}}) or C{None}.
       @kwarg wrap: Wrap and unroll longitudes (C{bool}).

       @return: 2-Tuple of the intersection points, each a
                L{LatLon2Tuple}C{(lat, lon)}.  For abutting circles,
                the intersection points are the same instance.

       @raise IntersectionError: Concentric, antipodal, invalid or
                                 non-intersecting circles or no
                                 convergence.

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

       @raise UnitError: Invalid B{C{lat1}}, B{C{lon1}}, B{C{radius1}}
                         B{C{lat2}}, B{C{lon2}} or B{C{radius2}}.
    '''
    if datum is None or euclidean(lat1, lon1, lat1, lon2, radius=R_M,
                                  adjust=True, wrap=wrap) < _D_I2_:
        import pygeodesy.vector3d as m

        def _V2T(x, y, _, **unused):  # _ == z unused
            return _xnamed(LatLon2Tuple(y, x), intersections2.__name__)

        r1 = m2degrees(Radius_(radius1=radius1), radius=R_M, lat=lat1)
        r2 = m2degrees(Radius_(radius2=radius2), radius=R_M, lat=lat2)

        _, lon2 = unroll180(lon1, lon2, wrap=wrap)
        t = m.intersections2(m.Vector3d(lon1, lat1, 0), r1,
                             m.Vector3d(lon2, lat2, 0), r2, sphere=False,
                               Vector=_V2T)

    else:
        def _LL2T(lat, lon, **unused):
            return _xnamed(LatLon2Tuple(lat, lon), intersections2.__name__)

        d = _spherical_datum(datum, name=intersections2.__name__)
        if d.isSpherical:
            import pygeodesy.sphericalTrigonometry as m
        elif d.isEllipsoidal:
            try:
                if d.ellipsoid.geodesic:
                    pass
                import pygeodesy.ellipsoidalKarney as m
            except ImportError:
                import pygeodesy.ellipsoidalVincenty as m
        else:
            raise _AssertionError(datum=d)

        t = m.intersections2(m.LatLon(lat1, lon1, datum=d), radius1,
                             m.LatLon(lat2, lon2, datum=d), radius2, wrap=wrap,
                               LatLon=_LL2T, height=0)
    return t