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
def circle( center: Feature, radius: int, steps: int = 64, units: str = "km", **kwargs ) -> Polygon: """ Takes a Point and calculates the circle polygon given a radius in degrees, radians, miles, or kilometers; and steps for precision. :param center: A `Point` object representing center point of circle. :param radius: An int representing radius of the circle. :param steps: An int representing number of steps. :param units: A string representing units of distance e.g. 'mi', 'km', 'deg' and 'rad'. :param kwargs: A dict representing additional properties. :return: A polygon feature object. Example: >>> from turfpy.transformation import circle >>> from geojson import Feature, Point >>> circle(center=Feature(geometry=Point((-75.343, 39.984))), radius=5, steps=10) """ coordinates = [] options = dict(steps=steps, units=units) options.update(kwargs) for i in range(steps): bearing = i * -360 / steps pt = destination(center, radius, bearing, options=options) cords = pt.geometry.coordinates coordinates.append(cords) coordinates.append(coordinates[0]) return Feature(geometry=Polygon([coordinates], **kwargs))
def test_destination(): origin = Feature(geometry=Point((-75.343, 39.984))) distance = 50 bearing = 90 options = {"units": "mi"} des = destination(origin, distance, bearing, options) assert des["type"] == "Feature" assert des["geometry"]["type"] == "Point" c0, c1 = list(map(lambda x: round(x, 4), des["geometry"]["coordinates"])) assert c0 == -74.3986 assert c1 == 39.9802
def line_arc(center: Feature, radius: int, bearing1: int, bearing2: int, options: dict = {}) -> Feature: """ Creates a circular arc, of a circle of the given radius and center point, between bearing1 and bearing2; 0 bearing is North of center point, positive clockwise. :param center: A `Point` object representing center point of circle. :param radius: An int representing radius of the circle. :param bearing1: Angle, in decimal degrees, of the first radius of the arc. :param bearing2: Angle, in decimal degrees, of the second radius of the arc. :param options: A dict representing additional properties,which can be `steps` which has default values as 64 and `units` which has default values of `km` :return: A Line String feature object. Example: >>> from turfpy.misc import line_arc >>> from geojson import Feature, Point >>> center = Feature(geometry=Point((-75, 40))) >>> radius = 5 >>> bearing1 = 25 >>> bearing2 = 47 >>> feature = line_arc(center=center, radius=radius, >>> bearing1=bearing1, bearing2=bearing2) """ if not options: options = {} steps = int(options["steps"]) if options.get("steps") else 64 units = str(options.get("units")) if options.get("units") else "km" angle1 = convert_angle_to_360(bearing1) angle2 = convert_angle_to_360(bearing2) properties = {} if center.get("type"): if center.get("type") == "Feature": properties = center.get("properties") else: raise Exception("Invalid Feature value for center parameter") if angle1 == angle2: return Feature( geometry=LineString( circle(center, radius, steps, units)["geometry"]["coordinates"][0]), properties=properties, ) arc_start_degree = angle1 arc_end_degree = angle2 if angle1 < angle2 else angle2 + 360 alfa = arc_start_degree coordinates = [] i = 0 while alfa < arc_end_degree: coordinates.append( destination(center, radius, alfa, { "steps": steps, "units": units })["geometry"]["coordinates"]) i += 1 alfa = arc_start_degree + i * 360 / steps if alfa > arc_end_degree: coordinates.append( destination(center, radius, arc_end_degree, { "steps": steps, "units": units })["geometry"]["coordinates"]) return Feature(geometry=LineString(coordinates, properties=properties))