def get_rtree(geometries, fp): fp = fp.as_posix() if not os.path.exists(fp + '.idx'): # Populate R-tree index with bounds of geometries print('Populate {} tree'.format(fp)) idx = Index(fp) for i, geo in enumerate(geometries): idx.insert(i, geo.bounds) idx.close() return {'rtree': Index(fp), 'geometries': geometries}
class SpatialIndex(): """ A spatial index is a type of extended index that allows you to index a spatial column. A spatial column is a table column that contains data of a spatial data type. Spatial indexes help to improve spatial query performance on a dataframe. Identifying a feature, selecting features, and joining data all have better performace when using spatial indexing. ==================== ================================================== Arguement Description -------------------- -------------------------------------------------- stype Required String. This sets the type of spatial index being used by the user. The current types of spatial indexes are: custom, rtree and quadtree. -------------------- -------------------------------------------------- bbox Optional Tuple. The extent of the spatial data as: (xmin, ymin, xmax, ymax). This parameter is required if a QuadTree Spatial Index is being used. Example: bbox=(-100, -50, 100, 50) -------------------- -------------------------------------------------- filename Optional String. The name of the spatial index file. This is only supported by rtree spatial indexes. For large datasets an rtree index can be saved to disk and used at a later time. If this is not provided the r-tree index will be in-memory. -------------------- -------------------------------------------------- custom_index Optional Object. Sometimes QuadTree and Rtree indexing is not enough. A custom spatial index class can be giving to the SpatialIndex class and used using encapsulation. The custom index must have two methods: `intersect` that excepts a tuple, and `insert` which must accept an oid and a bounding box. This object is required when `stype` of 'custom' is specified. ==================== ================================================== """ _stype = None _bbox = None _index = None _df = None #---------------------------------------------------------------------- def __init__(self, stype, bbox=None, **kwargs): """initializer""" ci = kwargs.pop('custom_index', None) self._filename = kwargs.pop('filename', None) self._bbox = bbox self._stype = stype.lower() self._df = None if ci and stype.lower() == 'custom': self._index = ci elif stype.lower() == 'quadtree' and bbox: self._index = QIndex(bbox=bbox) elif RIndex and stype.lower() == 'rtree': self._index = RIndex(self._filename) else: raise ValueError("Could not create the spatial index.") #---------------------------------------------------------------------- def intersect(self, bbox): """ Returns the spatial features that intersect the bbox :bbox: tuple - (xmin,ymin,xmax,ymax) :returns: list """ if self._stype.lower() in ['rtree']: return list(self._index.intersection(bbox)) elif self._stype.lower() in ['quadtree']: return list(self._index.intersect(bbox=bbox)) else: return list(self._index.intersect(bbox)) #---------------------------------------------------------------------- def insert(self, oid, bbox): """ Inserts the entry into the spatial index :oid: unique id :bbox: tuple - (xmin,ymin,xmax,ymax) """ if self._index is None: raise Exception(("Could not insert into a spatial index because " "it does not exist.")) if self._stype == 'rtree' and \ HASRTREE and \ isinstance(self._index, RIndex): r = self._index.insert(id=oid, coordinates=bbox, obj=None) self.flush() return r elif self._stype.lower() == 'quadtree': return self._index.insert(item=oid, bbox=bbox) elif self._stype.lower() == 'custom': r = self._index.intersect(oid, bbox) self.flush() return r #---------------------------------------------------------------------- def flush(self): """ Saves the index to disk if a filename is given for an R-Tree Spatial Index. **This applies only to the R-Tree implementation of the spatial index.** :returns: Boolean """ if hasattr(self._index, 'flush'): getattr(self._index, 'flush')() elif self._stype == 'rtree' and \ self._filename: self._index.close() self._index = RIndex(self._filename) else: return False return True
# In[2]: osm_land_use_idx = osm_land_use.sindex # osm_roads_idx = osm_roads.sindex # osm_waterways_idx = osm_waterways.sindex # osm_water_idx = osm_water.sindex # osm_traffic_idx = osm_traffic.sindex # osm_transport_idx = osm_transport.sindex # acled_idx = acled.sindex idx = Index("./index/osm_land_use_idx") print("here") for i, k in list(osm_land_use_idx): idx.insert(i, k) idx.close() print("Done with osm_land_use_idx") # idx = Index("./index/osm_roads_idx") # idx.insert(osm_roads_idx) # idx.close() # print("Done with osm_roads_idx") # idx = Index("./index/osm_waterways_idx") # idx.insert(osm_waterways_idx) # idx.close() # print("Done with osm_waterways_idx") # idx = Index("./index/osm_water_idx") # idx.insert(osm_water_idx) # idx.close()
class RectIndex(object): """A R-tree that stores all tracks on a layer.""" def __init__(self, resolution, basename=None, overwrite=False): # type: (float) -> None self._res = resolution self._cnt = 0 if basename is None: self._index = Index(interleaved=True) else: p = Property(overwrite=overwrite) self._index = Index(basename, interleaved=True, properties=p) @property def bound_box(self): # type: () -> BBox xl, yb, xr, yt = self._index.bounds return BBox(int(xl), int(yb), int(xr), int(yt), self._res, unit_mode=True) def close(self): self._index.close() def record_box(self, box, dx, dy): # type: (BBox, int, int) -> None """Record the given BBox.""" sp_box = box.expand(dx=dx, dy=dy, unit_mode=True) bnds = sp_box.get_bounds(unit_mode=True) obj = (box.left_unit, box.bottom_unit, box.right_unit, box.top_unit, dx, dy) self._index.insert(self._cnt, bnds, obj=obj) self._cnt += 1 def rect_iter(self): # type: () -> Generator[Tuple[BBox, int, int], None, None] for xl, yb, xr, yt, sdx, sdy in self._index.intersection( self._index.bounds, objects='raw'): box_real = BBox(xl, yb, xr, yt, self._res, unit_mode=True) yield box_real, sdx, sdy def intersection_iter(self, box, dx=0, dy=0): # type: (BBox, int, int) -> Generator[BBox, None, None] """Finds all bounding box that intersects the given box.""" res = self._res test_box = box.expand(dx=dx, dy=dy, unit_mode=True) box_iter = self._index.intersection( test_box.get_bounds(unit_mode=True), objects='raw') for xl, yb, xr, yt, sdx, sdy in box_iter: box_real = BBox(xl, yb, xr, yt, res, unit_mode=True) box_sp = box_real.expand(dx=sdx, dy=sdy, unit_mode=True) if box_sp.overlaps(box) or test_box.overlaps(box_real): yield box_real.expand(dx=max(dx, sdx), dy=max(dy, sdy), unit_mode=True) def intersection_rect_iter(self, box): # type: (BBox) -> Generator[BBox, None, None] """Finds all bounding box that intersects the given box.""" res = self._res box_iter = self._index.intersection(box.get_bounds(unit_mode=True), objects='raw') for xl, yb, xr, yt, sdx, sdy in box_iter: yield BBox(xl, yb, xr, yt, res, unit_mode=True)