예제 #1
0
    def _get_intermediate_coord(self,
                                fraction: float) -> List[Union[float, float]]:
        """
        Calculates the intermediate point on a great circle line
        http://www.edwilliams.org/avform.htm#Intermediate

        :param fraction: input fraction of the whole great circle
        :return: a tuple of cordinates
        """
        A = math.sin((1 - fraction) * self.distance) / math.sin(self.distance)
        B = math.sin(fraction * self.distance) / math.sin(self.distance)

        x = A * math.cos(self.start.y) * math.cos(self.start.x) + B * math.cos(
            self.end.y) * math.cos(self.end.x)

        y = A * math.cos(self.start.y) * math.sin(self.start.x) + B * math.cos(
            self.end.y) * math.sin(self.end.x)

        z = A * math.sin(self.start.y) + B * math.sin(self.end.y)

        lat = radians_to_degrees(
            math.atan2(z, math.sqrt(math.pow(x, 2) + math.pow(y, 2))))
        lon = radians_to_degrees(math.atan2(y, x))

        return Coordinate(lon, lat).coords
예제 #2
0
파일: _bearing.py 프로젝트: liupion/pyturf
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))
예제 #3
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))
예제 #4
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)
예제 #5
0
def test_radians_to_degrees(value, result):

    assert round(radians_to_degrees(value), 6) == result