예제 #1
0
    def create(self):
        def callback(counter, result):
            if not counter % 10000:
                logger.info('counter: %s' % counter)
                logger.info('result: %s' % result)

        self.t0 = time.time()

        tilecount.value = 0
        skipcount.value = 0

        tiles = TerrainTiles(self.dbConfigFile, self.tmsConfig, self.t0)
        procfactor = int(self.tmsConfig.get('General', 'procfactor'))

        pm = PoolManager(factor=procfactor)
        maxChunks = int(self.tmsConfig.get('General', 'maxChunks'))

        nbTiles = self.numOfTiles()
        tilesPerProc = int(nbTiles / pm.nbOfProcesses)
        if tilesPerProc < maxChunks:
            maxChunks = tilesPerProc
        if maxChunks < 1:
            maxChunks = 1

        logger.info('Starting creation of %s tiles (%s per chunk)' %
                    (nbTiles, maxChunks))
        pm.imap_unordered(createTile, tiles, maxChunks, callback=callback)

        tend = time.time()
        logger.info('It took %s to create %s tiles (%s were skipped)' %
                    (str(datetime.timedelta(seconds=tend - self.t0)),
                     tilecount.value, skipcount.value))
예제 #2
0
    def create(self):
        self.t0 = time.time()

        tilecount.value = 0
        skipcount.value = 0

        tiles = TerrainTiles(self.dbConfigFile, self.tmsConfig, self.t0)
        procfactor = int(self.tmsConfig.get('General', 'procfactor'))

        pm = PoolManager(logger=logger, factor=procfactor)

        maxChunks = int(self.tmsConfig.get('General', 'maxChunks'))

        nbTiles = self.numOfTiles()
        tilesPerProc = int(nbTiles / pm.numOfProcesses())
        if tilesPerProc < maxChunks:
            maxChunks = tilesPerProc
        if maxChunks < 1:
            maxChunks = 1

        logger.info('Starting creation of %s tiles (%s per chunk)' %
                    (nbTiles, maxChunks))
        pm.process(tiles, createTile, maxChunks)

        tend = time.time()
        logger.info('It took %s to create %s tiles (%s were skipped)' %
                    (str(datetime.timedelta(seconds=tend - self.t0)),
                     tilecount.value, skipcount.value))
예제 #3
0
    def _stats(self, withDb=True):
        self.t0 = time.time()
        total = 0

        msg = '\n'
        tiles = TerrainTiles(self.dbConfigFile, self.tmsConfig, self.t0)
        geodetic = getTileGrid(4326)(tmsCompatible=True)
        bounds = (tiles.minLon, tiles.minLat, tiles.maxLon, tiles.maxLat)
        zooms = range(tiles.tileMinZ, tiles.tileMaxZ + 1)

        db = DB('configs/terrain/database.cfg')
        try:
            with db.userSession() as session:
                for i in xrange(0, len(zooms)):
                    zoom = zooms[i]
                    model = modelsPyramid.getModelByZoom(zoom)
                    nbObjects = None
                    if withDb:
                        nbObjects = session.query(model).filter(
                            model.bboxIntersects(bounds)).count()
                    # top letf corner
                    tileMinX, tileMinY = geodetic.tileAddress(
                        zoom, [bounds[0], bounds[3]])
                    # bottom right
                    tileMaxX, tileMaxY = geodetic.tileAddress(
                        zoom, [bounds[2], bounds[1]])
                    tileBounds = geodetic.tileBounds(zoom, tileMinX, tileMinY)
                    xCount = tileMaxX - tileMinX + 1
                    yCount = tileMaxY - tileMinY + 1
                    nbTiles = xCount * yCount
                    total += nbTiles
                    pointA = transformCoordinate(
                        'POINT(%s %s)' % (tileBounds[0], tileBounds[1]), 4326,
                        21781).GetPoints()[0]
                    pointB = transformCoordinate(
                        'POINT(%s %s)' % (tileBounds[2], tileBounds[3]), 4326,
                        21781).GetPoints()[0]
                    length = int(round(c2d.distance(pointA, pointB)))
                    msg += 'At zoom %s:\n' % zoom
                    msg += 'We expect %s tiles overall\n' % nbTiles
                    msg += 'Min X is %s, Max X is %s\n' % (tileMinX, tileMaxX)
                    msg += '%s columns over X\n' % xCount
                    msg += 'Min Y is %s, Max Y is %s\n' % (tileMinY, tileMaxY)
                    msg += '%s rows over Y\n' % yCount
                    msg += '\n'
                    msg += 'A tile side is around %s meters' % length
                    if nbTiles > 0 and nbObjects is not None:
                        msg += 'We have an average of about %s triangles ' \
                               'per tile\n' % int(round(nbObjects / nbTiles))
                    msg += '\n\n'
            msg += '%s tiles in total.' % total
        except Exception as e:
            logger.error('An error occured during statistics collection')
            logger.error('%s' % e, exc_info=True)
            raise Exception(e)
        finally:
            db.userEngine.dispose()

        return (total, msg)
예제 #4
0
    def populateLakes(self):
        self.setupDatabase()
        logger.info('Action: populateLakes()')

        # For now we never reproject lakes
        with self.userSession() as session:
            shpFile = self.config.get('Data', 'lakes')

            if not os.path.exists(shpFile):
                logger.error('Shapefile %s does not exists' % (shpFile))
                sys.exit(1)

            count = 1
            shp = ShpToGDALFeatures(shpFile)
            logger.info('Processing %s' % (shpFile))
            bulk = BulkInsert(Lakes, session, withAutoCommit=1000)

            for feature in shp.getFeatures():
                polygon = feature.GetGeometryRef()
                # Force 2D for lakes
                polygon.FlattenTo2D()
                # add shapefile path to dict
                # self.shpFilePath
                bulk.add(
                    dict(the_geom=WKTElement(polygon.ExportToWkt(), 4326)))
                count += 1
            bulk.commit()
            logger.info('Commit %s features for %s.' % (count, shpFile))
            # Once all features have been commited, start creating all
            # the simplified versions of the lakes
            logger.info('Simplifying lakes')
            tiles = TerrainTiles(self.dbConfigFile, tmsConfig, time.time())
            geodetic = GlobalGeodetic(True)
            bounds = (tiles.minLon, tiles.minLat, tiles.maxLon, tiles.maxLat)
            zooms = range(tiles.tileMinZ, tiles.tileMaxZ + 1)
            for i in xrange(0, len(zooms)):
                zoom = zooms[i]
                tablename = 'lakes_%s' % zoom
                tileMinX, tileMinY = geodetic.LonLatToTile(
                    bounds[0], bounds[1], zoom)
                tileMaxX, tileMaxY = geodetic.LonLatToTile(
                    bounds[2], bounds[3], zoom)
                tileBounds = geodetic.TileBounds(tileMinX, tileMinY, zoom)
                pointA = transformCoordinate(
                    'POINT(%s %s)' % (tileBounds[0], tileBounds[1]), 4326,
                    21781).GetPoints()[0]
                pointB = transformCoordinate(
                    'POINT(%s %s)' % (tileBounds[2], tileBounds[3]), 4326,
                    21781).GetPoints()[0]
                length = c2d.distance(pointA, pointB)
                pixelArea = pow(length, 2) / pow(256.0, 2)
                pixelLength = math.sqrt(pixelArea)
                session.execute(
                    create_simplified_geom_table(tablename, pixelLength))
                session.commit()
                logger.info('Commit table public.%s with %s meters '
                            'tolerance' % (tablename, pixelLength))
예제 #5
0
    def metadata(self):
        t0 = time.time()
        basePath = self.tmsConfig.get('General', 'bucketpath')
        baseUrls = []
        url = 'https://terrain.dev.bgdi.ch'
        url += '/%s{z}/{x}/{y}.terrain?v={version}' % basePath
        baseUrls.append(url)
        # TODO
        #for i in range(0, 5):
        #    url = 'https://terrain10%s.geo.admin.ch' % i
        #    url = 'https://terrain10%s.geo.admin.ch' % i
        #    url += '/%s{z}/{x}/{y}.terrain?v={version}' % basePath
        #    baseUrls.append(url)

        db = DB('configs/terrain/database.cfg')
        tiles = TerrainTiles(self.dbConfigFile, self.tmsConfig, t0)
        tMeta = TerrainMetadata(
            bounds=tiles.bounds,
            minzoom=tiles.tileMinZ,
            maxzoom=tiles.tileMaxZ,
            useGlobalTiles=True,
            hasLighting=tiles.hasLighting,
            hasWatermask=tiles.hasWatermask,
            baseUrls=baseUrls)

        try:
            with db.userSession() as session:
                tilecount = 1
                for tile in tiles:
                    tMeta = scanTerrain(tMeta, tile, session, tilecount)
                    tilecount += 1

                tend = time.time()
                logger.info('It took %s to scan %s tiles' % (
                    str(datetime.timedelta(seconds=tend - t0)), tilecount))
        except Exception as e:
            logger.error('An error occured during layer.json creation')
            logger.error('%s' % e, exc_info=True)
            raise Exception(e)
        finally:
            db.userEngine.dispose()

        with open('.tmp/layer.json', 'w') as f:
            f.write(tMeta.toJSON())
예제 #6
0
    def metadata(self):
        t0 = time.time()
        serverAddress = self.tmsConfig.get('General', 'serveraddress')
        basePath = self.tmsConfig.get('General', 'bucketpath')
        baseUrls = [
            serverAddress + basePath + "{z}/{x}/{y}.terrain?v={version}"
        ]

        db = DB('configs/terrain/database.cfg')
        tiles = TerrainTiles(self.dbConfigFile, self.tmsConfig, t0)
        tMeta = TerrainMetadata(bounds=tiles.bounds,
                                minzoom=tiles.tileMinZ,
                                maxzoom=tiles.tileMaxZ,
                                useGlobalTiles=True,
                                hasLighting=tiles.hasLighting,
                                hasWatermask=tiles.hasWatermask,
                                baseUrls=baseUrls)

        try:
            with db.userSession() as session:
                tilecount = 1
                for tile in tiles:
                    tMeta = scanTerrain(tMeta, tile, session, tilecount)
                    tilecount += 1

                tend = time.time()
                logger.info(
                    'It took %s to scan %s tiles' %
                    (str(datetime.timedelta(seconds=tend - t0)), tilecount))
        except Exception as e:
            logger.error('An error occured during layer.json creation')
            logger.error('%s' % e, exc_info=True)
            raise Exception(e)
        finally:
            db.userEngine.dispose()

        with open('.tmp/layer.json', 'w') as f:
            f.write(tMeta.toJSON())
예제 #7
0
    def createQueue(self):
        queueName = self.tmsConfig.get('General', 'sqsqueue')
        maxChunks = int(self.tmsConfig.get('General', 'maxChunks'))
        self.t0 = time.time()
        if len(queueName) <= 0:
            logger.error('Missing queueName')
            return
        try:
            sqs = getSQS()
            q = sqs.get_queue(queueName)
            if q is not None:
                logger.error('Queue already exists. Can\'t overwrite'
                             ' existing queue. [%s]' % (queueName))
                return

            # queue with default message visiblity time of 3600.
            # So each message is blocked for other users for 3600 seconds.
            # Default would be 30 seconds.
            # It's that high because each message contains maxChunks tiles
            q = sqs.create_queue(queueName,
                                 visibility_timeout=visibility_timeout)
            # Assure queue is kept for maximum of 14 weeks (aws limit).
            # default would be 4 days.
            sqs.set_queue_attribute(q, 'MessageRetentionPeriod', 1209600)
        except Exception as e:
            logger.error('Error during creation of queue:\n' + str(e),
                         exc_info=True)
            return

        if q.count() > 0:
            logger.error('Queue already contains messages. '
                         'Use a different queue or delete this queue first')
            return

        logger.info('Queue ' + queueName + ' has been created')
        tiles = TerrainTiles(self.dbConfigFile, self.tmsConfig, self.t0)
        nbTiles = self.numOfTiles()
        try:
            logger.info('Starting creation of SQS queue with approx. '
                        '%s tiles)' % (nbTiles))
            totalcount = 0
            tcount = 0
            messagecount = 0
            msg = ''
            for tile in tiles:
                (bounds, tileXYZ, t0, dbConfigFile, hasLighting,
                 hasWatermask) = tile
                if msg:
                    msg += ','
                msg += ('%s,%s,%s' %
                        (str(tileXYZ[0]), str(tileXYZ[1]), str(tileXYZ[2])))
                tcount += 1
                if tcount >= maxChunks:
                    messagecount += 1
                    writeSQSMessage(q, msg)
                    tcount = 0
                    msg = ''
                totalcount = totalcount + 1
            if msg:
                messagecount += 1
                writeSQSMessage(q, msg)
        except Exception as e:
            logger.error('Error during writing of sqs message:\n' + str(e),
                         exc_info=True)

        tend = time.time()
        logger.info('It took %s to create %s message in SQS gueue '
                    'representing %s tiles' %
                    (str(datetime.timedelta(seconds=tend - self.t0)),
                     messagecount, totalcount))
예제 #8
0
    def _stats(self, withDb=True):
        self.t0 = time.time()
        total = 0

        msg = '\n'
        tiles = TerrainTiles(self.dbConfigFile, self.tmsConfig, self.t0)
        geodetic = GlobalGeodetic(True)
        bounds = (tiles.minLon, tiles.minLat, tiles.maxLon, tiles.maxLat)
        zooms = range(tiles.tileMinZ, tiles.tileMaxZ + 1)

        db = DB('configs/terrain/database.cfg')
        try:
            with db.userSession() as session:
                for i in xrange(0, len(zooms)):
                    zoom = zooms[i]
                    model = modelsPyramid.getModelByZoom(zoom)
                    nbObjects = None
                    if withDb:
                        nbObjects = session.query(model).filter(
                            model.bboxIntersects(bounds)).count()
                    tileMinX, tileMinY = geodetic.LonLatToTile(
                        bounds[0], bounds[1], zoom)
                    tileMaxX, tileMaxY = geodetic.LonLatToTile(
                        bounds[2], bounds[3], zoom)
                    # Fast approach, but might not be fully correct
                    if tiles.fullonly == 1:
                        tileMinX += 1
                        tileMinY += 1
                        tileMaxX -= 1
                        tileMaxY -= 1
                    tileBounds = geodetic.TileBounds(tileMinX, tileMinY, zoom)
                    xCount = tileMaxX - tileMinX + 1
                    yCount = tileMaxY - tileMinY + 1
                    nbTiles = xCount * yCount
                    total += nbTiles
                    pointA = transformCoordinate(
                        'POINT(%s %s)' % (tileBounds[0], tileBounds[1]), 4326,
                        21781).GetPoints()[0]
                    pointB = transformCoordinate(
                        'POINT(%s %s)' % (tileBounds[2], tileBounds[3]), 4326,
                        21781).GetPoints()[0]
                    length = c2d.distance(pointA, pointB)
                    if tiles.fullonly == 1:
                        msg += 'WARNING: stats are approximative because ' \
                               'fullonly is activated!\n'
                    msg += 'At zoom %s:\n' % zoom
                    msg += 'We expect %s tiles overall\n' % nbTiles
                    msg += 'Min X is %s, Max X is %s\n' % (tileMinX, tileMaxX)
                    msg += '%s columns over X\n' % xCount
                    msg += 'Min Y is %s, Max Y is %s\n' % (tileMinY, tileMaxY)
                    msg += '%s rows over Y\n' % yCount
                    msg += '\n'
                    msg += 'A tile side is around %s meters' % int(
                        round(length))
                    if nbTiles > 0 and nbObjects is not None:
                        msg += 'We have an average of about %s triangles ' \
                               'per tile\n' % int(round(nbObjects / nbTiles))
                    msg += '\n\n'
            msg += '%s tiles in total.' % total
        except Exception as e:
            logger.error('An error occured during statistics collection')
            logger.error('%s' % e, exc_info=True)
            raise Exception(e)
        finally:
            db.userEngine.dispose()

        return (total, msg)