private void addTileOrDescendants(DrawContext dc, MercatorTextureTile tile) { if (this.meetsRenderCriteria(dc, tile)) { this.addTile(dc, tile); return; } // The incoming tile does not meet the rendering criteria, so it must be subdivided and those // subdivisions tested against the criteria. // All tiles that meet the selection criteria are drawn, but some of those tiles will not have // textures associated with them either because their texture isn't loaded yet or because they // are finer grain than the layer has textures for. In these cases the tiles use the texture of // the closest ancestor that has a texture loaded. This ancestor is called the // currentResourceTile. // A texture transform is applied during rendering to align the sector's texture coordinates // with the // appropriate region of the ancestor's texture. MercatorTextureTile ancestorResource = null; try { // TODO: Revise this to reflect that the parent layer is only requested while the algorithm // continues // to search for the layer matching the criteria. // At this point the tile does not meet the render criteria but it may have its texture in // memory. // If so, register this tile as the resource tile. If not, then this tile will be the next // level // below a tile with texture in memory. So to provide progressive resolution increase, add // this tile // to the draw list. That will cause the tile to be drawn using its parent tile's texture, and // it will // cause it's texture to be requested. At some future call to this method the tile's texture // will be in // memory, it will not meet the render criteria, but will serve as the parent to a tile that // goes // through this same process as this method recurses. The result of all this is that a tile // isn't rendered // with its own texture unless all its parents have their textures loaded. In addition to // causing // progressive resolution increase, this ensures that the parents are available as the user // zooms out, and // therefore the layer remains visible until the user is zoomed out to the point the layer is // no longer // active. if (tile.isTextureInMemory(dc.getTextureCache()) || tile.getLevelNumber() == 0) { ancestorResource = this.currentResourceTile; this.currentResourceTile = tile; } else if (!tile.getLevel().isEmpty()) { // this.addTile(dc, tile); // return; // Issue a request for the parent before descending to the children. if (tile.getLevelNumber() < this.levels.getNumLevels()) { // Request only tiles with data associated at this level if (!this.levels.isResourceAbsent(tile)) this.requestTexture(dc, tile); } } MercatorTextureTile[] subTiles = tile.createSubTiles(this.levels.getLevel(tile.getLevelNumber() + 1)); for (MercatorTextureTile child : subTiles) { if (this.isTileVisible(dc, child)) this.addTileOrDescendants(dc, child); } } finally { if (ancestorResource != null) // Pop this tile as the currentResource ancestor this.currentResourceTile = ancestorResource; } }