Exemplo n.º 1
0
def get_coords_from_geometry(geometry: Any,
                             allowed_types: Sequence = None,
                             raise_exception: bool = True) -> List:
    """
    Retrieves coords from a given Geometry. Geometry must be a GeoJSON,
    a Geometry object or a list of coordinates, otherwise it raises an exception.

    :param geometry: Any input value(s)
    :param allowed_types: allowed Feature types
    :param raise_exception: if an exception should be raised or if it should be silent
    :return: list with extracted coords
    """

    if not allowed_types:
        allowed_types = allowed_types_default

    if isinstance(geometry, (list, tuple)):
        return _process_list_input(allowed_types, geometry,
                                   get_coords_from_geometry, raise_exception)

    if isinstance(geometry, (Feature, dict)):
        if geometry.get("type") == "Feature":
            return get_coords_from_geometry(geometry.get("geometry", {}),
                                            allowed_types)

    allowed_class_types = [
        *[eval(allowed_type) for allowed_type in allowed_types],
        dict,
    ]

    if any(
            isinstance(geometry, allowed_type_class)
            and geometry.get("type", "") in allowed_types
            for allowed_type_class in allowed_class_types):
        return geometry.get("coordinates", [])

    if raise_exception:
        raise InvalidInput(
            error_code_messages["InvalidGeometry"](allowed_types))
    else:
        return []
Exemplo n.º 2
0
def square(bbox):
    """
    Takes a bounding box and calculates the minimum square bounding box that
    would contain the input.

    :param bbox: bounding box extent in [minX, minY, maxX, maxY] order

    :return: a square surrounding bbox

    """
    if not isinstance(bbox, list) or len(bbox) != 4:
        raise InvalidInput(error_code_messages["InvalidBoundingBox"])

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

    horizontal_distance = distance([west, south], [east, south])
    vertical_distance = distance([west, south], [west, north])

    if horizontal_distance >= vertical_distance:
        vertical_midpoint = (south + north) / 2
        bounding_box = [
            west,
            vertical_midpoint - ((east - west) / 2),
            east,
            vertical_midpoint + ((east - west) / 2),
        ]
    else:

        horizontal_midpoint = (west + east) / 2
        bounding_box = [
            horizontal_midpoint - ((north - south) / 2),
            south,
            horizontal_midpoint + ((north - south) / 2),
            north,
        ]

    return bounding_box
Exemplo n.º 3
0
def get_geometry_from_features(features: Any,
                               allowed_types: Sequence = None) -> List:
    """
    Retrieves Geometries from Features. Features must be a GeoJSON,
    a Feature object or a list of coordinates, otherwise it raises an exception.

    :param features: Any input value(s)
    :param allowed_types: allowed Feature types
    :return: list with extracted coords
    """

    if not allowed_types:
        allowed_types = allowed_types_default

    if isinstance(features, (list, tuple)):
        return _process_list_input([*allowed_types, "Feature"], features,
                                   get_geometry_from_features)

    if isinstance(features, (FeatureCollection, dict)):
        if features.get("type") == "FeatureCollection":
            return list(
                map(
                    lambda feature: feature.get("geometry", {}),
                    features.get("features", []),
                ))

    if isinstance(features, (Feature, dict)):
        if features.get("type", "") == "Feature":
            if features.get("geometry", {}).get("type", "") in allowed_types:
                return features.get("geometry", {})

    if isinstance(features,
                  (*[eval(allowed_type)
                     for allowed_type in allowed_types], dict)):
        if features.get("type", "") in allowed_types:
            return features

    raise InvalidInput(error_code_messages["InvalidGeometry"](allowed_types))
Exemplo n.º 4
0
def along(line, dist, options=None):
    """
    Takes a LineString and returns a Point at a specified distance along the line

    :param line: input LineString
    :param dist: distance along the line
    :param options: optional parameters
        [options["units"]="kilometers"] can be degrees, radians, miles, or kilometers
    :return: Point `dist` `units` along the line
    """

    if not options or not isinstance(options, dict):
        options = {}

    if not isinstance(dist, (float, int)) or dist < 0:
        raise InvalidInput(error_code_messages["InvalidDistance"])

    coords = get_coords_from_features(line, ["LineString"])

    travelled = 0
    for i in range(len(coords)):
        if dist >= travelled and i == len(coords) - 1:
            break
        elif travelled >= dist:
            overshot = dist - travelled
            if not overshot:
                return point([truncate(coord, 6) for coord in coords[i]])
            else:
                direction = bearing(coords[i], coords[i - 1]) - 180
                interpolated = destination(coords[i], overshot, direction,
                                           options)
                return interpolated
        else:
            travelled += distance(coords[i], coords[i + 1])

    return point([truncate(coord, 6) for coord in coords[-1]])