示例#1
0
def distance(start, end, options=None):
    """
    Calculates the distance between two Points in degrees, radians, miles, or kilometers.
    This uses the [Haversine formula](http://en.wikipedia.org/wiki/Haversine_formula) to account for global curvature.

    :param start: starting point [lng, lat] or Point feature
    :param end: ending point [lng, lat] or Point feature
    :param options: dictionary with units as an attribute. Can be degrees, radians, miles, or kilometers
    :return: distance between the 2 points
    """

    kwargs = {}
    if isinstance(options, dict) and "units" in options:
        kwargs.update(options)

    coordinates1 = get_coords_from_features(start, ["Point"])
    coordinates2 = get_coords_from_features(end, ["Point"])

    d_lat = degrees_to_radians(coordinates2[1] - coordinates1[1])
    d_lon = degrees_to_radians(coordinates2[0] - coordinates1[0])

    lat1 = degrees_to_radians(coordinates1[1])
    lat2 = degrees_to_radians(coordinates2[1])

    distance_rad = calculate_radians_distance(d_lon, d_lat, lat1, lat2)

    return radians_to_length(distance_rad, **kwargs)
示例#2
0
    def __init__(self, lon: float, lat: float, decimals=6):

        self.lon = lon
        self.lat = lat
        self.x = degrees_to_radians(lon)
        self.y = degrees_to_radians(lat)
        self.decimals = decimals
示例#3
0
def bearing(start, end, options=None):
    """
    Takes two points and finds the geographic bearing between them,
    i.e. the angle measured in degrees from the north line (0 degrees)

    :param start: starting point [lng, lat] or Point feature
    :param end: ending point [lng, lat] or Point feature
    :param options: dictionary with options:
        [options["final"]] - calculates the final bearing if true
    :return: bearing in decimal degrees, between -180 and 180 (positive clockwise)
    """

    if not options:
        options = {}

    if isinstance(options, dict) and "final" in options:
        return calculate_final_bearing(start, end)

    start = get_coords_from_features(start, ["Point"])
    end = get_coords_from_features(end, ["Point"])

    lon1 = degrees_to_radians(start[0])
    lon2 = degrees_to_radians(end[0])
    lat1 = degrees_to_radians(start[1])
    lat2 = degrees_to_radians(end[1])

    a = np.sin(lon2 - lon1) * np.cos(lat2)

    b = np.cos(lat1) * np.sin(lat2) - np.sin(lat1) * np.cos(lat2) * np.cos(lon2 - lon1)

    return radians_to_degrees(np.arctan2(a, b))
示例#4
0
def calculate_rhumb_destination(origin: Sequence,
                                distance_in_meters: float,
                                bearing: float,
                                radius: float = None) -> List:
    """
    Calculates the destination point having travelled along a rhumb line
    from origin point the given distance on the  given bearing.
    Adapted from Geodesy:
    http://www.movable-type.co.uk/scripts/latlong.html#rhumblines

    param origin: point coordinates in [lng, lat] form
    param distance: - Distance travelled, in same units as earth radius (default: metres).
    param bearing: - Bearing in degrees from north.
    param radius: - (Mean) radius of earth

    returns destination: point.
    """
    if not radius:
        radius = earth_radius

    # angular distance in radians
    delta = distance_in_meters / radius
    # to radians, but without normalize to pi
    lambda_1 = origin[0] * pi / 180

    phi_1 = degrees_to_radians(origin[1])
    theta = degrees_to_radians(bearing)

    delta_phi = delta * cos(theta)
    phi_2 = phi_1 + delta_phi

    # check for some points going past the pole, normalise latitude if so
    if abs(phi_2) > (pi / 2) and (phi_2 > 0):
        phi_2 = pi - phi_2
    if abs(phi_2) > (pi / 2) and (phi_2 < 0):
        phi_2 = pi - phi_2

    delta_psi = log(tan(phi_2 / 2 + pi / 4) / tan(phi_1 / 2 + pi / 4))

    # E-W course becomes ill-conditioned with 0/0
    if abs(delta_psi) > 10e-12:
        q_1 = delta_phi / delta_psi
    else:
        q_1 = cos(phi_1)

    delta_lambda = delta * sin(theta) / q_1
    lambda_2 = lambda_1 + delta_lambda

    # normalise to −180..+180°
    destination = [
        fmod(((lambda_2 * 180 / pi) + 540), 360) - 180,
        (phi_2 * 180 / pi),
    ]

    return destination
示例#5
0
def calculate_rhumb_distance(origin: List,
                             destination: List,
                             radius: float = None) -> float:
    """
    Calculates the rhumb distance between two Points.

    # https://en.wikipedia.org/wiki/Rhumb_line

    :param origin: starting point [lng, lat]
    :param destination: ending point [lng, lat]
    :param radius: radius of the earth

    :return: distance between the 2 points in meters
    """
    if not radius:
        radius = earth_radius

    phi_1 = degrees_to_radians(origin[1])
    phi_2 = degrees_to_radians(destination[1])
    delta_phi = phi_2 - phi_1

    delta_lambda = degrees_to_radians(abs(destination[0] - origin[0]))

    # if dLon over 180° take shorter rhumb line across the anti-meridian:
    if delta_lambda > np.pi:
        delta_lambda -= 2 * np.pi

    # on Mercator projection, longitude distances shrink by latitude; q is the 'stretch factor'
    # q becomes ill-conditioned along E-W line (0/0); use empirical tolerance to avoid it

    delta_psi = np.log(
        np.tan(phi_2 / 2 + np.pi / 4) / np.tan(phi_1 / 2 + np.pi / 4))

    if abs(delta_psi) > 10e-12:
        q_1 = delta_phi / delta_psi
    else:
        q_1 = np.cos(phi_1)

    # distance is pythagoras on 'stretched' Mercator projection
    delta = np.sqrt(delta_phi * delta_phi +
                    q_1 * q_1 * delta_lambda * delta_lambda)
    # angular distance in radians
    distance = delta * radius

    return distance
示例#6
0
def destination(origin, distance, bearing, options=None):
    """
    Takes a Point and calculates the location of a destination point given a distance in
    degrees, radians, miles, or kilometers; and bearing in degrees.
    This uses the [Haversine formula](http://en.wikipedia.org/wiki/Haversine_formula) to account for global curvature.

    :param origin: starting point
    :param distance: distance from the origin point
    :param bearing: bearing ranging from -180 to 180
    :param options: optional parameters
        [options["units"]='kilometers'] miles, kilometers, degrees, or radians
        [options["properties"]={}] Translate properties to Point
    :return: destination GeoJSON Point feature
    """

    if not options:
        options = {}

    kwargs = {}
    if "units" in options:
        kwargs["units"] = options.get("units")

    coords = get_coords_from_features(origin, ["Point"])

    longitude1 = degrees_to_radians(coords[0])
    latitude1 = degrees_to_radians(coords[1])
    bearing_rads = degrees_to_radians(bearing)

    radians = length_to_radians(distance, **kwargs)

    latitude2 = asin(
        sin(latitude1) * cos(radians) +
        cos(latitude1) * sin(radians) * cos(bearing_rads))

    longitude2 = longitude1 + atan2(
        sin(bearing_rads) * sin(radians) * cos(latitude1),
        cos(radians) - sin(latitude1) * sin(latitude2),
    )

    lng = truncate(radians_to_degrees(longitude2), 6)
    lat = truncate(radians_to_degrees(latitude2), 6)

    return point([lng, lat], options.get("properties", None))
示例#7
0
def calculate_rhumb_bearing(origin: Sequence, destination: Sequence) -> float:
    """
    Calculates the bearing from origin to destination point along a rhumb line.
    http://www.edwilliams.org/avform.htm#Rhumb
    """
    phi_1 = degrees_to_radians(origin[1])
    phi_2 = degrees_to_radians(destination[1])
    delta_lambda = degrees_to_radians(destination[0] - origin[0])

    # if delta_lambda over 180° take shorter rhumb line across the anti-meridian:
    if abs(delta_lambda) > pi:
        if delta_lambda > 0:
            delta_lambda = -(2 * pi - delta_lambda)
        if delta_lambda < 0:
            delta_lambda = 2 * pi + delta_lambda

    delta_psi = log(tan(phi_2 / 2 + pi / 4) / tan(phi_1 / 2 + pi / 4))
    theta = atan2(delta_lambda, delta_psi)

    return fmod(radians_to_degrees(theta) + 360, 360)
示例#8
0
def test_degrees_to_radians(value, result):

    assert degrees_to_radians(value) == result