[Tilecache] Virtual Earth compatible TC-cache

Steven M. Ottens steven at minst.net
Fri Feb 8 11:01:44 EST 2008


Hi all,

For those lost souls who want to create a cache which is directly 
compatible with the virtual earth client I've attached a modified 
disk.py, renamed to VE.py. It is written for TC 2.01 and should be put 
in the <tilecache>/Cache folder.

Some information on the VE compatible cache structure:
http://msdn2.microsoft.com/en-us/library/bb259689.aspx

This VE cache is a flat file structure, which means that you need a 
filesystem that can handle thousands of files in a directory. To be 
honest the only reason why you would want to do this is so you can 
directly add a dataset in virtualearth using the new 
VETileSourceSpecification
 and have the files available in a web-accessible directory. The next 
step will be to add a VE layer so you can use tilecache to dynamically 
generate the VE-tiles.

The reason why you want to create VE-specific tiles is to be able to 
view them in 3D (inside the VE viewer).

Regards,
Steven
-------------- next part --------------
# BSD Licensed, Copyright (c) 2006-2007 MetaCarta, Inc.

from TileCache.Cache import Cache
import sys, os, time

class VE (Cache):
    def __init__ (self, base = None, umask = '002', **kwargs):
        Cache.__init__(self, **kwargs)
        self.basedir = base
        self.umask = int(umask, 0)
        
        if sys.platform.startswith("java"):
            from java.io import File
            self.file_module = File
            self.platform = "jython"
        else:
            self.platform = "cpython"
        
        if not self.access(base, 'read'):
            self.makedirs(base)
        
    def makedirs(self, path):
        old_umask = os.umask(self.umask)
        os.makedirs(path)
        os.umask(old_umask)
        
    def access(self, path, type='read'):
        if self.platform == "jython":
            if type == "read":
                return self.file_module(path).canRead()
            else:
                return self.file_module(path).canWrite()
        else:
            if type =="read":
                return os.access(path, os.R_OK)
            else:
                return os.access(path, os.W_OK)

    def getKey (self, tile):
        components = ( self.basedir,
                       tile.layer.name,
                       "%s.%s" % (self.quad(tile),tile.layer.extension)
                    )
        filename = os.path.join( *components )
        return filename

    def quad (self, tile):
        quadKey = ''
        for i in range (tile.z, 0, -1):
              digit = 0
              mask = 1 << (i -1 )
              if (tile.x & mask) != 0:
                    digit=digit+1
              if (tile.y & mask) !=0:
                    digit=digit+2
              quadKey = quadKey + str(digit)
        return quadKey

    def get (self, tile):
        filename = self.getKey(tile)
        if self.access(filename, 'read'):
            tile.data = file(filename, "rb").read()
            return tile.data
        else:
            return None

    def set (self, tile, data):
        if self.readonly: return data
        filename = self.getKey(tile)
        dirname  = os.path.dirname(filename)
        if not self.access(dirname, 'write'):
            self.makedirs(dirname)
        tmpfile = filename + ".%d.tmp" % os.getpid()
        old_umask = os.umask(self.umask)
        output = file(tmpfile, "wb")
        output.write(data)
        output.close()
        os.umask( old_umask );
        try:
            os.rename(tmpfile, filename)
        except OSError:
            os.unlink(filename)
            os.rename(tmpfile, filename)
        tile.data = data
        return data
    
    def delete (self, tile):
        filename = self.getKey(tile)
        if self.access(filename, 'read'):
            os.unlink(filename)
            
    def attemptLock (self, tile):
        name = self.getLockName(tile)
        try: 
            self.makedirs(name)
            return True
        except OSError:
            pass
        try:
            st = os.stat(name)
            if st.st_ctime + self.stale < time.time():
                warnings.warn("removing stale lock %s" % name)
                # remove stale lock
                self.unlock()
                self.makedirs(name)
                return True
        except OSError:
            pass
        return False 
     
    def unlock (self, tile):
        name = self.getLockName(tile)
        try:
            os.rmdir(name)
        except OSError, E:
            print >>sys.stderr, "unlock %s failed: %s" % (name, str(E))


More information about the Tilecache mailing list