Beispiel #1
0
def get_footprints(perimeter=None,
                   point=None,
                   radius=None,
                   footprint='building'):

    if perimeter is not None:
        # Boundary defined by polygon (perimeter)
        footprints = ox.geometries_from_polygon(
            union(perimeter.geometry),
            tags={footprint: True} if type(footprint) == str else footprint)
        perimeter = union(ox.project_gdf(perimeter).geometry)

    elif (point is not None) and (radius is not None):
        # Boundary defined by circle with radius 'radius' around point
        footprints = ox.geometries_from_point(
            point,
            dist=radius,
            tags={footprint: True} if type(footprint) == str else footprint)
        perimeter = GeoDataFrame(geometry=[Point(point[::-1])],
                                 crs=footprints.crs)
        perimeter = ox.project_gdf(perimeter).geometry[0].buffer(radius)

    if len(footprints) > 0:
        footprints = ox.project_gdf(footprints)

    footprints = [[x] if type(x) == Polygon else x for x in footprints.geometry
                  if type(x) in [Polygon, MultiPolygon]]
    footprints = list(
        np.concatenate(footprints)) if len(footprints) > 0 else []
    footprints = [pathify(x) for x in footprints if x.within(perimeter)]

    return footprints, perimeter
Beispiel #2
0
    def GenerateOSMPOIs(self):

        # old way in OSMNX
        # df = ox.pois_from_polygon(polygon = self.bbox, amenities = self.tags)

        # note that even as of Dec, 2020 the code below will be depreciated, as OSMNX deleted the poi modeule in favor of the new geometries module
        #df = ox.pois_from_polygon(polygon = self.bbox, tags = {'amenity':self.current_amenity} )

        df = ox.geometries_from_polygon(self.bbox, self.tags).reset_index()

        print(f"is df empty: {df.empty}")
        if df.empty == True:
            return df

        points = df.copy()
        points = points.loc[points['element_type'] == 'node']

        polygons = df.copy()
        polygons = polygons.loc[polygons['element_type'] == 'way']
        polygons['geometry'] = polygons.centroid

        multipolys = df.copy()
        multipolys = multipolys.loc[multipolys['element_type'] == 'relation']
        multipolys['geometry'] = multipolys['geometry'].apply(
            lambda x: self.RelationtoPoint(x))

        df = pd.concat([
            pd.DataFrame(points),
            pd.DataFrame(polygons),
            pd.DataFrame(multipolys)
        ],
                       ignore_index=True)

        self.df = df
        return df
Beispiel #3
0
def _download_geometries(place, download_method, tags, crs, distance = 500.0):
    """
    The function downloads certain geometries from OSM, by means of OSMNX functions.
    It returns a GeoDataFrame, that could be empty when no geometries are found, with the provided tags.
    
    Parameters
    ----------
    place: string
        name of cities or areas in OSM: when using "OSMpolygon" please provide the name of a "relation" in OSM as an argument of "place"; when using "distance_from_address"
        provide an existing OSM address; when using "OSMplace" provide an OSM place name
    download_method: string {"polygon", "distance_from_address", "OSMplace"}
        it indicates the method that should be used for downloading the data.
    tag: dict 
        the desired OSMN tags
    crs: string
        the coordinate system of the case study area
        
    Returns
    -------
    geometries_gdf: GeoDataFrame
        the resulting GeoDataFrame
    """    
    if download_method == 'distance_from_address': 
        geometries_gdf = ox.geometries_from_address(place, tags = tags, dist = distance)
    elif download_method == 'OSMplace': 
        geometries_gdf = ox.geometries_from_place(place, tags = tags)
    else: 
        geometries_gdf = ox.geometries_from_polygon(place, tags = tags)
    
    geometries_gdf = geometries_gdf.to_crs(crs)
    return geometries_gdf
def get_urban_rail_fromOSM(place, download_method, epsg, distance=7000):
    """
    The function downloads and creates a simplified OSMNx graph for a selected area's urban rail network. 
    Afterwards, GeoDataFrames for nodes and edges are created, assigning new nodeID and edgeID identifiers.
        
    Parameters
    ----------
    place: string
        name of cities or areas in OSM: when using "OSMpolygon" please provide the name of a "relation" in OSM as an argument of "place"; when using "distance_from_address"
        provide an existing OSM address; when using "OSMplace" provide an OSM place name
    download_method: string {"polygon", "distance_from_address", "OSMplace"}
        it indicates the method that should be used for downloading the data. When 'polygon' the shape to get network data within. coordinates should be in
        unprojected latitude-longitude degrees (EPSG:4326).
    epsg: int
        epsg of the area considered; if None OSMNx is used for the projection
    distance: float
        it is used only if download_method == "distance from address"
        
    Returns
    -------
    nodes_gdf, edges_gdf: Tuple of GeoDataFrames
        the nodes and edges GeoDataFrames
    """

    crs = 'EPSG:' + str(epsg)
    tag = {'railway': True}

    if download_method == 'distance_from_address':
        railways_gdf = ox.geometries_from_address(place,
                                                  tags=tag,
                                                  dist=distance)
    elif download_method == 'OSMplace':
        railways_gdf = ox.geometries_from_place(place, tags=tag)
    else:
        railways_gdf = ox.geometries_from_polygon(place, tags=tag)

    print(railways_gdf.columns)
    railways_gdf = railways_gdf.to_crs(crs)
    to_keep = ["rail", "light_rail", "subway"]
    railways_gdf = railways_gdf[railways_gdf.railway.isin(to_keep)]
    railways_gdf['type'] = railways_gdf['railway']

    railways_gdf['length'] = railways_gdf.geometry.length
    railways_gdf = railways_gdf[[
        "geometry", "length", "name", "type", "bridge", "tunnel"
    ]]
    railways_gdf.reset_index(inplace=True, drop=True)
    railways_gdf['edgeID'] = railways_gdf.index.values.astype(int)
    railways_gdf.index.name = None
    return railways_gdf
Beispiel #5
0
def extract_osm_csv(district_poly: Polygon,
                    tags: dict = default_tags) -> pd.DataFrame:
    """Given the geometry of a district polygon and a set of tags (for different ammenities), the method extracts 
    a pandas dataframe using OpenStreetMaps API. 

    Args:
        district_poly (Polygon): Polygon geometry of a district
        tags (dict, optional): Tags to be passed on the OSM API to extract relevant data for a district. Defaults to default_tags.

    Returns:
        pd.DataFrame: A pandas dataframe containing a list of ammenities and other features for a given district.
    """
    district_osmdf = ox.geometries_from_polygon(district_poly, tags=tags)
    return district_osmdf
Beispiel #6
0
    def _get_city_data_within_city_limits(self):

        if self.city_dict['cycleways'] is True:
            self.cycleways = self._get_cycleways()
        if self.city_dict['roads'] is True:
            self.roads = ox.graph_from_place(self.city_name,
                                             network_type='drive')
        if self.city_dict['water'] is True:
            self.water = ox.geometries_from_polygon(self.city_area.unary_union,
                                                    tags=self.water_tags)
        if self.city_dict['green'] is True:
            self.green = ox.geometries_from_polygon(self.city_area.unary_union,
                                                    tags=self.green_tags)
        if self.city_dict['buildings'] is True:
            self.buildings = ox.geometries_from_place(self.city_name,
                                                      tags={
                                                          "building": True,
                                                          'landuse':
                                                          'construction'
                                                      })
        if self.city_dict['railways'] is True:
            self.railways = ox.geometries_from_place(self.city_name,
                                                     tags=self.railway_tags)
Beispiel #7
0
def osm_gdf_from_polygon(polygon, tags):
    """Create GeoDataFrame of OSM entities within boundaries of a (multi)polygon.

    Args:
        polygon (shapely.geometry.Polygon | shapely.geometry.MultiPolygon): Geographic boundaries to fetch geometries within
        tags (dict): Dict of tags used for finding objects in the selected area. Results returned are the union, not intersection of each individual tag. Each result matches at least one given tag. The dict keys should be OSM tags, (e.g., building, landuse, highway, etc) and the dict values should be either True to retrieve all items with the given tag, or a string to get a single tag-value combination, or a list of strings to get multiple values for the given tag. For example, tags = {‘building’: True} would return all building footprints in the area. tags = {‘amenity’:True, ‘landuse’:[‘retail’,’commercial’], ‘highway’:’bus_stop’} would return all amenities, landuse=retail, landuse=commercial, and highway=bus_stop.

    Returns:
        GeoDataFrame: A GeoDataFrame of OSM entities.
    """
    check_package("osmnx",
                  "https://osmnx.readthedocs.io/en/stable/#installation")
    import osmnx as ox

    gdf = ox.geometries_from_polygon(polygon, tags)
    return gdf
Beispiel #8
0
def get_buildings_fromOSM(place, download_method, epsg=None, distance=1000):
    """    
    The function downloads and cleans buildings footprint geometries and create a buildings GeoDataFrames for the area of interest.
    The function exploits OSMNx functions for downloading the data as well as for projecting it.
    The land use classification for each building is extracted. Only relevant columns are kept.   
            
    Parameters
    ----------
    place: string, tuple
        name of cities or areas in OSM: when using "from point" please provide a (lat, lon) tuple to create the bounding box around it; when using "distance_from_address"
        provide an existing OSM address; when using "OSMplace" provide an OSM place name
    download_method: string, {"from_point", "distance_from_address", "OSMplace"}
        it indicates the method that should be used for downloading the data.
    epsg: int
        epsg of the area considered; if None OSMNx is used for the projection
    distance: float
        Specify distance from address or point
    
    Returns
    -------
    buildings_gdf: Polygon GeoDataFrame
        the buildings GeoDataFrame
    """

    columns_to_keep = [
        'amenity', 'building', 'geometry', 'historic', 'land_use_raw'
    ]

    if download_method == "distance_from_address":
        buildings_gdf = ox.geometries_from_address(address=place,
                                                   dist=distance,
                                                   tags={"building": True})
    elif download_method == "OSMplace":
        buildings_gdf = ox.geometries_from_place(place,
                                                 tags={"building": True})
    elif download_method == "from_point":
        buildings_gdf = ox.geometries_from_point(center_point=place,
                                                 dist=distance,
                                                 tags={"building": True})
    elif download_method == "OSMpolygon":
        buildings_gdf = ox.geometries_from_polygon(place,
                                                   tags={"building": True})
    else:
        raise downloadError(
            'Provide a download method amongst {"from_point", "distance_from_address", "OSMplace", "OSMpolygon}'
        )

    if epsg is None:
        buildings_gdf = ox.projection.project_gdf(buildings_gdf)
    else:
        crs = 'EPSG:' + str(epsg)
        buildings_gdf = buildings_gdf.to_crs(crs)

    buildings_gdf['land_use_raw'] = None
    for column in buildings_gdf.columns:
        if column.startswith('building:use:'):
            buildings_gdf.loc[pd.notnull(buildings_gdf[column]),
                              'land_use_raw'] = column[13:]
        if column not in columns_to_keep:
            buildings_gdf.drop(column, axis=1, inplace=True)

    buildings_gdf = buildings_gdf[~buildings_gdf['geometry'].is_empty]
    buildings_gdf['building'].replace('yes', np.nan, inplace=True)
    buildings_gdf['building'][
        buildings_gdf['building'].isnull()] = buildings_gdf['amenity']
    buildings_gdf['land_use_raw'][
        buildings_gdf['land_use_raw'].isnull()] = buildings_gdf['building']
    buildings_gdf['land_use_raw'][
        buildings_gdf['land_use_raw'].isnull()] = 'residential'

    buildings_gdf = buildings_gdf[['geometry', 'historic', 'land_use_raw']]
    buildings_gdf['area'] = buildings_gdf.geometry.area
    buildings_gdf = buildings_gdf[buildings_gdf['area'] >= 50]

    # reset index
    buildings_gdf = buildings_gdf.reset_index(drop=True)
    buildings_gdf['buildingID'] = buildings_gdf.index.values.astype('int')

    return buildings_gdf