In a large parcel map, features are edited and need to be re-styled. I want to keep as much of the cache as possible, but invalidate the cache for features that are edited when the features are saved.

In order to do this, I need some way of determining which tiles (at all zoom levels) contain the feature.

Assuming my features are in PostGIS and served up in Leaflet, what are some ways to determine that intersection?


I would try to use the tilestache-seed.py script:


You can get the bounds of your parcel (which units depend on the units of your data) and pass it into the script.

use the '-x', '--ignore-cached' options to force the tiles to be regenerated.

Since your data is coming from postgres you should be able to do a query like this (from my US States Table):

SELECT ST_EXTENT( wkb_geometry ) FROM ( 
    SELECT ST_ENVELOPE( wkb_geometry ) as wkb_geometry 
        FROM US_States where state_name = 'California'  
) as extent

The answer is indeed located inside tilestache-seed.py. Since I need to trigger the cache invalidation whenever a feature is updated, I needed to extract the juicy bits. So now on post-save I pass the features to this method:

def invalidate_feature_cache(layer, features):
    invaldiates the cached tiles that contain the features
    @:param features: array of feature objects
    # get bbox of features

    lon1, lat1, lon2, lat2 = features.extent()
    south, west = min(lat1, lat2), min(lon1, lon2)
    north, east = max(lat1, lat2), max(lon1, lon2)
    northwest = Location(north, west)
    southeast = Location(south, east)

    osm = Provider()

    ul = osm.locationCoordinate(northwest)
    lr = osm.locationCoordinate(southeast)

    # get tiles from bbox and invalidate them
    config = TileStache.parseConfigfile(settings.TILESTACHE_CONFIG)

    layer_key = layer.id
    logger.info("\t\t\tInvalidating layer_key %s" % layer_key)
    ts_layer = config.layers[layer_key]
    for coord in generateCoordinates(ul, lr, range(4, 19), padding=0):
        config.cache.unlock(ts_layer, coord, 'png')
        config.cache.remove(ts_layer, coord, 'png')

and here is the generateCoordinates from tilestache-seed:

def generateCoordinates(ul, lr, zooms, padding):
    """ Generate a stream of coordinates for seeding.

        Flood-fill coordinates based on two corners, a list of zooms and padding.
    offset = 0
    for zoom in zooms:
        ul_ = ul.zoomTo(zoom).container().left(padding).up(padding)
        lr_ = lr.zoomTo(zoom).container().right(padding).down(padding)

    for row in range(int(ul_.row), int(lr_.row + 1)):
        for column in range(int(ul_.column), int(lr_.column + 1)):
            coord = Coordinate(row, column, zoom)

            yield coord
            offset += 1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.