Source code for turf.point_on_feature._point_on_feature

from typing import List, TypeVar, Union

import numpy as np

from turf.boolean_point_in_polygon import boolean_point_in_polygon
from turf.center import center
from turf.explode import explode
from turf.nearest_point import nearest_point
from turf.helpers import Feature, FeatureCollection, Point
from turf.helpers import feature, feature_collection, point
from turf.helpers._features import all_geometry_types
from turf.utils.error_codes import error_code_messages
from turf.utils.exceptions import InvalidInput

from turf.boolean_point_on_line import boolean_point_on_line

GeoJSON = TypeVar("GeoJSON", Feature, FeatureCollection)


[docs]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 for feature in feature_collection["features"]: geometry_type = feature.get("geometry").get("type") geometry_coords = feature.get("geometry").get("coordinates") if geometry_type in ["Point", "MultiPoint"]: if geometry_type == "Point": geometry_coords = [geometry_coords] for point_coords in geometry_coords: if (center_coords[0] == point_coords[0]) and ( center_coords[1] == point_coords[1] ): center_on_surface = True break elif geometry_type in ["LineString", "MultiLineString"]: if geometry_type == "LineString": geometry_coords = [geometry_coords] for line_coords in geometry_coords: if boolean_point_on_line(center_coords, line_coords): center_on_surface = True break elif geometry_type in ["Polygon", "MultiPolygon"]: if boolean_point_in_polygon(center_point, feature): 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 normalize_to_feature_collection(geojson: GeoJSON) -> FeatureCollection: """ Normalizes any GeoJSON to a FeatureCollection :param geojson: any GeoJSON :return: FeatureCollection """ geojson_type = geojson.get("type") if geojson_type == "FeatureCollection": pass elif geojson_type == "Feature": geojson = feature_collection([geojson]) else: geojson = feature_collection([feature(geojson)]) return geojson