1. 程式人生 > >4.01WorldWindAndroid載入TileImage切片解析

4.01WorldWindAndroid載入TileImage切片解析

重點類:

TileSufaceImage

    public void setLevelSet(LevelSet levelSet) {
        if (levelSet == null) {
            throw new IllegalArgumentException(
                Logger.logMessage(Logger.ERROR, "TiledSurfaceImage", "setLevelSet", "missingLevelSet"));
        }

        this.levelSet = levelSet;
        this.invalidateTiles();
    }

    public void setTileFactory
(TileFactory tileFactory) { this.tileFactory = tileFactory; this.invalidateTiles(); }
@Override
protected void doRender(RenderContext rc) {
    if (rc.terrain.getSector().isEmpty()) {
        return; // no terrain surface to render on
    }

    this.determineActiveProgram(rc);
    this.assembleTiles(rc);
this.activeProgram = null; // clear the active program to avoid leaking render resources this.ancestorTile = null; // clear the ancestor tile and texture this.ancestorTexture = null; }
protected void assembleTiles(RenderContext rc) {
    // TODO
    // The need to create Tiles with a defined image source couples the need to determine a tile's visibility with
    // he need to know its image source. Decoupling the two would mean we only need to know the image source when
    // the texture is actually requested Could the tile-based operations done here be implicit on level/row/column,
    // or use transient pooled tile objects not tied to an image source?

    if (this.topLevelTiles.isEmpty()) {
        this.createTopLevelTiles();
} for (int idx = 0, len = this.topLevelTiles.size(); idx < len; idx++) { this.addTileOrDescendants(rc, (ImageTile) this.topLevelTiles.get(idx)); } } protected void createTopLevelTiles() { Level firstLevel = this.levelSet.firstLevel(); if (firstLevel != null) { Tile.assembleTilesForLevel(firstLevel, this.tileFactory, this.topLevelTiles); } }
    protected void addTileOrDescendants(RenderContext rc, ImageTile tile) {
        if (!tile.intersectsSector(this.levelSet.sector) || !tile.intersectsFrustum(rc, rc.frustum)) {
            return; // ignore the tile and its descendants if it's not needed or not visible
        }

        if (tile.level.isLastLevel() || !tile.mustSubdivide(rc, this.detailControl)) {
            this.addTile(rc, tile);
            return; // use the tile if it does not need to be subdivided
        }

        ImageTile currentAncestorTile = this.ancestorTile;
        Texture currentAncestorTexture = this.ancestorTexture;

        ImageSource tileImageSource = tile.getImageSource();
        if (tileImageSource != null) { // tile has an image source; its level is not empty
            Texture tileTexture = rc.getTexture(tileImageSource);
            if (tileTexture != null) { // tile has a texture; use it as a fallback tile for descendants
                this.ancestorTile = tile;
                this.ancestorTexture = tileTexture;
            }
        }

        for (Tile child : tile.subdivideToCache(this.tileFactory, this.tileCache, 4)) { // each tile has a cached size of 1
            this.addTileOrDescendants(rc, (ImageTile) child); // recursively process the tile's children
        }

        this.ancestorTile = currentAncestorTile; // restore the last fallback tile, even if it was null
        this.ancestorTexture = currentAncestorTexture;
    }

    protected void addTile(RenderContext rc, ImageTile tile) {
        ImageSource imageSource = tile.getImageSource();
        if (imageSource == null) {
            return; // no image source indicates an empty level or an image missing from the tiled data store
        }

        Texture texture = rc.getTexture(imageSource); // try to get the texture from the cache
        if (texture == null) {
            texture = rc.retrieveTexture(imageSource, this.imageOptions); // puts retrieved textures in the cache
        }

        if (texture != null) { // use the tile's own texture
            Pool<DrawableSurfaceTexture> pool = rc.getDrawablePool(DrawableSurfaceTexture.class);
            Drawable drawable = DrawableSurfaceTexture.obtain(pool).set(this.activeProgram, tile.sector, texture, texture.getTexCoordTransform());
            rc.offerSurfaceDrawable(drawable, 0 /*z-order*/);
        } else if (this.ancestorTile != null) { // use the ancestor tile's texture, transformed to fill the tile sector
            this.ancestorTexCoordMatrix.set(this.ancestorTexture.getTexCoordTransform());
            this.ancestorTexCoordMatrix.multiplyByTileTransform(tile.sector, this.ancestorTile.sector);
            Pool<DrawableSurfaceTexture> pool = rc.getDrawablePool(DrawableSurfaceTexture.class);
            Drawable drawable = DrawableSurfaceTexture.obtain(pool).set(this.activeProgram, tile.sector, this.ancestorTexture, this.ancestorTexCoordMatrix);
            rc.offerSurfaceDrawable(drawable, 0 /*z-order*/);
        }
    }


Tile:

  public static Collection<Tile> assembleTilesForLevel(Level level, TileFactory tileFactory, Collection<Tile> result) {
        if (level == null) {
            throw new IllegalArgumentException(
                Logger.logMessage(Logger.ERROR, "Tile", "assembleTilesForLevel", "missingLevel"));
        }

        if (tileFactory == null) {
            throw new IllegalArgumentException(
                Logger.logMessage(Logger.ERROR, "Tile", "assembleTilesForLevel", "missingTileFactory"));
        }

        if (result == null) {
            throw new IllegalArgumentException(
                Logger.logMessage(Logger.ERROR, "Tile", "assembleTilesForLevel", "missingResult"));
        }

        Sector sector = level.parent.sector;
        double tileDelta = level.tileDelta;

        int firstRow = Tile.computeRow(tileDelta, sector.minLatitude());
        int lastRow = Tile.computeLastRow(tileDelta, sector.maxLatitude());
        int firstCol = Tile.computeColumn(tileDelta, sector.minLongitude());
        int lastCol = Tile.computeLastColumn(tileDelta, sector.maxLongitude());

        double firstRowLat = -90 + firstRow * tileDelta;
        double firstRowLon = -180 + firstCol * tileDelta;
        double lat = firstRowLat;
        double lon;

        for (int row = firstRow; row <= lastRow; row++) {
            lon = firstRowLon;

            for (int col = firstCol; col <= lastCol; col++) {
                Sector tileSector = new Sector(lat, lon, tileDelta, tileDelta);
                result.add(tileFactory.createTile(tileSector, level, row, col));

                lon += tileDelta;
            }

            lat += tileDelta;
        }

        return result;
    }

LevelSet

 public LevelSet(LevelSetConfig config) {
        if (config == null) {
            throw new IllegalArgumentException(
                Logger.logMessage(Logger.ERROR, "LevelSet", "constructor", "missingConfig"));
        }

        if (config.sector == null) {
            throw new IllegalArgumentException(
                Logger.logMessage(Logger.ERROR, "LevelSet", "constructor", "missingSector"));
        }

        if (config.firstLevelDelta <= 0) {
            throw new IllegalArgumentException(
                Logger.logMessage(Logger.ERROR, "LevelSet", "constructor", "invalidTileDelta"));
        }

        if (config.numLevels < 0) {
            throw new IllegalArgumentException(
                Logger.logMessage(Logger.ERROR, "LevelSet", "constructor", "invalidNumLevels"));
        }

        if (config.tileWidth < 1 || config.tileHeight < 1) {
            throw new IllegalArgumentException(
                Logger.logMessage(Logger.ERROR, "LevelSet", "constructor", "invalidWidthOrHeight"));
        }

        this.sector.set(config.sector);
        this.firstLevelDelta = config.firstLevelDelta;
        this.tileWidth = config.tileWidth;
        this.tileHeight = config.tileHeight;
        this.levels = new Level[config.numLevels];
        this.assembleLevels();
    }

    protected void assembleLevels() {
        for (int i = 0, len = this.levels.length; i < len; i++) {
            double n = Math.pow(2, i);
            double delta = firstLevelDelta / n;
            this.levels[i] = new Level(this, i, delta);
        }
    }

TileFactory:

public interface TileFactory {

    /**
     * Returns a tile for a specified sector, level within a {@link LevelSet}, and row and column within that level.
     *
     * @param sector the sector spanned by the tile
     * @param level  the level at which the tile lies within a LevelSet
     * @param row    the row within the specified level
     * @param column the column within the specified level
     *
     * @return a tile constructed with the specified arguments
     *
     * @throws IllegalArgumentException if either the sector or the level is null
     */
    Tile createTile(Sector sector, Level level, int row, int column);
}