Пример #1
0
def create_s2_geom_cells(extent, resolutions):


    # Create s2 rectangle to fill with s2 cells
    region_rect = s2.S2LatLngRect(
        s2.S2LatLng.FromDegrees(extent.bounds[1], extent.bounds[0]),
        s2.S2LatLng.FromDegrees(extent.bounds[3], extent.bounds[2]))
    coverer = s2.S2RegionCoverer()

    # Projection for cell area calculation
    transformer = Transformer.from_crs("epsg:4326", 'proj=isea')

    # Iterate through given resolutions, create and populate geopandas for each
    for r in resolutions:
        coverer.min_level = r
        coverer.max_level = r
        covering = coverer.GetCovering(region_rect)
        geoms = gpd.GeoDataFrame()
        geoms['cell_id'] = None
        geoms['area'] = None
        geoms['geometry'] = None
        for cellid in covering:
            new_cell = s2.S2Cell(cellid)
            vertices = []
            for i in range(0, 4):
                vertex = new_cell.GetS2LatLngVertex(i)
                vertices.append((vertex.lng().degrees,
                                 vertex.lat().degrees))
            geom = Polygon(vertices)
            geoms.loc[len(geoms)] = [cellid.get, transform(transformer.transform, geom).area, geom]

        geoms.to_file("s2_level{}.geojson".format(r), driver='GeoJSON')
Пример #2
0
def get_s2_cells(res, extent=None):
    """Get s2 cells for given resolution

    Parameters:
    res (int): S2 resolution 
    extent (list): Extent as array of 2 lon lat pairs to get raster values for
    Returns:
    Pandas dataframe
   """

    coverer = s2.S2RegionCoverer()
    if extent:
        coverer.set_fixed_level(res)
        region_rect = s2.S2LatLngRect(
        s2.S2LatLng_FromDegrees(extent[1], extent[0]),
        s2.S2LatLng_FromDegrees(extent[3], extent[2]))
        set_hex = [x.ToToken() for x in coverer.GetCovering(region_rect)]

    else:
        coverer.set_fixed_level(res)
        region_rect = s2.S2LatLngRect(
        s2.S2LatLng_FromDegrees(-90, -180),
        s2.S2LatLng_FromDegrees(90, 180))
        set_hex = [x.ToToken() for x in coverer.GetCovering(region_rect)]

    df = pd.DataFrame({"cell_id": set_hex})
    
    return df
Пример #3
0
 async def level_12_covering(self):
     cap = await self.s2_cap()
     if not cap:
         return None
     coverer = s2.S2RegionCoverer()
     coverer.set_fixed_level(12)
     covering = coverer.GetCovering(cap)
     id_list = [hex(x.id()) for x in covering]
     return id_list
 def cover_region(self, feature):
     # Cover a feature's extent with S2 cells
     xcoords = [x[0] for x in feature['geometry']['coordinates'][0]]
     ycoords = [y[1] for y in feature['geometry']['coordinates'][0]]
     rect = s2.S2LatLngRect(
         s2.S2LatLng.FromDegrees(min(ycoords), min(xcoords)),
         s2.S2LatLng.FromDegrees(max(ycoords), max(xcoords)))
     coverer = s2.S2RegionCoverer()
     coverer.set_max_cells(self.config.limit)
     coverer.set_min_level(self.config.min_res)
     coverer.set_max_level(self.config.max_res)
     ids = coverer.GetCovering(rect)
     return ids
Пример #5
0
def cover_rect(lat1, long1, lat2, long2):
    # create a rect in !!!!!
    region_rect = s2.S2LatLngRect(s2.S2LatLng.FromDegrees(lat1, long1),
                                  s2.S2LatLng.FromDegrees(lat2, long2))

    # ask s2 to create a cover of this rect
    coverer = s2.S2RegionCoverer()
    coverer.set_min_level(10)
    coverer.set_max_level(30)
    coverer.set_max_cells(60)
    covering = coverer.GetCovering(region_rect)
    res = [c.ToToken() for c in covering]

    return {"total": len(res), "cellIDs": res}
Пример #6
0
 def testCovererIsWrappedCorrectly(self):
   london = s2.S2LatLngRect(s2.S2LatLng.FromDegrees(51.3368602, 0.4931979),
                            s2.S2LatLng.FromDegrees(51.7323965, 0.1495211))
   e14lj = s2.S2LatLngRect(s2.S2LatLng.FromDegrees(51.5213527, -0.0476026),
                           s2.S2LatLng.FromDegrees(51.5213527, -0.0476026))
   coverer = s2.S2RegionCoverer()
   coverer.set_max_cells(6)
   self.assertEqual(6, coverer.max_cells())
   covering = coverer.GetCovering(e14lj)
   self.assertLessEqual(len(covering), 6)
   for cellid in covering:
     self.assertTrue(london.Contains(s2.S2Cell(cellid)))
   interior = coverer.GetInteriorCovering(e14lj)
   for cellid in interior:
     self.assertTrue(london.Contains(s2.S2Cell(cellid)))
Пример #7
0
def vector_to_s2(vector_path, value_name, resolution, extent=None, layer=None):
    """Load vector values into s2 dggs cells

    Parameters:
    vector_path (string): path to vector file for uploading
    value_name (string): name of a vector attribute to be uploaded
    resolution (integer): s2 resolution to load vector values into
    extent (list): Extent as array of 2 lat lon pairs to get vector values for

    Returns:
    Pandas dataframe
   """
    # Open vector to geodataframe
    gdf = gpd.read_file(vector_path, layer)

    # Get extent to fill with s2 squares
    if extent:
        region_rect = s2.S2LatLngRect(
            s2.S2LatLng_FromDegrees(extent[1], extent[0]),
            s2.S2LatLng_FromDegrees(extent[3], extent[2]))
    else:
        region_rect = s2.S2LatLngRect(
            s2.S2LatLng_FromDegrees(gdf['geometry'].total_bounds[1], gdf['geometry'].total_bounds[0]),
            s2.S2LatLng_FromDegrees(gdf['geometry'].total_bounds[2], gdf['geometry'].total_bounds[3]))

    coverer = s2.S2RegionCoverer()
    coverer.set_fixed_level(resolution)

    # Create dataframe with cell_ids from cover with given resolution
    print(f"Start filling raster extent with s2 indexes at resolution {resolution}")
    s2_gdf = gpd.GeoDataFrame({'cell_id': [x.ToToken() for x in coverer.GetCovering(region_rect)]})

    # Get hex centroids for points
    s2_gdf['geometry'] = s2_gdf['cell_id'].apply(
        lambda x: Point(s2.S2CellId.FromToken(x,len(x)).ToLatLng().lng().degrees(), s2.S2CellId.FromToken(x,len(x)).ToLatLng().lat().degrees()))
    s2_gdf = s2_gdf.set_crs('epsg:4326')

    # Spatial join hex centroids with gdf
    vector_s2 = gpd.sjoin(s2_gdf, gdf)

    # Drop unnecessary fields
    vector_s2 = vector_s2[['cell_id', value_name]]

    return vector_s2
Пример #8
0
    def _randomCaps(self, query_type, **indexer_options):
        # This function creates an index consisting either of points (if
        # options.index_contains_points_only() is true) or S2Caps of random size.
        # It then executes queries consisting of points (if query_type == POINT)
        # or S2Caps of random size (if query_type == CAP).
        #
        # indexer_options are set on both the indexer & coverer (if relevant)
        # eg. _randomCaps('cap', min_level=0) calls indexer.set_min_level(0)
        ITERATIONS = 400

        indexer = s2.S2RegionTermIndexer()
        coverer = s2.S2RegionCoverer()

        # set indexer options
        for opt_key, opt_value in indexer_options.items():
            setter = "set_%s" % opt_key
            getattr(indexer, setter)(opt_value)
            if hasattr(coverer, setter):
                getattr(coverer, setter)(opt_value)

        caps = []
        coverings = []
        index = defaultdict(set)

        index_terms = 0
        query_terms = 0
        for i in range(ITERATIONS):
            # Choose the region to be indexed: either a single point or a cap
            # of random size (up to a full sphere).
            terms = []
            if indexer.index_contains_points_only():
                cap = s2.S2Cap.FromPoint(s2.S2Testing.RandomPoint())
                terms = indexer.GetIndexTerms(cap.center(), "")
            else:
                cap = s2.S2Testing.GetRandomCap(
                    0.3 * s2.S2Cell.AverageArea(indexer.max_level()),
                    4.0 * s2.S2Cell.AverageArea(indexer.min_level()))
                terms = indexer.GetIndexTerms(cap, "")

            caps.append(cap)
            coverings.append(s2.S2CellUnion(coverer.GetCovering(cap)))
            for term in terms:
                index[term].add(i)

            index_terms += len(terms)

        for i in range(ITERATIONS):
            # Choose the region to be queried: either a random point or a cap of
            # random size.
            terms = []

            if query_type == 'cap':
                cap = s2.S2Cap.FromPoint(s2.S2Testing.RandomPoint())
                terms = indexer.GetQueryTerms(cap.center(), "")
            else:
                cap = s2.S2Testing.GetRandomCap(
                    0.3 * s2.S2Cell.AverageArea(indexer.max_level()),
                    4.0 * s2.S2Cell.AverageArea(indexer.min_level()))
                terms = indexer.GetQueryTerms(cap, "")

            # Compute the expected results of the S2Cell query by brute force.
            covering = s2.S2CellUnion(coverer.GetCovering(cap))
            expected, actual = set(), set()
            for j in range(len(caps)):
                if covering.Intersects(coverings[j]):
                    expected.add(j)

            for term in terms:
                actual |= index[term]

            self.assertEqual(expected, actual)
            query_terms += len(terms)

            print("Index terms/doc: %0.2f, Query terms/doc: %0.2f" %
                  (float(index_terms) / ITERATIONS,
                   float(query_terms) / ITERATIONS))
Пример #9
0
def raster_to_s2(raster_path, value_name, cell_min_res, cell_max_res, extent=None, pix_size_factor=3):
    """Load raster values into s2 dggs cells

    Parameters:
    raster (string): path to raster file for uploading
    value_name (string): name of a value to be uploaded
    cell_min_res (integer): min h3 resolution to look for based on raster cell size
    cell_max_res (integer): max h3 resolution to look for based on raster cell size
    extent (list): Extent as array of 2 lon lat pairs to get raster values for
    pix_size_factor (pinteger): how times smaller h3 hex size should be comparing with raster cell size

    Returns:
    Pandas dataframe
   """
    # Open raster
    rs = rasterio.open(raster_path)

    # Get extent to fill with s2 squares
    if extent:
        region_rect = s2.S2LatLngRect(
            s2.S2LatLng_FromDegrees(extent[1], extent[0]),
            s2.S2LatLng_FromDegrees(extent[3], extent[2]))
    else:
        region_rect = s2.S2LatLngRect(
            s2.S2LatLng_FromDegrees(rs.bounds.bottom, rs.bounds.left),
            s2.S2LatLng_FromDegrees(rs.bounds.top, rs.bounds.right))

    # Get resolution dict
    resolutions = {}
    coverer = s2.S2RegionCoverer()
    # transformer = Transformer.from_crs("epsg:4326", 'proj=isea')
    for i in range(cell_min_res, cell_max_res, 1):
        # get s2 cell at level i
        coverer.set_fixed_level(i)
        cell = s2.S2Cell(coverer.GetCovering(region_rect)[0])

        # get s2 edge size at resolution i
        p1 = cell.GetS2LatLngVertex(0)
        p2 = cell.GetS2LatLngVertex(1)
        # edge = Point(transformer.transform(p2.lat().degrees(), p2.lng().degrees())).distance(Point(transformer.transform(p1.lat().degrees(), p2.lng().degrees())))
        edge = __haversine(p2.lat().degrees(), p2.lng().degrees(), p1.lat().degrees(), p2.lng().degrees())

        resolutions[i] = edge

    # Get two neighbour pixels in raster
    x1 = rs.transform[2]
    y1 = rs.transform[5]
    x2 = rs.transform[2] + rs.transform[0]
    y2 = rs.transform[5] - rs.transform[4]

    # Get pixel size from projected src
    size = __haversine(x1, y1, x1, y2)

    print(f"Raster pixel size {size}")

    # Get raster band as np array
    raster_band_array = rs.read(1)

    # Get h3 resolution for raster pixel size
    for key, value in resolutions.items():
        print(value)
        if value < size / pix_size_factor:
            resolution = key
            break
    print(resolution)

    coverer.set_fixed_level(resolution)

    # Create dataframe with cell_ids from cover with given resolution
    print(f"Start filling raster extent with s2 indexes at resolution {resolution}")
    df = pd.DataFrame({'cell_id': [x.ToToken() for x in coverer.GetCovering(region_rect)]})

    # Get raster values for each hex_id
    print(f"Start getting raster values for s2 cells at resolution {resolution}")
    df[value_name] = df['cell_id'].apply(lambda x: raster_band_array[
        rs.index(s2.S2CellId.FromToken(x,len(x)).ToLatLng().lng().degrees(), s2.S2CellId.FromToken(x,len(x)).ToLatLng().lat().degrees())])

    # Drop nodata
    df = df[df[value_name] != rs.nodata]

    return df