def is_multipoint_on_polygon(feature_1: Sequence, feature_2: Sequence) -> bool: """ Checks if feature_1 multipoint feature is in feature_2 polygon returns False, if all multipoints are on the boundary :param feature_1: Coordinates of multipoint feature :param feature_2: Coordinates of polygon feature 2 :return: boolean True/False if feature 1 is within feature 2 """ points_on_poly = False points_on_poly = all( boolean_point_in_polygon(coords_1, feature_2[1]) for coords_1 in feature_1[1]) if not points_on_poly: return points_on_poly points_on_poly = any( boolean_point_in_polygon(coords_1, feature_2[1], {"ignoreBoundary": True}) for coords_1 in feature_1[1]) return points_on_poly
def is_line_in_poly(feature_1: Sequence, feature_2: Sequence) -> bool: """ Checks if feature_1 linestring feature is in feature_2 polygon :param feature_1: Coordinates of linestring feature 1 :param feature_2: Coordinates of polygon feature 2 :return: boolean True/False if feature 1 is within feature 2 """ line_in_poly = False line_bbox = bbox(feature_1) poly_bbox = bbox(feature_2) if not bbox_overlap(poly_bbox, line_bbox): return False for i in range(len(feature_1) - 1): if not boolean_point_in_polygon(feature_1[i], feature_2): return False if not line_in_poly: line_in_poly = boolean_point_in_polygon(feature_1[i], feature_2, {"ignoreBoundary": True}) if not line_in_poly: mid = midpoint(point(feature_1[i]), point(feature_1[i + 1])) line_in_poly = boolean_point_in_polygon(mid, feature_2, {"ignoreBoundary": True}) return line_in_poly
def test_exception(self, pt, poly, exception_value): with pytest.raises(Exception) as excinfo: boolean_point_in_polygon(pt, poly) assert excinfo.type == InvalidInput assert str(excinfo.value) == exception_value
def disjoint(feature_1: List[Union[str, Sequence]], feature_2: List[Union[str, Sequence]]) -> bool: """ Returns true if the intersection of the two geometries is an empty set. :param feature_1: {List} a List with geometry type and coordinates :param feature_2: {List} a List with geometry type and coordinates :return: boolean True/False if features are disjoint """ is_disjoint = True if feature_1[0] in ["Point"]: if feature_2[0] in ["Point"]: is_disjoint = feature_1[1] != feature_2[1] elif feature_2[0] in ["LineString"]: is_disjoint = not boolean_point_on_line(feature_1[1], feature_2[1]) elif feature_2[0] in ["Polygon"]: is_disjoint = not boolean_point_in_polygon(feature_1[1], feature_2[1]) elif feature_1[0] in ["LineString"]: if feature_2[0] in ["Point"]: is_disjoint = not boolean_point_on_line(feature_2[1], feature_1[1]) elif feature_2[0] in ["LineString"]: is_disjoint = not is_line_on_line(feature_1[1], feature_2[1]) elif feature_2[0] in ["Polygon"]: is_disjoint = not is_line_in_poly(feature_2[1], feature_1[1]) elif feature_1[0] in ["Polygon"]: if feature_2[0] in ["Point"]: is_disjoint = not boolean_point_in_polygon(feature_2[1], feature_1[1]) elif feature_2[0] in ["LineString"]: is_disjoint = not is_line_in_poly(feature_1[1], feature_2[1]) elif feature_2[0] in ["Polygon"]: is_disjoint = not is_poly_in_poly(feature_2[1], feature_1[1]) return is_disjoint
def is_poly_in_poly(feature_1: Sequence, feature_2: Sequence) -> bool: """ Checks if polygon feature_1 is inside polygon feature_2 and either way See http://stackoverflow.com/a/4833823/1979085 :param feature: Coordinates of polygon feature 1 :param feature: Coordinates of polygon feature 1 :return: bool if there is an intersection """ feature_1_line = polygon_to_line(polygon(feature_1)) feature_2_line = polygon_to_line(polygon(feature_2)) for coord1 in feature_1_line["geometry"]["coordinates"]: if boolean_point_in_polygon(coord1, feature_2): return True for coord2 in feature_2_line["geometry"]["coordinates"]: if boolean_point_in_polygon(coord2, feature_1): return True if is_line_on_line(feature_1_line, feature_2_line): return True return False
def is_line_in_poly(feature_1: Sequence, feature_2: Sequence) -> bool: """ Checks if a linestring feature is inside or intersects a polygon feature :param feature_1: Coordinates of polygon feature :param feature_2: Coordinates of linestring feature :return: bool if there is an intersection """ feature_1_line = polygon_to_line(polygon(feature_1)) if is_line_on_line(feature_2, feature_1_line): return True for coord in feature_2: if boolean_point_in_polygon(coord, feature_1): return True return False
def is_poly_in_poly(feature_1: Sequence, feature_2: Sequence) -> bool: """ Checks if feature_1 polygon feature is in feature_2 polygon :param feature_1: Coordinates of polygon feature 1 :param feature_2: Coordinates of polygon feature 2 :return: boolean True/False if feature 1 is within feature 2 """ poly_bbox_1 = bbox(feature_1) poly_bbox_2 = bbox(feature_2) if not bbox_overlap(poly_bbox_2, poly_bbox_1): return False feature_1 = polygon_to_line(polygon(feature_1)) line_coords = get_coords_from_features(feature_1) for coords in line_coords: if not boolean_point_in_polygon(coords, feature_2): return False return True
def check_within(feature_1: List[Union[str, Sequence]], feature_2: List[Union[str, Sequence]]) -> bool: """ Returns true if the first geometry is completely within the second geometry :param feature_1: {List} a List with geometry type and coordinates :param feature_2: {List} a List with geometry type and coordinates :return: boolean True/False if feature 1 is within feature 2 """ is_within = False if feature_1[0] in ["Point"]: if feature_2[0] in ["Point", "MultiPoint"]: is_within = boolean_point_on_point(feature_1[1], feature_2[1]) elif feature_2[0] in ["LineString", "MultiLineString"]: is_within = boolean_point_on_line(feature_1[1], feature_2[1], {"ignoreEndVertices": True}) elif feature_2[0] in ["Polygon", "MultiPolygon"]: is_within = boolean_point_in_polygon(feature_1[1], feature_2[1], {"ignoreBoundary": True}) if feature_1[0] in ["MultiPoint"]: if feature_2[0] in ["MultiPoint"]: is_within = all( boolean_point_on_point(coords_1, feature_2[1]) for coords_1 in feature_1[1]) elif feature_2[0] in ["LineString", "MultiLineString"]: is_within = is_multipoint_on_linestring(feature_1, feature_2) elif feature_2[0] in ["Polygon", "MultiPolygon"]: is_within = is_multipoint_on_polygon(feature_1, feature_2) elif feature_1[0] in ["LineString"]: if feature_2[0] in ["LineString"]: is_within = is_line_on_line(feature_1[1], feature_2[1]) if feature_2[0] in ["MultiLineString"]: is_within = is_line_on_multiline(feature_1[1], feature_2[1]) elif feature_2[0] in ["Polygon"]: is_within = is_line_in_poly(feature_1[1], feature_2[1]) elif feature_2[0] in ["MultiPolygon"]: is_within = is_line_in_multipoly(feature_1[1], feature_2[1]) elif feature_1[0] in ["MultiLineString"]: if feature_2[0] in ["MultiLineString"]: is_within = all( is_line_on_multiline(coords_1, feature_2[1]) for coords_1 in feature_1[1]) elif feature_2[0] in ["Polygon", "MultiPolygon"]: is_within = all( is_line_in_poly(coords_1, feature_2[1]) for coords_1 in feature_1[1]) elif feature_1[0] in ["Polygon"]: if feature_2[0] in ["Polygon"]: is_within = is_poly_in_poly(feature_1[1], feature_2[1]) if feature_2[0] in ["MultiPolygon"]: is_within = is_poly_in_multipoly(feature_1[1], feature_2[1]) elif feature_1[0] in ["MultiPolygon"]: if feature_2[0] in ["MultiPolygon"]: is_within = all( is_poly_in_multipoly(coords_1, feature_2[1]) for coords_1 in feature_1[1]) return is_within
def point_on_feature(features: GeoJSON) -> Point: """ Takes a Feature or FeatureCollection and returns a {Point} guaranteed to be on the surface of the feature. Given a {Polygon}, the point will be in the area of the polygon Given a {LineString}, the point will be along the string Given a {Point}, the point will the same as the input :param features: any GeoJSON feature or feature collection :return: Point GeoJSON Feature on the surface of `input` """ feature_collection = normalize_to_feature_collection(features) center_point = center(feature_collection) center_coords = center_point.get("geometry").get("coordinates") # check to see if centroid is on surface center_on_surface = False geometry_type = get_geometry_type(feature_collection) geometry_coords = get_coords_from_features(feature_collection) if isinstance(geometry_type, str): geometry_type = [geometry_type] for geo_type, geo_coords in zip(geometry_type, geometry_coords): if geo_type in ["Point", "MultiPoint"]: if geo_type == "Point": geo_coords = [geo_coords] for point_coords in geo_coords: if (center_coords[0] == point_coords[0]) and (center_coords[1] == point_coords[1]): center_on_surface = True break elif geo_type in ["LineString", "MultiLineString"]: if geo_type == "LineString": geo_coords = [geo_coords] for line_coords in geo_coords: if boolean_point_on_line(center_coords, line_coords): center_on_surface = True break elif geo_type in ["Polygon", "MultiPolygon"]: if geo_type == "Polygon": geo_coords = polygon(geo_coords) else: geo_coords = multi_polygon(geo_coords) if boolean_point_in_polygon(center_point, geo_coords): center_on_surface = True break if center_on_surface: point_on_surface = center_point else: point_on_surface = nearest_point(center_point, feature_collection) return point_on_surface
def test_boolean_point_in_polygon_simple(self, poly, point_in, point_out): assert boolean_point_in_polygon(point_in, poly) assert not boolean_point_in_polygon(point_out, poly)
def test_boolean_point_in_polygon(self, fixture, points): poly = fixture["in"] for pt, result in points: assert boolean_point_in_polygon(pt, poly) is result
def test_boolean_point_in_polygon_boundary(self, boundary, poly, points): options = {"ignoreBoundary": boundary} for pt, result in points: assert boolean_point_in_polygon(pt, poly, options) is result(boundary)