def __init__(self, segment: Dict):
     self.strava_id = segment["strava_id"]
     self.name_str = segment["name"]
     self.start_latlng = segment["start_latlng"]
     self.end_latlng = segment["end_latlng"]
     self.bearing = calculate_initial_compass_bearing(
         point_a=tuple(self.start_latlng), point_b=tuple(self.end_latlng))
Example #2
0
def _calculate_bearings(graph, nodes):
    """
    Calculate the compass bearings for each sequential node paid in `nodes`.  Lat/lon coordinates are expected to be
    node attributes in `graph` named 'y' and 'x'.
    Args:
        graph (networkx graph):  containing lat/lon coordinates of each node in `nodes`
        nodes (list): list of nodes in sequential order that bearings will be calculated
    Returns:
        list[float] of the bearings between each node pair
    """

    # bearings list
    bearings = []
    edge_type = is_graph_line_or_circle(graph)

    node_pairs = list(zip(nodes[:-1], nodes[1:]))
    if edge_type == 'circle':
        node_pairs = [(nodes[-1], nodes[0])] + node_pairs + [(nodes[-1], nodes[0])]

    for pair in node_pairs:
        comp_bearing = calculate_initial_compass_bearing(
            (graph.nodes[pair[0]]['x'], graph.nodes[pair[0]]['y']),
            (graph.nodes[pair[1]]['x'], graph.nodes[pair[1]]['y'])
        )
        bearings.append((pair[0], pair[1], comp_bearing))

    return bearings
Example #3
0
def add_direction(input_df):
    df = input_df[['Milliseconds', 'GPSLatitude', 'GPSLongitude']]
    df = df.drop_duplicates(subset='GPSLatitude')
    compassbearing_series = pd.Series()
    direction_x_series = pd.Series()
    direction_y_series = pd.Series()
    speed_series = pd.Series()
    df = df.reset_index()
    for row in range(0, len(df)):
        if row == len(df) - 1 or np.isnan(
                df.loc[row, 'GPSLatitude']) or np.isnan(df.loc[row + 1,
                                                               'GPSLatitude']):
            direction_x_series = direction_x_series.append(pd.Series(
                direction_x_series.iloc[-1]),
                                                           ignore_index=True)
            direction_y_series = direction_y_series.append(pd.Series(
                direction_y_series.iloc[-1]),
                                                           ignore_index=True)
            speed_series = speed_series.append(pd.Series(
                speed_series.iloc[-1]),
                                               ignore_index=True)
            compassbearing_series = compassbearing_series.append(
                pd.Series(compassbearing_series.iloc[-1]), ignore_index=True)
        else:

            lat1, long1 = df.loc[row, 'GPSLatitude'], df.loc[row,
                                                             'GPSLongitude']
            lat2, long2 = df.loc[row + 1,
                                 'GPSLatitude'], df.loc[row + 1,
                                                        'GPSLongitude']

            distance = get_distance(lat1, long1, lat2, long2) * 1000
            diff_timestamp = (df.loc[row + 1, 'Milliseconds'] -
                              df.loc[row, 'Milliseconds']) / 1000

            x, y, compassbearing = cb.calculate_initial_compass_bearing(
                lat1, long1, lat2, long2)

            direction_x_series = direction_x_series.append(pd.Series(x),
                                                           ignore_index=True)
            direction_y_series = direction_y_series.append(pd.Series(y),
                                                           ignore_index=True)
            speed_series = speed_series.append(pd.Series(distance /
                                                         diff_timestamp),
                                               ignore_index=True)
            compassbearing_series = compassbearing_series.append(
                pd.Series(compassbearing), ignore_index=True)

    df = df.assign(Speed=speed_series.values)
    df = df.assign(DirectionX=direction_x_series.values)
    df = df.assign(DirectionY=direction_y_series.values)
    df = df.assign(CompassBearing=compassbearing_series.values)
    df = df.drop(columns=['index', 'Milliseconds'])
    input_df = pd.merge(input_df,
                        df,
                        how='left',
                        on=['GPSLatitude', 'GPSLongitude'])

    return input_df
Example #4
0
def azimuth(lat1, lon1, lat2, lon2):

    current_coord = (lat1, lon1)
    coord2 = (lat2, lon2)
    diff1 = -(current_coord[0] - coord2[0])
    diff2 = -(current_coord[1] - coord2[1])

    azimuth = cp.calculate_initial_compass_bearing(current_coord, coord2)

    return azimuth
Example #5
0
def get_xy_to_crs_double_loops(gdf, n_det=1, double_loops=True):
    new_gdf = []
    individ_gdf = []
    for i in range(1, n_det + 1):
        a = pd.Series(gdf['detector ' + str(i)])
        a_x = list(a.apply(lambda p: p.x))
        a_y = list(a.apply(lambda p: p.y))
        p_d = pd.Series(gdf['bearing ' + str(i)])
        p_x = list(p_d.apply(lambda p: p.x))
        p_y = list(p_d.apply(lambda p: p.y))
        p = Proj(proj='utm', zone=34, ellps='WGS84', preserve_units=False)
        # Detector coordinates transformation
        lon, lat = p(a_x, a_y, inverse=True)
        c = {'lon': lon, 'lat': lat}
        df = pd.DataFrame(c)
        det_lonlat = df.apply(tuple, axis=1)
        det_lonlat = det_lonlat.rename('detector_' + str(i))
        # Bearing points coordinates transformation
        p_lon, p_lat = p(p_x, p_y, inverse=True)
        p_c = {'lon_p': p_lon, 'lat_p': p_lat}
        df_p = pd.DataFrame(p_c)
        p1 = [tuple(xy) for xy in zip(df.lat, df.lon)]
        p2 = [tuple(xy) for xy in zip(df_p.lat_p, df_p.lon_p)]
        bearing = [compassbearing.calculate_initial_compass_bearing(p1[j], p2[j]) for j in range(0, len(p1))]
        gdf = gdf.drop(['detector ' + str(i)], axis=1)
        gdf = gdf.drop(['bearing ' + str(i)], axis=1)
        geom = [Point(xy) for xy in det_lonlat]
        gdf = pd.concat([gdf, det_lonlat], axis=1)
        gdf.insert(len(gdf.columns), 'detector_bearing_' + str(i), bearing)
        gdf_ind = gdf[['index', 'N1', 'N2', 'detector_' + str(i), 'detector_bearing_' + str(i)]]
        gdf_ind = gpd.GeoDataFrame(gdf_ind, crs='WGS84', geometry=geom)
        individ_gdf.append(gdf_ind)
    if double_loops:
        for i in range(1, n_det + 1):
            a = pd.Series(gdf['detector ' + str(i) + 'bis'])
            a_x = list(a.apply(lambda p: p.x))
            a_y = list(a.apply(lambda p: p.y))
            p_d = pd.Series(gdf['bearing ' + str(i + n_det)])
            p_x = list(p_d.apply(lambda p: p.x))
            p_y = list(p_d.apply(lambda p: p.y))
            p = Proj(proj='utm', zone=34, ellps='WGS84', preserve_units=False)
            lon, lat = p(a_x, a_y, inverse=True)
            c = {'lon': lon, 'lat': lat}
            df = pd.DataFrame(c)
            det_lonlat = df.apply(tuple, axis=1)
            det_lonlat = det_lonlat.rename('detector_' + str(i) + 'bis')
            # Bearing points coordinates transformation
            p_lon, p_lat = p(p_x, p_y, inverse=True)
            p_c = {'lon_p': p_lon, 'lat_p': p_lat}
            df_p = pd.DataFrame(p_c)
            p1 = [tuple(xy) for xy in zip(df.lat, df.lon)]
            p2 = [tuple(xy) for xy in zip(df_p.lat_p, df_p.lon_p)]
            bearing = [compassbearing.calculate_initial_compass_bearing(p1[j], p2[j]) for j in range(0, len(p1))]
            gdf = gdf.drop(['detector ' + str(i) + 'bis'], axis=1)
            gdf = gdf.drop(['bearing ' + str(i + n_det)], axis=1)
            geom = [Point(xy) for xy in det_lonlat]
            gdf = pd.concat([gdf, det_lonlat], axis=1)
            gdf.insert(len(gdf.columns), 'detector_bearing_' + str(i) + 'bis', bearing)
            gdf_ind = gdf[['index', 'N1', 'N2', 'detector_' + str(i) + 'bis', 'detector_bearing_' + str(i) + 'bis']]
            gdf_ind = gpd.GeoDataFrame(gdf_ind, crs='WGS84', geometry=geom)
            individ_gdf.append(gdf_ind)
        gdf = gdf.drop(['geometry'], axis=1)
        geom = [Point(xy) for xy in gdf.detector_1]
        gdf = gpd.GeoDataFrame(gdf, crs='WGS84', geometry=geom)
        new_gdf.append(gdf)
        new_gdf.append(individ_gdf)
    return new_gdf
def test_directly_south_gives_180():
    start_latlong = tuple(LatLon(lat=51.27987, lon=-2.77271))
    end_latlong = tuple(LatLon(lat=51.27800, lon=-2.77271))
    assert calculate_initial_compass_bearing(
        point_a=start_latlong,
        point_b=end_latlong) == pytest.approx(180.0, 0.01)
def test_directly_north_east_with_pos_lon_neg_lat():
    start_latlong = tuple(LatLon(lat=-22.5001, lon=33.0001))
    end_latlong = tuple(LatLon(lat=-22.5000, lon=33.00021))
    assert calculate_initial_compass_bearing(
        point_a=start_latlong, point_b=end_latlong) == pytest.approx(45.0, 1)
def create_turn_weight_edge_attr(graph,
                                 length_weight='length',
                                 normalization_coefficient=1):
    """
    add dictionary of turn weights to attributes for each edge
    Args:
        graph (NetworkX Graph): input graph with lat/lon attributes on nodes
        length_weight (str): edge attribute used for edge length
        normalization_coefficient (float): coefficient used to weight turn_weights relative to lengths
    Returns:
        NetworkX Graph with turn weight dictionary added to each edge.
        An edge's turn weight dictionary is keyed by possible predecessor edges.
    """
    length_min, length_max, length_median, length_mean, length_stdev = generate_turn_weight_normalization_parameters(
        graph, length_weight=length_weight)
    graph_copy = graph.copy()

    #e_prim is edge that turn attributes are added to, and e_pred is predecessor edge
    for e_prim in graph.edges(keys=True):
        for e_pred in graph.edges():
            if e_prim[0] == e_pred[1]:
                turn_start = e_pred[0]
                turn_middle = e_prim[0]
                turn_end = e_prim[1]

                key = e_prim[2]

                #create turn weights
                turn_start_lon = graph.nodes(data=True)[turn_start]['x']
                turn_middle_lon = graph.nodes(data=True)[turn_middle]['x']
                turn_end_lon = graph.nodes(data=True)[turn_end]['x']

                turn_start_lat = graph.nodes(data=True)[turn_start]['y']
                turn_middle_lat = graph.nodes(data=True)[turn_middle]['y']
                turn_end_lat = graph.nodes(data=True)[turn_end]['y']

                comp1_bearing = calculate_initial_compass_bearing(
                    (turn_start_lat, turn_start_lon),
                    (turn_middle_lat, turn_middle_lon))
                comp2_bearing = calculate_initial_compass_bearing(
                    (turn_middle_lat, turn_middle_lon),
                    (turn_end_lat, turn_end_lon))
                turn_angle = comp2_bearing - comp1_bearing
                if turn_angle < 0:
                    turn_angle = 360 + turn_angle
                if (turn_angle >= 315
                        and turn_angle <= 360) or (turn_angle >= 0
                                                   and turn_angle < 45):
                    turn_weight = 0
                elif turn_angle >= 45 and turn_angle < 135:
                    turn_weight = 1
                elif turn_angle >= 225 and turn_angle < 315:
                    turn_weight = 2
                else:
                    turn_weight = 4
                #create turn_length
                turn_length = turn_weight * length_max * normalization_coefficient

                #add turn_length attribute
                if 'turn_length' not in graph_copy[e_prim[0]][e_prim[1]][key]:
                    graph_copy[e_prim[0]][e_prim[1]][key]['turn_length'] = {
                        e_pred[0]: turn_length
                    }
                elif e_pred[0] not in graph_copy[e_prim[0]][
                        e_prim[1]][key]['turn_length']:
                    graph_copy[e_prim[0]][e_prim[1]][key]['turn_length'][
                        e_pred[0]] = turn_length
    return (graph_copy)