示例#1
0
def line_offset(geojson: Feature,
                distance: float,
                unit: str = "km") -> Feature:
    """
    Takes a linestring or multilinestring and returns
    a line at offset by the specified distance.

    :param geojson: input GeoJSON
    :param distance: distance to offset the line (can be of negative value)
    :param unit: Units in which distance to be calculated, values can be 'deg', 'rad',
        'mi', 'km', default is 'km'
    :return: Line feature offset from the input line

    Example:

    >>> from geojson import MultiLineString, Feature
    >>> from turfpy.transformation import line_offset
    >>> ls = Feature(geometry=MultiLineString([
    ... [(3.75, 9.25), (-130.95, 1.52)],
    ... [(23.15, -34.25), (-1.35, -4.65), (3.45, 77.95)]
    ... ]))
    >>> line_offset(ls, 2, unit='mi')
    """
    if not geojson:
        raise Exception("geojson is required")

    if not distance:
        raise Exception("distance is required")

    type = get_type(geojson)
    properties = geojson.get("properties", {})

    if type == "LineString":
        return line_offset_feature(geojson, distance, unit)
    elif type == "MultiLineString":
        coords = []

        def callback_flatten_each(feature, feature_index, multi_feature_index):
            nonlocal coords
            coords.append(
                line_offset_feature(feature, distance,
                                    unit).geometry.coordinates)
            return True

        flatten_each(geojson, callback_flatten_each)
        return Feature(geometry=MultiLineString(coords), properties=properties)
示例#2
0
文件: misc.py 项目: omanges/turfpy
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())
示例#3
0
def scale(feature, factor, origin):
    is_point = get_type(feature) == "Point"
    origin = define_origin(feature, origin)

    if factor == 1 or is_point:
        return feature

    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

    coord_each(feature, _callback_coord_each)

    return feature
示例#4
0
def polygon_tangents(point, polygon):
    """
    Finds the tangents of a (Multi)Polygon from a Point.

    :param point: Point or Point Feature.
    :param polygon: (Multi)Polygon or (Multi)Polygon Feature.
    :return: FeatureCollection of two tangent Point Feature.

    Example:

    >>> from turfpy.measurement import polygon_tangents
    >>> from geojson import Polygon, Point, Feature
    >>> point = Feature(geometry=Point((61, 5)))
    >>> polygon = Feature(geometry=Polygon([(11, 0), (22, 4), (31, 0), (31, 11),
    ...                                 (21, 15), (11, 11), (11, 0)]))
    >>> polygon_tangents(point, polygon)
    """
    point_coords = get_coords(point)
    poly_coords = get_coords(polygon)

    enext = 0
    bbox_points = bbox(polygon)
    nearest_pt_index = 0
    nearest = None

    if (bbox_points[0] < point_coords[0] < bbox_points[2]
            and bbox_points[1] < point_coords[1] < bbox_points[3]):
        nearest = nearest_point(point, explode(polygon))
        nearest_pt_index = nearest.properties.featureIndex

    geo_type = get_type(polygon)

    if geo_type == "Polygon":
        rtan = poly_coords[0][nearest_pt_index]
        ltan = poly_coords[0][0]
        if nearest:
            if nearest["geometry"]["coordinates"][1] < point_coords[1]:
                ltan = poly_coords[0][nearest_pt_index]

        eprev = _is_left(
            poly_coords[0][0],
            poly_coords[0][len(poly_coords[0]) - 1],
            point_coords,
        )
        out = process_polygon(poly_coords[0], point_coords, eprev, enext, rtan,
                              ltan)
        rtan = out[0]
        ltan = out[1]
    elif geo_type == "MultiPolygon":
        closest_feature = 0
        closest_vertex = 0
        vertices_counted = 0
        for i in range(0, len(poly_coords[0])):
            closest_feature = i
            vertice_found = False
            for i2 in range(0, len(poly_coords[0][i])):
                closest_vertex = i2
                if vertices_counted == nearest_pt_index:
                    vertice_found = True
                    break
                vertices_counted += 1
            if vertice_found:
                break
        rtan = poly_coords[0][closest_feature][closest_vertex]
        ltan = poly_coords[0][closest_feature][closest_vertex]
        eprev = _is_left(
            poly_coords[0][0][0],
            poly_coords[0][0][len(poly_coords[0][0]) - 1],
            point_coords,
        )
        for ring in poly_coords:
            out = process_polygon(ring[0], point_coords, eprev, enext, rtan,
                                  ltan)
            rtan = out[0]
            ltan = out[1]

    return FeatureCollection(
        [Feature(geometry=Point(rtan)),
         Feature(geometry=Point(ltan))])