Exemple #1
0
def rhumb_bearing(start, end, final=False):
    """
    Takes two points and finds the bearing angle between them along a Rhumb line,
    i.e. the angle measured in degrees start the north line (0 degrees).

    :param start: Start Point or Point Feature.
    :param end: End Point or Point Feature.
    :param final: Calculates the final bearing if true
    :return: bearing from north in decimal degrees, between -180 and 180 degrees
        (positive clockwise)

    Example:

    >>> from turfpy.measurement import rhumb_bearing
    >>> from geojson import Feature, Point
    >>> start = Feature(geometry=Point((-75.343, 39.984)))
    >>> end = Feature(geometry=Point((-75.534, 39.123)))
    >>> rhumb_bearing(start, end, True)
    """
    if final:
        bear_360 = calculate_rhumb_bearing(get_coord(end), get_coord(start))
    else:
        bear_360 = calculate_rhumb_bearing(get_coord(start), get_coord(end))

    if bear_360 > 180:
        bear_180 = -1 * (360 - bear_360)
    else:
        bear_180 = bear_360

    return bear_180
Exemple #2
0
def distance(point1: Feature, point2: Feature, units: str = "km"):
    """
    Calculates distance between two Points. A point is containing latitude and
    logitude in decimal degrees and ``unit`` is optional.

    It calculates distance in units such as kilometers, meters, miles, feet and inches.

    :param point1: first point; tuple of (latitude, longitude) in decimal degrees.
    :param point2: second point; tuple of (latitude, longitude) in decimal degrees.
    :param units: A string containing unit, E.g. kilometers = 'km', miles = 'mi',
        meters = 'm', feet = 'ft', inches = 'in'.
    :return: The distance between the two points in the requested unit, as a float.

    Example:

    >>> from turfpy import measurement
    >>> from geojson import Point, Feature
    >>> start = Feature(geometry=Point((-75.343, 39.984)))
    >>> end = Feature(geometry=Point((-75.534, 39.123)))
    >>> measurement.distance(start,end)
    """
    coordinates1 = get_coord(point1)
    coordinates2 = get_coord(point2)

    dlat = radians((coordinates2[1] - coordinates1[1]))

    dlon = radians((coordinates2[0] - coordinates1[0]))

    lat1 = radians(coordinates1[1])

    lat2 = radians(coordinates2[1])

    a = pow(sin(dlat / 2), 2) + pow(sin(dlon / 2), 2) * cos(lat1) * cos(lat2)
    b = 2 * atan2(sqrt(a), sqrt(1 - a))
    return radians_to_length(b, units)
Exemple #3
0
def rhumb_distance(start, to, units="km"):
    """
    Calculates the distance along a rhumb line between two points in degrees, radians,
    miles, or kilometers.

    :param start: Start Point or Point Feature from which distance to be calculated.
    :param to: End Point or Point Feature upto which distance to be calculated.
    :param units: Units in which distance to be calculated, values can be 'deg', 'rad',
        'mi', 'km'
    :return: Distance calculated from provided start to end Point.

    Example:

    >>> from turfpy.measurement import rhumb_distance
    >>> from geojson import Point, Feature
    >>> start = Feature(geometry=Point((-75.343, 39.984)))
    >>> end = Feature(geometry=Point((-75.534, 39.123)))
    >>> rhumb_distance(start, end,'mi')
    """
    origin = get_coord(start)
    dest = get_coord(to)

    if dest[0] - origin[0] > 180:
        temp = -360
    elif origin[0] - dest[0] > 180:
        temp = 360
    else:
        temp = 0
    dest[0] += temp

    distance_in_meters = _calculate_rhumb_distance(origin, dest)
    ru_distance = convert_length(distance_in_meters, "m", units)
    return ru_distance
Exemple #4
0
    def callback_flatten_each(feature, feature_index, multi_feature_index):
        nonlocal length
        nonlocal closest_pt

        coords = get_coords(feature)
        for i, coord in enumerate(coords[:-1]):
            # start
            start = Feature(geometry=Point(coord))
            start.properties = {"dist": dist(point, start, options)}
            # stop
            stop = Feature(geometry=Point(coords[i + 1]))
            stop.properties = {"dist": dist(point, stop, options)}
            # section length
            section_length = dist(start, stop, options)
            # perpendicular
            height_distance = max(start.properties["dist"],
                                  stop.properties["dist"])
            direction = bearing(start, stop)

            perpendicular_pt1 = destination(Feature(geometry=point),
                                            height_distance, direction + 90,
                                            options)
            perpendicular_pt2 = destination(Feature(geometry=point),
                                            height_distance, direction - 90,
                                            options)
            intersect = line_intersect(
                Feature(geometry=LineString([
                    get_coord(perpendicular_pt1),
                    get_coord(perpendicular_pt2)
                ])),
                Feature(geometry=LineString(
                    [get_coord(start), get_coord(stop)])),
            )
            intersect_pt = None
            if len(intersect["features"]) > 0:
                intersect_pt = intersect["features"][0]
                intersect_pt.properties["dist"] = dist(point, intersect_pt,
                                                       options)
                intersect_pt.properties["location"] = length + dist(
                    start, intersect_pt, options)

            if start.properties["dist"] < closest_pt.properties["dist"]:
                closest_pt = start
                closest_pt.properties["index"] = i
                closest_pt.properties["location"] = length

            if stop.properties["dist"] < closest_pt.properties["dist"]:
                closest_pt = stop
                closest_pt.properties["index"] = i + 1
                closest_pt.properties["location"] = length + section_length

            if (intersect_pt and intersect_pt.properties["dist"] <
                    closest_pt.properties["dist"]):
                closest_pt = intersect_pt
                closest_pt.properties["index"] = i

            # update length
            length += section_length
        # process all Features
        return True
Exemple #5
0
def test_get_coord():
    """Test get_coord function."""

    point = Point((73, 19))
    feature = Feature(geometry=point)
    flist = [73, 19]
    c1 = get_coord(point)
    c2 = get_coord(feature)
    c3 = get_coord(flist)
    assert c1 == [73, 19]
    assert c1 == c2 == c3

    # Test for derived class from Feature
    class Vertex(Feature):
        """Derived from Feature"""
        def __init__(self, node: str, point: Point):
            Feature.__init__(self, geometry=point)
            self.nodeid = node

    p1 = Point((25.25458, 51.623879))
    f1 = Feature(geometry=p1)
    v1 = Vertex("v1", point=p1)
    p2 = Point((25.254626, 51.624053))
    f2 = Feature(geometry=p2)
    v2 = Vertex("v2", point=p2)

    df = distance(f1, f2)
    dv = distance(v1, v2)
    assert df == dv
Exemple #6
0
def define_origin(geojson, origin):
    if not origin:
        origin = "centroid"

    if isinstance(origin, list):
        return get_coord(origin)

    bb = bbox(geojson)
    west = bb[0]
    south = bb[1]
    east = bb[2]
    north = bb[3]

    if (origin == "sw" or origin == "southwest" or origin == "westsouth"
            or origin == "bottomleft"):
        return [west, south]
    elif (origin == "se" or origin == "southeast" or origin == "eastsouth"
          or origin == "bottomright"):
        return [east, south]
    elif (origin == "nw" or origin == "northwest" or origin == "westnorth"
          or origin == "topleft"):
        return [west, north]
    elif (origin == "ne" or origin == "northeast" or origin == "eastnorth"
          or origin == "topright"):
        return [east, north]
    elif origin == "center":
        return center(geojson)["geometry"]["coordinates"]
    elif origin is None or origin == "centroid":
        return centroid(geojson)["geometry"]["coordinates"]
    else:
        raise Exception("invalid origin")
Exemple #7
0
def rhumb_destination(origin, distance, bearing, options) -> Feature:
    """
    Returns the destination Point having travelled the given distance along a Rhumb line
    from the origin Point with the (varant) given bearing.

    :param origin: Starting Point
    :param distance: Distance from the starting point
    :param bearing: Varant bearing angle ranging from -180 to 180 degrees from north
    :param options: A dict of two values 'units' for the units of distance provided and
        'properties' that are to be passed to the Destination Feature Point
        Example :- {'units':'mi', 'properties': {"marker-color": "F00"}}
    :return: Destination Feature Point

    Example:

    >>> from turfpy.measurement import rhumb_destination
    >>> from geojson import Point, Feature
    >>> start = Feature(geometry=Point((-75.343, 39.984)),
    properties={"marker-color": "F00"})
    >>> distance = 50
    >>> bearing = 90
    >>> rhumb_destination(start, distance, bearing, {'units':'mi',
    'properties': {"marker-color": "F00"}})
    """
    was_negative_distance = distance < 0
    distance_in_meters = convert_length(abs(distance), options.get("units", ""), "m")
    if was_negative_distance:
        distance_in_meters = -1 * (abs(distance_in_meters))
    coords = get_coord(origin)
    destination_point = _calculate_rhumb_destination(coords, distance_in_meters, bearing)
    return Feature(
        geometry=Point(destination_point), properties=options.get("properties", ""),
    )
Exemple #8
0
 def _callback_coord_each(
     coord, coord_index, feature_index, multi_feature_index, geometry_index
 ):
     nonlocal pivot, angle
     initial_angle = rhumb_bearing(GeoPoint(pivot), GeoPoint(coord))
     final_angle = initial_angle + angle
     distance = rhumb_distance(GeoPoint(pivot), GeoPoint(coord))
     new_coords = get_coord(rhumb_destination(GeoPoint(pivot), distance, final_angle))
     coord[0] = new_coords[0]
     coord[1] = new_coords[1]
Exemple #9
0
 def _callback_coord_each(coord, coord_index, feature_index,
                          multi_feature_index, geometry_index):
     nonlocal distance, direction, units, z_translation
     new_coords = get_coord(
         rhumb_destination(GeoPoint(coord), distance, direction,
                           {"units": units}))
     coord[0] = new_coords[0]
     coord[1] = new_coords[1]
     if z_translation and len(coord) == 3:
         coord[2] += z_translation
Exemple #10
0
 def _callback_coord_each(
     coord, coord_index, feature_index, multi_feature_index, geometry_index
 ):
     nonlocal factor, origin
     original_distance = rhumb_distance(GeoPoint(origin), GeoPoint(coord))
     bearing = rhumb_bearing(GeoPoint(origin), GeoPoint(coord))
     new_distance = original_distance * factor
     new_coord = get_coord(rhumb_destination(GeoPoint(origin), new_distance, bearing))
     coord[0] = new_coord[0]
     coord[1] = new_coord[1]
     if len(coord) == 3:
         coord[2] = coord[2] * factor
Exemple #11
0
def boolean_point_in_polygon(point, polygon, ignore_boundary=False):
    """
    Takes a Point or a Point Feature and Polygon or Polygon Feature as input and returns
    True if Point is in given Feature.

    :param point: Point or Point Feature.
    :param polygon: Polygon or Polygon Feature.
    :param ignore_boundary: [Optional] default value is False, specify whether to exclude
        boundary of the given polygon or not.
    :return: True if the given Point is in Polygons else False

    Example:

    >>> from turfpy.measurement import boolean_point_in_polygon
    >>> from geojson import Point, MultiPolygon, Feature
    >>> point = Feature(geometry=Point((-77, 44)))
    >>> polygon = Feature(geometry=MultiPolygon([([(-81, 41), (-81, 47), (-72, 47),
    (-72, 41), (-81, 41)],),
    >>> ([(3.78, 9.28), (-130.91, 1.52), (35.12, 72.234), (3.78, 9.28)],)]))
    >>> boolean_point_in_polygon(point, polygon)
    """
    if not point:
        raise Exception("point is required")
    if not polygon:
        raise Exception("polygon is required")

    pt = get_coord(point)
    geom = get_geom(polygon)
    geo_type = geom["type"]
    bbox = polygon.get("bbox", None)
    polys = geom["coordinates"]

    if bbox and not in_bbox(pt, bbox):
        return False

    if geo_type == "Polygon":
        polys = [polys]

    inside_poly = False

    for i in range(0, len(polys)):
        if in_ring(pt, polys[i][0], ignore_boundary):
            in_hole = False
            k = 1
            while k < len(polys[i]) and not in_hole:
                if in_ring(pt, polys[i][k], not ignore_boundary):
                    in_hole = True
                k += 1
            if not in_hole:
                inside_poly = True

    return inside_poly
Exemple #12
0
def destination(origin: Union[Feature, Point],
                distance,
                bearing,
                options: dict = {}) -> Feature:
    """
    Takes a Point and calculates the location of a destination point given a distance in
    degrees, radians, miles, or kilometers and bearing in degrees.

    :param origin: Start point.
    :param distance: distance upto which the destination is from origin.
    :param bearing: Direction in which is the destination is from origin.
    :param options: Option like units of distance and properties to be passed to
        destination point feature, value
        for units are 'mi', 'km', 'deg' and 'rad'.
    :return: Feature: destination point in at the given distance and given direction.

    Example:

    >>> from turfpy.measurement import destination
    >>> from geojson import Point, Feature
    >>> origin = Feature(geometry=Point([-75.343, 39.984]))
    >>> distance = 50
    >>> bearing = 90
    >>> options = {'units': 'mi'}
    >>> destination(origin,distance,bearing,options)
    """
    coordinates1 = get_coord(origin)
    longitude1 = radians(float(coordinates1[0]))
    latitude1 = radians(float(coordinates1[1]))
    bearingRad = radians(float(bearing))
    if "units" in options:
        radian = length_to_radians(distance, options["units"])
    else:
        radian = length_to_radians(distance)

    latitude2 = asin((sin(latitude1) * cos(radian)) +
                     (cos(latitude1) * sin(radian) * cos(bearingRad)))
    longitude2 = longitude1 + atan2(
        sin(bearingRad) * sin(radian) * cos(latitude1),
        cos(radian) - sin(latitude1) * sin(latitude2),
    )

    lng = degrees(longitude2)
    lat = degrees(latitude2)

    point = Point((lng, lat))

    return Feature(
        geometry=point,
        properties=options["properties"] if "properties" in options else {},
    )
Exemple #13
0
def line_slice(
    start_pt: Point,
    stop_pt: Point,
    line: LineString,
) -> LineString:
    """
    Takes a LineString, a start Point, and a stop Point
    and returns a subsection of the line in-between those points.
    The start & stop points don't need to fall exactly on the line.

    This can be useful for extracting only the part of a route between waypoints.

    :param start_pt: starting point
    :param stop_pt: stopping point
    :param line: line to slice
    :return: sliced line as LineString Feature
    """

    if not line or get_type(line) != "LineString":
        raise Exception("line must be a LineString")

    coords = get_coords(line)
    start_vertex = nearest_point_on_line(line, start_pt)
    stop_vertex = nearest_point_on_line(line, stop_pt)

    if start_vertex["properties"]["index"] <= stop_vertex["properties"][
            "index"]:
        ends = [start_vertex, stop_vertex]
    else:
        ends = [stop_vertex, start_vertex]

    clip_coords = [get_coord(ends[0])]
    clip_coords.extend(coords[ends[0]["properties"]["index"] +
                              1:ends[1]["properties"]["index"] + 1])
    clip_coords.append(get_coord(ends[1]))

    return Feature(geometry=LineString(clip_coords),
                   properties=line["properties"].copy())