Example #1
0
    def load_files(self, *files: List[Path], verbose: bool = False):
        files = [Path(file) for file in files]
        if verbose:
            from tqdm import tqdm
            files = tqdm(files, desc="RoadEngine Load")
        for file in files:
            if not file.exists():
                raise FileNotFoundError(f"Could not load {file.absolute()}!")
            gdf = gpd.read_file(file.absolute())
            self.cache = self.cache.append(gdf, ignore_index=True, sort=False)

        tileset = set()
        geometry = gdf['geometry']
        if verbose:
            geometry = tqdm(geometry, desc="RoadEngine Quadtree")
        for geom in geometry:
            if type(geom) != LineString:
                continue
            root = bounding_tile(*geom.bounds)
            tileset |= {root}
        self.cached_tiles |= set(simplify(*tileset))
        if verbose:
            logger.info("RoadEngine is building an R-Tree...")
        self.cache.sindex
        if verbose:
            logger.info("RoadEngine R-Tree done!")
Example #2
0
 def __get_from_osmnx(self, tile: Tile) -> gpd.GeoDataFrame:
     bbox: LngLatBbox = bounds(tile)
     west, south, east, north = bbox
     west -= LAT_LNG_BUFFER
     east += LAT_LNG_BUFFER
     north += LAT_LNG_BUFFER
     south -= LAT_LNG_BUFFER
     try:
         graph = ox.graph_from_bbox(north,
                                    south,
                                    east,
                                    west,
                                    simplify=False,
                                    retain_all=True)
         gdfs = ox.graph_to_gdfs(graph)
         for gdf in gdfs:
             self.cache = self.cache.append(gdf,
                                            ignore_index=True,
                                            sort=False)
     except ox.core.EmptyOverpassResponse:
         pass
     except ValueError as e:
         if "not enough values" in str(e):
             print(
                 f"[WARNING] Could not load tile {tile}! Assuming it is empty..."
             )
         else:
             raise e
     self.cached_tiles |= {tile}
     self.cached_tiles = set(simplify(*self.cached_tiles))
     return self.__get_from_cache(tile)
Example #3
0
def quadkeys_to_poly(quadkeys):
    quadkeys = sorted(set(quadkeys))
    tiles = [mercantile.quadkey_to_tile(qk) for qk in quadkeys]
    tiles = mercantile.simplify(tiles)
    quadkeys = [mercantile.quadkey(t) for t in tiles]
    polys = quadkeys_to_polys(quadkeys)
    poly = shapely.ops.unary_union(polys)
    return poly
Example #4
0
def test_simplify_removal():
    ''' Verify that tiles are being removed by simplify()
    '''
    tiles = [
        (1298, 3129, 13),
        (649, 1564, 12),
        (650, 1564, 12),
    ]
    simplified = mercantile.simplify(tiles)
    assert (1298, 3129, 13) not in simplified, 'Tile covered by a parent'
    assert (650, 1564, 12) in simplified, 'Highest-level tile'
    assert (649, 1564, 12) in simplified, 'Also highest-level tile'
def test_simplify():
    children = mercantile.children(243, 166, 9, zoom=12)
    assert len(children) == 64
    children = children[:-3]
    children.append(children[0])
    simplified = mercantile.simplify(children)
    targets = [
        (487, 332, 10),
        (486, 332, 10),
        (487, 333, 10),
        (973, 667, 11),
        (973, 666, 11),
        (972, 666, 11),
        (1944, 1334, 12),
    ]
    for target in targets:
        assert target in simplified
def missing_quadkeys(mosaic: Dict,
                     shp_path: str,
                     bounds: List[float] = None,
                     simplify: bool = True) -> Dict:
    """Find quadkeys over land missing from mosaic

    Args:
        - mosaic: mosaic definition
        - shp_path: path to Natural Earth shapefile of land boundaries
        - bounds: force given bounds
        - simplify: reduce size of the tileset as much as possible by merging leaves into parents

    Returns:
        - GeoJSON FeatureCollection of missing tiles
    """
    bounds = bounds or mosaic['bounds']
    top_tile = mercantile.bounding_tile(*bounds)
    gdf = gpd.read_file(shp_path)
    quadkey_zoom = mosaic.get('quadkey_zoom', mosaic['minzoom'])

    # Remove null island
    # Keep the landmasses that are visible at given zoom
    gdf = gdf[gdf['max_zoom'] <= quadkey_zoom]

    land_tiles = find_child_land_tiles(top_tile, gdf, quadkey_zoom)
    quadkeys = {mercantile.quadkey(tile) for tile in land_tiles}

    mosaic_quadkeys = set(mosaic['tiles'].keys())
    not_in_mosaic = quadkeys.difference(mosaic_quadkeys)
    not_in_mosaic = [mercantile.quadkey_to_tile(qk) for qk in not_in_mosaic]

    if simplify:
        not_in_mosaic = mercantile.simplify(not_in_mosaic)

    features = [mercantile.feature(tile) for tile in not_in_mosaic]

    return {'type': 'FeatureCollection', 'features': features}