예제 #1
0
def test_geometry_length__linestring():
    geod = Geod(ellps="WGS84")
    assert_almost_equal(
        geod.geometry_length(LineString([Point(1, 2), Point(3, 4)])),
        313588.39721259556,
        decimal=2,
    )
예제 #2
0
def test_geometry_length__multilinestring():
    geod = Geod(ellps="WGS84")
    line_string = LineString([Point(1, 2), Point(3, 4), Point(5, 2)])
    assert_almost_equal(
        geod.geometry_length(MultiLineString([line_string, line_string])),
        1254353.5888503822,
        decimal=2,
    )
예제 #3
0
def test_geometry_length__multipolygon():
    geod = Geod(ellps="WGS84")
    polygon = Polygon(LineString([Point(1, 2), Point(3, 4), Point(5, 2)]))
    assert_almost_equal(
        geod.geometry_length(MultiPolygon([polygon, polygon])),
        2 * 1072185.2103813463,
        decimal=2,
    )
예제 #4
0
def test_geometry_length__polygon():
    geod = Geod(ellps="WGS84")
    assert_almost_equal(
        geod.geometry_length(
            Polygon(LineString([Point(1, 2), Point(3, 4), Point(5, 2)]))
        ),
        1072185.2103813463,
        decimal=2,
    )
예제 #5
0
def test_geometry_length__linestring__radians():
    geod = Geod(ellps="WGS84")
    assert_almost_equal(
        geod.geometry_length(
            LineString([
                Point(math.radians(1), math.radians(2)),
                Point(math.radians(3), math.radians(4)),
            ]),
            radians=True,
        ),
        313588.39721259556,
        decimal=2,
    )
예제 #6
0
def test_geometry_length__multipolygon__radians():
    geod = Geod(ellps="WGS84")
    polygon = Polygon(
        LineString([
            Point(math.radians(1), math.radians(2)),
            Point(math.radians(3), math.radians(4)),
            Point(math.radians(5), math.radians(2)),
        ]))
    assert_almost_equal(
        geod.geometry_length(MultiPolygon([polygon, polygon]), radians=True),
        2 * 1072185.2103813463,
        decimal=2,
    )
예제 #7
0
def test_geometry_length__polygon__radians():
    geod = Geod(ellps="WGS84")
    assert_almost_equal(
        geod.geometry_length(
            Polygon(
                LineString([
                    Point(math.radians(1), math.radians(2)),
                    Point(math.radians(3), math.radians(4)),
                    Point(math.radians(5), math.radians(2)),
                ])),
            radians=True,
        ),
        1072185.2103813463,
        decimal=2,
    )
예제 #8
0
def to_graph(link_path, node_path):
    adjacency_list = defaultdict(list)

    with fiona.open(link_path) as link_collection,\
            fiona.open(node_path) as node_collection:

        nodes_coordinates = []
        nodes_ids = []
        for rec in node_collection:
            nodes_coordinates.append(rec['geometry']['coordinates'])
            nodes_ids.append(rec['properties']['id'])

        kdtree = KDTree(nodes_coordinates)

        geod = Geod(ellps="WGS84")
        for rec in link_collection:
            direction = rec['properties']['dir']
            vel_AB = rec['properties']['VEL_AB']
            vel_BA = rec['properties']['VEL_BA']

            length = geod.geometry_length(shape(rec['geometry']))
            time_AB = length / vel_AB * (60/1000) * 60
            time_BA = length / vel_BA * (60/1000) * 60

            start_point = rec['geometry']['coordinates'][0]
            end_point = rec['geometry']['coordinates'][-1]

            start_distance, start_pos = kdtree.query(start_point)
            end_distance, end_pos = kdtree.query(end_point)

            start_id = nodes_ids[start_pos]
            end_id = nodes_ids[end_pos]

            if direction == 1:
                adjacency_list[start_id].append((time_AB, end_id))
            elif direction == -1:
                adjacency_list[end_id].append((time_BA, start_id))
            elif direction == 0:
                adjacency_list[start_id].append((time_AB, end_id))
                adjacency_list[end_id].append((time_BA, start_id))
            else:
                raise ValueError(direction)

    return adjacency_list
예제 #9
0
def get_reachMeasure(intersectionPoint, flowlines, *raindropPath):
    """Collect NHD Flowline Reach Code and Measure"""
    print('intersectionPoint: ', intersectionPoint)

    # Set Geoid to measure distances in meters
    geod = Geod(ellps="WGS84")

    # Convert the flowline to a geometry colelction to be exported
    nhdGeom = flowlines['features'][0]['geometry']
    nhdFlowline = GeometryCollection([shape(nhdGeom)])[0]

    # Select the stream name from the NHD Flowline
    streamname = flowlines['features'][0]['properties']['gnis_name']
    if streamname == ' ':
        streamname = 'none'

    # Create streamInfo dict and add some data
    streamInfo = {
        'gnis_name':
        streamname,
        'comid':
        flowlines['features'][0]['properties']['comid'],
        # 'lengthkm': flowlines['features'][0]['properties']['lengthkm'],
        'intersectionPoint':
        (intersectionPoint.coords[0][1], intersectionPoint.coords[0][0]),
        'reachcode':
        flowlines['features'][0]['properties']['reachcode']
    }

    # Add more data to the streamInfo dict
    if raindropPath:
        streamInfo['raindropPathDist'] = round(
            geod.geometry_length(raindropPath[0]), 2)

    # If the intersectionPoint is on the NHD Flowline, split the flowline at the point
    if nhdFlowline.intersects(intersectionPoint) is True:
        NHDFlowlinesCut = split(nhdFlowline, intersectionPoint)

    # If they don't intersect (weird right?), buffer the intersectionPoint and then split the flowline
    if nhdFlowline.intersects(intersectionPoint) is False:
        buffDist = intersectionPoint.distance(nhdFlowline) * 1.01
        buffIntersectionPoint = intersectionPoint.buffer(buffDist)
        NHDFlowlinesCut = split(nhdFlowline, buffIntersectionPoint)
        # print('NHDFlowlinesCut: ', len(NHDFlowlinesCut), NHDFlowlinesCut)

    # If the NHD Flowline was split, then calculate measure
    try:
        NHDFlowlinesCut[1]
    except:  # If NHDFlowline was not split, then the intersectionPoint is either the first or last point on the NHDFlowline
        startPoint = Point(nhdFlowline[0].coords[0][0],
                           nhdFlowline[0].coords[0][1])
        lastPointID = len(nhdFlowline[0].coords) - 1
        lastPoint = Point(nhdFlowline[0].coords[lastPointID][0],
                          nhdFlowline[0].coords[lastPointID][1])
        if (intersectionPoint == startPoint):
            streamInfo['measure'] = 100
        if (intersectionPoint == lastPoint):
            streamInfo['measure'] = 0
        if (intersectionPoint != startPoint
                and intersectionPoint != lastPoint):
            print('Error: NHD Flowline measure not calculated')
            streamInfo['measure'] = 'null'
    else:
        lastLineID = len(NHDFlowlinesCut) - 1
        distToOutlet = round(geod.geometry_length(NHDFlowlinesCut[lastLineID]),
                             2)
        flowlineLength = round(geod.geometry_length(nhdFlowline), 2)
        streamInfo['measure'] = round((distToOutlet / flowlineLength) * 100, 2)
    print('calculated measure and reach')

    return streamInfo
예제 #10
0
def test_geometry_length__multipoint():
    geod = Geod(ellps="WGS84")
    assert (
        geod.geometry_length(MultiPoint([Point(1, 2), Point(3, 4), Point(5, 2)])) == 0
    )
예제 #11
0
def test_geometry_length__point():
    geod = Geod(ellps="WGS84")
    assert geod.geometry_length(Point(1, 2)) == 0
예제 #12
0
def main(config):
    data_path = config['paths']['data']
    scratch_path = config['paths']['scratch']

    edges = gpd.read_file((os.path.join(scratch_path,
                            "road_africa","africa-road.gpkg")),
                            layer="lines",
                            ignore_fields=["waterway","aerialway","barrier","man_made","z_order","other_tags"])
    
    print(edges)
    print("Done reading file")
    
    # From the geopackage file extract relevant roads
    highway_list = ['motorway','motorway_link',
               'trunk','trunk_link',
               'primary','primary_link',
               'secondary','secondary_link',
               'tertiary','tertiary_link']
    edges = edges[edges.highway.isin(highway_list)]
    edges['highway'] = edges.progress_apply(lambda x: x.highway.replace('_link',''),axis=1)

    # Create network topology
    network = create_network_from_nodes_and_edges(
        None,
        edges,
        "road",
        out_fname,
    )

    network.edges = network.edges.set_crs(epsg=4326)
    network.nodes = network.nodes.set_crs(epsg=4326)
    
    print (network.edges)
    print (network.nodes)
    print("Ready to export file")

    # Store the final road network in geopackage in the processed_path
    out_fname = os.path.join(data_path,"road/africa","africa-roads.gpkg")

    network.edges.to_file(out_fname, layer='edges', driver='GPKG')
    network.nodes.to_file(out_fname, layer='nodes', driver='GPKG')


    print("Done exporting, ready to add attributes")

    """Assign country info"""

    #Find the countries of the nodes and assign them to the node ID's, accordingly modify the edge ID's as well

    nodes = gpd.read_file(out_fname,layer='nodes')
    edges = gpd.read_file(out_fname,layer='edges')
    print("Done reading files")

    global_country_info = gpd.read_file(os.path.join(data_path,
                                                "Admin_boundaries",
                                                "gadm36_levels_gpkg",
                                                "gadm36_levels_continents.gpkg"))
    global_country_info = global_country_info.to_crs(epsg=4326)
    global_country_info = global_country_info.explode(ignore_index=True)
    global_country_info = global_country_info.sort_values(by="CONTINENT",ascending=True)
    # print (global_country_info)

    
    nodes["node_id"] = nodes.progress_apply(lambda x:"_".join(x["node_id"].split("_")[1:]),axis=1)
    nodes = nodes[["node_id","geometry"]]

    edges["edge_id"] = edges.progress_apply(lambda x:"_".join(x["edge_id"].split("_")[1:]),axis=1)
    edges["from_node"] = edges.progress_apply(lambda x:"_".join(x["from_node"].split("_")[1:]),axis=1)
    edges["to_node"] = edges.progress_apply(lambda x:"_".join(x["to_node"].split("_")[1:]),axis=1)
    edges = edges[["edge_id","from_node","to_node","highway","surface","maxspeed","lanes","bridge","length_km","geometry"]]

    # Set the crs
    edges = edges.set_crs(epsg=4326)
    nodes = nodes.set_crs(epsg=4326)
    
    nodes, edges = match_nodes_edges_to_countries(nodes,edges,global_country_info)

    print ("Done adding country info attributes")

    #edges.to_file(os.path.join(data_path,"road/africa","africa-roads.gpkg"), layer='edges', driver='GPKG')
    #nodes.to_file(os.path.join(data_path,"road/africa","africa-roads.gpkg"), layer='nodes', driver='GPKG')

    """Assign road attributes"""

    # Calculate and add length of line segments 
    geod = Geod(ellps="WGS84")
    edges['length_m'] = edges.progress_apply(lambda x:float(geod.geometry_length(x.geometry)),axis=1)
    edges = edges.drop(['length_km'],axis=1)

    # Drop geometry for faster processing times
    edges_simple = edges.drop(['geometry'],axis=1)

    # Add road condition and material 
    edges_simple['surface_material'] = edges_simple.progress_apply(lambda x:get_road_condition_surface(x),axis=1)
    edges_simple[['road_cond','material']] = edges_simple['surface_material'].progress_apply(pd.Series)
    edges_simple.drop('surface_material',axis=1,inplace=True)

    # Add number of lanes
    edges_simple['lanes'] = edges_simple.progress_apply(lambda x:get_road_lanes(x),axis=1)

    # Add road width
    width = 6.5 # Default carriageway width in meters for Africa, needs to be generalizable for global
    shoulder = 1.5 # Default shoulder width in meters for Africa, needs to be generalizable for global
    edges_simple['width_m'] = edges_simple.progress_apply(lambda x:float(x.lanes)*width + 2.0*shoulder,axis=1)

    # Assign min and max road speeds
    road_speeds = pd.read_excel(os.path.join(data_path,"road","global_road_speeds.xlsx"),sheet_name="global speeds")
    edges_simple = pd.merge(edges_simple,road_speeds,how="left",left_on=["from_iso"],right_on=["ISO_A3"])
    edges_simple["min_max_speed"] = edges_simple.progress_apply(lambda x:assign_road_speeds(x),axis=1)
    edges_simple[["min_speed","max_speed"]] = edges_simple["min_max_speed"].progress_apply(pd.Series)
    edges_simple.drop(["min_max_speed","maxspeed"]+road_speeds.columns.values.tolist(),axis=1,inplace=True)

    print("Done adding road attributes")

    """Assign cost attributes"""

    # Assign rehabilitation costs
    rehab_costs = pd.read_excel(os.path.join(data_path,"costs","rehabilitation_costs.xlsx"), sheet_name = "road_costs")
    edges_simple["rehab_costs"] = edges_simple.progress_apply(lambda x:get_rehab_costs(x,rehab_costs),axis=1)
    edges_simple[["cost_min","cost_max","cost_unit"]] = edges_simple["rehab_costs"].progress_apply(pd.Series)
    edges_simple.drop("rehab_costs",axis=1,inplace=True)

    # Assign tariff costs 
    cost_data = pd.read_csv(os.path.join(data_path,"costs","transport_costs.csv"))
    cost_data = cost_data.loc[cost_data['transport'] == "road"]
    cost_data.rename(columns = {'cost_km':'tariff_cost'}, inplace = True)

    edges_simple = pd.merge(edges_simple,cost_data[["from_iso3","tariff_cost"]],how="left",left_on=["from_iso"],right_on=["from_iso3"])

    edges_simple["min_tariff"] = edges_simple.progress_apply(lambda x:float(x.tariff_cost) - (float(x.tariff_cost)*0.2),axis=1)
    edges_simple["max_tariff"] = edges_simple.progress_apply(lambda x:float(x.tariff_cost) + (float(x.tariff_cost)*0.2),axis=1)
    edges_simple.drop(["tariff_cost","from_iso3"],axis=1,inplace=True)
    edges_simple["tariff_cost_unit"] = "USD/ton-km"

    # Assign flow costs    
    time_cost_factor = 0.49
    edges_simple["min_flow_cost"] = (time_cost_factor*edges["length_m"]/1000)/edges_simple["max_speed"] + (edges_simple["min_tariff"]*edges_simple["length_m"]/1000)
    edges_simple["max_flow_cost"] = (time_cost_factor*edges["length_m"]/1000)/edges_simple["min_speed"] + (edges_simple["max_tariff"]*edges_simple["length_m"]/1000)
    edges_simple["flow_cost_unit"] = "USD/ton"

    print("Done adding cost attributes")
    
    # Prepare for export and finish
    edges = edges_simple.merge(edges[["edge_id","geometry"]],how = "left", on = "edge_id")
    edges = gpd.GeoDataFrame(edges,geometry="geometry",crs="EPSG:4326")
    
    # Add the component column
    edges, nodes = components(edges,nodes)
    print("Done adding components")

    print("Ready to export")
    edges.to_file(os.path.join(data_path,"road/africa","africa-roads-modified.gpkg"), layer='edges', driver='GPKG')
    nodes.to_file(os.path.join(data_path,"road/africa","africa-roads-modified.gpkg"), layer='nodes', driver='GPKG')

    print("Done.")
예제 #13
0
piece_dict = {}
for edge in edge_dict:

    # Keep only unique break points
    break_points = edge_dict[edge].break_points
    unique_breaks = list(set(break_points))

    # If all break points are the same, the edge is a point and we can skip
    if len(unique_breaks) == 1:
        print('Edge is a point: ', edge)
        continue

    way_id = str(edge_dict[edge].way)
    try:
        full_line = way_dict[way_id]
        line_length_ft = geod.geometry_length(
            full_line) * 3.28084  # meters to ft
    except KeyError:
        print('Error, No way available for ', way_id)
        continue

    # Discard break points that are at the ends of the line
    int_points = []
    distances = []
    line_start = False
    line_end = False
    for point in unique_breaks:
        point_geom = Point(point)
        distance = full_line.project(point_geom, normalized=True)

        if distance * line_length_ft <= midblock_tolerance:
            line_start = True
예제 #14
0
def points_to_meters(point_1, point_2):
    line_string = LineString([point_1, point_2])
    geod = Geod(ellps="WGS84")
    return geod.geometry_length(line_string)