1. 程式人生 > >4.02WorldwindAndroid載入切片解析之請求的傳送

4.02WorldwindAndroid載入切片解析之請求的傳送

TileSurfaceImage類
    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 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; }
Tile類
    public Tile[] subdivideToCache(TileFactory tileFactory, LruMemoryCache<String, Tile[]> cache, int cacheSize) {
        if (tileFactory == null) {
            throw new IllegalArgumentException(
                Logger.logMessage(Logger.ERROR, "Tile", "subdivideToCache", "missingTileFactory"));
        }

        if (cache == null) {
            throw new IllegalArgumentException(
                Logger.logMessage(Logger.ERROR, "Tile", "subdivideToCache", "missingCache"));
        }

        Tile[] children = cache.get(this.tileKey);
        if (children == null) {
            children = this.subdivide(tileFactory);
            if (children != null) {
                cache.put(this.tileKey, children, cacheSize);
            }
        }

        return children;
    }
 public Tile[] subdivide(TileFactory tileFactory) {
        if (tileFactory == null) {
            throw new IllegalArgumentException(
                Logger.logMessage(Logger.ERROR, "Tile", "subdivide", "missingTileFactory"));
        }

        Level childLevel = this.level.nextLevel();
        if (childLevel == null) {
            return null;
        }

        Tile[] children = new Tile[4];
        double latMin = this.sector.minLatitude();
        double lonMin = this.sector.minLongitude();
        double latMid = this.sector.centroidLatitude();
        double lonMid = this.sector.centroidLongitude();
        double childDelta = this.level.tileDelta * 0.5;

        int childRow = 2 * this.row;
        int childCol = 2 * this.column;
        Sector childSector = new Sector(latMin, lonMin, childDelta, childDelta);
        children[0] = tileFactory.createTile(childSector, childLevel, childRow, childCol); // Southwest

        childRow = 2 * this.row;
        childCol = 2 * this.column + 1;
        childSector = new Sector(latMin, lonMid, childDelta, childDelta);
        children[1] = tileFactory.createTile(childSector, childLevel, childRow, childCol); // Southeast

        childRow = 2 * this.row + 1;
        childCol = 2 * this.column;
        childSector = new Sector(latMid, lonMin, childDelta, childDelta);
        children[2] = tileFactory.createTile(childSector, childLevel, childRow, childCol); // Northwest

        childRow = 2 * this.row + 1;
        childCol = 2 * this.column + 1;
        childSector = new Sector(latMid, lonMid, childDelta, childDelta);
        children[3] = tileFactory.createTile(childSector, childLevel, childRow, childCol); // Northeast

        return children;
    }

這裡想說明問題是:

     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
        }

就是對當前的現實狀態進行判斷,以決定是否直接載入當前切片還是需要進一步切分,如果需要繼續劃分,就不載入,繼續向下切分子切片,並遞迴呼叫addTileOrDescendants,繼續判斷切片是否還需切分,如果不需要繼續切分,就addTile

  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*/);
        }
    }

此時,就需要傳送請求來獲取對應的切片了!

RenderresourceCachelei

    public Texture retrieveTexture(ImageSource imageSource, ImageOptions options) {
        if (imageSource == null) {
            return null; // a null image source corresponds to a null texture
        }

        // Bitmap image sources are already in memory, so a texture may be created and put into the cache immediately.
        if (imageSource.isBitmap()) {
            Texture texture = this.createTexture(imageSource, options, imageSource.asBitmap());
            this.put(imageSource, texture, texture.getByteCount());
            return texture;
        }

        // All other image sources must be retrieved from disk or network and must be retrieved on a separate thread.
        // This includes bitmap factory image sources, since we cannot make any guarantees about what a bitmap factory
        // implementation may do. First look for the image in the image retrieval cache, removing it and creating a
        // corresponding texture if found.
        Bitmap bitmap = this.imageRetrieverCache.remove(imageSource);
        if (bitmap != null) {
            Texture texture = this.createTexture(imageSource, options, bitmap);
            this.put(imageSource, texture, texture.getByteCount());
            return texture;
        }

        // The image must be retrieved on a separate thread. Request the image source and return null to indicate that
        // the texture is not in memory. The image is added to the image retrieval cache upon successful retrieval. It's
        // then expected that a subsequent render frame will result in another call to retrieveTexture, in which case
        // the image will be found in the image retrieval cache.
        if (imageSource.isUrl()) {
            this.urlImageRetriever.retrieve(imageSource, options, this);
        } else {
            this.imageRetriever.retrieve(imageSource, options, this);
        }
        return null;
    }

Retriever類:

    public void retrieve(K key, O options, Callback<K, O, V> callback) {
        if (key == null) {
            throw new IllegalArgumentException(
                Logger.logMessage(Logger.ERROR, "Retriever", "retrieve", "missingKey"));
        }

        if (callback == null) {
            throw new IllegalArgumentException(
                Logger.logMessage(Logger.ERROR, "Retriever", "retrieve", "missingCallback"));
        }

        AsyncTask<K, O, V> task = this.obtainAsyncTask(key, options, callback);
        if (task == null) { // too many async tasks running, or a task for 'key' is already running
            callback.retrievalRejected(this, key);
            return;
        }

        try {
            WorldWind.taskService().execute(task);
        } catch (RejectedExecutionException ignored) { // singleton task service is full
            this.recycleAsyncTask(task);
            callback.retrievalRejected(this, key);
        }
    }