def rhumb_distance(origin, destination, options: Dict = None) -> float: """ Calculates the rhumb distance between two Points. Units are defined in helpers._units # https://en.wikipedia.org/wiki/Rhumb_line :param start: starting point [lng, lat] or Point feature :param end: ending point [lng, lat] or Point feature :param options: dictionary with units as an attribute. Units are defined in helpers._units :return: distance between the 2 points """ if not isinstance(options, dict): options = {} origin = get_coords_from_features(origin, ["Point"]) destination = get_coords_from_features(destination, ["Point"]) # compensate the crossing of the 180th meridian (https://macwright.org/2016/09/26/the-180th-meridian.html) # solution from https://github.com/mapbox/mapbox-gl-js/issues/3250#issuecomment-294887678 if (destination[0] - origin[0]) > 180: destination[0] -= 360 elif (origin[0] - destination[0]) > 180: destination[0] += 360 distance_in_meters = calculate_rhumb_distance(origin, destination) distance = convert_length( distance_in_meters, "meters", options.get("units", "kilometers") ) return distance
def rhumb_destination(features: Dict, options: Dict = None) -> Point: """ Returns the destination {Point} having travelled the given distance along a Rhumb line from the origin Point with the (varant) given bearing. # https://en.wikipedia.org/wiki/Rhumb_line :param features: any GeoJSON feature or feature collection :param properties: specification to calculate the rhumb line [options["distance"]=100] distance from the starting point [options["bearing"]=180] varant bearing angle ranging from -180 to 180 degrees from north [options["units"]=kilometers] units: specifies distance (can be degrees, radians, miles, or kilometers) :param options: optional parameters also be part of features["properties"] [options["units"]={}] can be degrees, radians, miles, or kilometers [options["properties"]={}] Translate GeoJSON Properties to Point [options["id"]={}] Translate GeoJSON Id to Point :return: a FeatureDestination point. """ if not options: options = features.get("properties", {}) coords = get_coords_from_features(features, ["Point"]) bearing = options.get("bearing", 180) distance = options.get("dist", 100) units = options.get("units", "kilometers") distance_in_meters = convert_length(abs(distance), original_unit=units, final_unit="meters") if distance < 0: distance_in_meters *= -1 destination = calculate_rhumb_destination(coords, distance_in_meters, bearing) # compensate the crossing of the 180th meridian: # (https://macwright.org/2016/09/26/the-180th-meridian.html) # solution from: # https://github.com/mapbox/mapbox-gl-js/issues/3250#issuecomment-294887678 if (destination[0] - coords[0]) > 180: destination[0] -= 360 elif (coords[0] - destination[0]) > 180: destination[0] += 360 return point(destination, options.get("properties", None))
def point_to_line_distance( point: Union[Sequence, Dict, Feature], line: Union[Sequence, Dict, Feature], options: Dict = None, ) -> float: """ Returns the minimum distance between a {Point} and a {LineString}, being the distance from a line the minimum distance between the point and any segment of the `LineString` http://geomalgorithms.com/a02-_lines.html :param point: Point GeoJSON Feature or Geometry :param line: LineString GeoJSON Feature or Geometry :param options: Optional parameters [options["units"]]: any supported unit (e.g. degrees, radians, miles...) [options["method"]]: geodesic or 'planar for distance calculation :return: distance between point and line """ dist = [] if not isinstance(options, dict): options = {"method": "geodesic", "units": "kilometers"} point = get_coords_from_features(point, ["Point"]) line = get_coords_from_features(line, ["LineString"]) for i in range(1, len(line)): dist.append( get_distance_to_segment(point, line[i - 1], line[i], options.get("method", "geodesic"))) dist = convert_length(min(dist), "degrees", options.get("units", "kilometers")) return dist
def test_convert_length(value, original_unit, final_unit, result): assert convert_length(value, original_unit, final_unit) == result