worldwind java批量下载Mercator数据
来源:互联网 发布:网络流行文化的论文 编辑:程序博客网 时间:2024/05/15 20:33
在Worldwind java的示例代码中,有一个示例是BulkDownload,它的主要功能就是下载可批量下载图层的数据。具体过程可以自行分析BulkDownload的源码,源码比较简单,这里不进行分析。
可批量下载图层的标志是图层是否实现了BulkRetrievable接口,如果实现了这个接口,就可以批量对该图层的数据进行批量下载。
在gov.nasa.worldwind.retrieve包中,BulkRetrievable的定义如下:
public interface BulkRetrievable{ BulkRetrievalThread makeLocal(Sector sector, double resolution, BulkRetrievalListener listener); long getEstimatedMissingDataSize(Sector sector, double resolution); long getEstimatedMissingDataSize(Sector sector, double resolution, FileStore fileStore); BulkRetrievalThread makeLocal(Sector sector, double resolution, FileStore fileStore, BulkRetrievalListener listener); String getName();}
它主要有两个功能,一是评估选定区域在指定可能需要下载的数据量;二是生成一个下载的线程。
为了实现对TiledImageLayer的批量下载,worldwind java的源码中给出了示例,一是针对BasicTiledImageLayer,实现BulkRetrievable接口;二是从BulkRetrievalThread建立派生类BasicTiledImageLayerBulkDownloader,以实现tile图像的下载。
在实现了Mercator层数据加载的情况下,为了进一步实现对Mercator层数据的下载,可以仿照BasicTiledImageLayer的做法,先实现BulkRetrievable接口,后建立对应的下载线程类。
- 针对Mecator图层实现BulkRetrievable接口
从TileImageLayer中把对BulkRetrievable实现的函数复制过来,然后进行修改。
需要注意的是BasicMercatorTiledImageLayer层与BasicTiledImageLayer层不同的地方主要是Sector不同,在BasicMercatorTiledImageLayer中几乎所有进行计算的Sector均是MercatorSector,因此,只需要将代码中的计算Sector改成计算MercatorSector即可完成。
Sector的计算如下:
Sector s = Sector.fromDegrees( sector.getMinLatitude().degrees + dLat * row, sector.getMinLatitude().degrees + dLat * row + dLat, sector.getMinLongitude().degrees + dLon * col, sector.getMinLongitude().degrees + dLon * col + dLon);
MercatorSector的计算如下:
MercatorSector s = MercatorSector.fromDegrees( l2 + dLat * row, l2 + dLat * row + dLat, sector.getMinLongitude().degrees + dLon * col, sector.getMinLongitude().degrees + dLon * col + dLon);
BasicTiledImageLayer层中,每一个Sector将由许多的Tile组成,每一个Tile由TextureTile对象表示,相应地,在BasicMercatorTiledImageLayer层中,对应的Sector变成了MecatorSector,Tile也变成了MercatorTextureTile,
sectorTiles[nwRow - row][col - nwCol] = new MercatorTextureTile( mSector, targetLevel, row, col);
Worldwind java的源码中只针对BasicTiledImageLayer实现了BulkRetrievable接口,而用来载入基于Mercator投影的图层并没有实现这一接口。
BasicMercatorTiledImageLayer的扩展类示例如下:
public class BasicMercatorTiledImageLayerCustom extends BasicMercatorTiledImageLayer implements BulkRetrievable{ private String strLayerName = ""; public BasicMercatorTiledImageLayerCustom(TileUrlBuilder ub,String labelName) { super(makeLevels(ub,labelName,labelName)); } public BasicMercatorTiledImageLayerCustom(TileUrlBuilder ub,String labelName,String datasetName) { super(makeLevels(ub,labelName,datasetName)); strLayerName = labelName; } private static LevelSet makeLevels(TileUrlBuilder ub,String labelName,String datasetName) { return makeLevels(ub,labelName,datasetName,".png","www.test.com",,0,16); } private static LevelSet makeLevels(TileUrlBuilder ub,String labelName,String datasetName,String suffix, String serverName,int numLevelMin,int numLevelMax) { return makeLevels(ub,labelName,datasetName,suffix,serverName,numLevelMin,numLevelMax,256,256); } private static LevelSet makeLevels(TileUrlBuilder ub, String labelName,String datasetName,String suffix,String serverName,int numLevelMin,int numLevelMax,int tileWidth,int tileHeight) { AVList params = new AVListImpl(); String strTemp = ""; params.setValue(AVKey.TILE_WIDTH, tileWidth); params.setValue(AVKey.TILE_HEIGHT, tileHeight); params.setValue(AVKey.DATA_CACHE_NAME, "Earth/"+labelName); params.setValue(AVKey.SERVICE, serverName); params.setValue(AVKey.DATASET_NAME, datasetName); params.setValue(AVKey.FORMAT_SUFFIX, suffix); params.setValue(AVKey.NUM_LEVELS, numLevelMax); params.setValue(AVKey.NUM_EMPTY_LEVELS, numLevelMin); params.setValue(AVKey.LEVEL_ZERO_TILE_DELTA, new LatLon(Angle.fromDegrees(22.5d), Angle.fromDegrees(45d))); params.setValue(AVKey.SECTOR, new MercatorSector(-1.0, 1.0, Angle.NEG180, Angle.POS180)); params.setValue(AVKey.TILE_URL_BUILDER, ub); return new LevelSet(params); } protected boolean transformAndSave(BufferedImage image, MercatorSector sector,File outFile) { image = transform(image, sector); String extension = outFile.getName().substring( outFile.getName().lastIndexOf('.') + 1); synchronized (this.fileLock) // synchronized with read of file in RequestTask.run() { //return ImageIO.write(image, extension, outFile); return ImageUtilCustom.savePngTransparent(image, extension, outFile); } } @Override public String toString() { return strLayerName; } //////////////////////////////////////////////////////////////// protected void retrieveTexture(MercatorTextureTile tile, DownloadPostProcessor postProcessor) { if (this.getValue(AVKey.RETRIEVER_FACTORY_LOCAL) != null) this.retrieveLocalTexture(tile, postProcessor); else // Assume it's remote, which handles the legacy cases. this.retrieveRemoteTexture(tile, postProcessor); } protected void retrieveLocalTexture(MercatorTextureTile tile, DownloadPostProcessor postProcessor) { if (!WorldWind.getLocalRetrievalService().isAvailable()) return; RetrieverFactory retrieverFactory = (RetrieverFactory) this.getValue(AVKey.RETRIEVER_FACTORY_LOCAL); if (retrieverFactory == null) return; AVListImpl avList = new AVListImpl(); avList.setValue(AVKey.SECTOR, tile.getSector()); avList.setValue(AVKey.WIDTH, tile.getWidth()); avList.setValue(AVKey.HEIGHT, tile.getHeight()); avList.setValue(AVKey.FILE_NAME, tile.getPath()); Retriever retriever = retrieverFactory.createRetriever(avList, postProcessor); WorldWind.getLocalRetrievalService().runRetriever(retriever, tile.getPriority()); } protected void retrieveRemoteTexture(MercatorTextureTile tile, DownloadPostProcessor postProcessor) { if (!this.isNetworkRetrievalEnabled()) { this.getLevels().markResourceAbsent(tile); return; } if (!WorldWind.getRetrievalService().isAvailable()) return; java.net.URL url; try { url = tile.getResourceURL(); if (url == null) return; if (WorldWind.getNetworkStatus().isHostUnavailable(url)) { this.getLevels().markResourceAbsent(tile); return; } } catch (java.net.MalformedURLException e) { Logging.logger().log(java.util.logging.Level.SEVERE, Logging.getMessage("layers.TextureLayer.ExceptionCreatingTextureUrl", tile), e); return; } Retriever retriever; if (postProcessor == null) //postProcessor = this.createDownloadPostProcessor(tile); postProcessor = new DownloadPostProcessor(tile,this); retriever = URLRetriever.createRetriever(url, postProcessor); if (retriever == null) { Logging.logger().severe( Logging.getMessage("layers.TextureLayer.UnknownRetrievalProtocol", url.toString())); return; } retriever.setValue(URLRetriever.EXTRACT_ZIP_ENTRY, "true"); // supports legacy layers // Apply any overridden timeouts. Integer cto = AVListImpl.getIntegerValue(this, AVKey.URL_CONNECT_TIMEOUT); if (cto != null && cto > 0) retriever.setConnectTimeout(cto); Integer cro = AVListImpl.getIntegerValue(this, AVKey.URL_READ_TIMEOUT); if (cro != null && cro > 0) retriever.setReadTimeout(cro); Integer srl = AVListImpl.getIntegerValue(this, AVKey.RETRIEVAL_QUEUE_STALE_REQUEST_LIMIT); if (srl != null && srl > 0) retriever.setStaleRequestLimit(srl); WorldWind.getRetrievalService().runRetriever(retriever, tile.getPriority()); } ////////////////////////////////////////////////////////////// @Override public BulkRetrievalThread makeLocal(Sector sector, double resolution, BulkRetrievalListener listener) { return makeLocal(sector, resolution, null, listener); } @Override public long getEstimatedMissingDataSize(Sector sector, double resolution) { return 0; } @Override public long getEstimatedMissingDataSize(Sector sector, double resolution, FileStore fileStore) { return 0; } @Override public BulkRetrievalThread makeLocal(Sector sector, double resolution, FileStore fileStore, BulkRetrievalListener listener) { Sector targetSector = sector != null ? getLevels().getSector().intersection(sector) : null; if (targetSector == null) return null; BasicMercatorTiledImageLayerCustomBulkDownloader thread = new BasicMercatorTiledImageLayerCustomBulkDownloader(this, targetSector, resolution, fileStore != null ? fileStore : this.getDataFileStore(), listener); thread.setDaemon(true); thread.start(); return thread; } public int countImagesInSector(Sector sector, int levelNumber) { MercatorSector s = MercatorSector.fromSector(sector); return countImagesInSector(s,levelNumber); } public int countImagesInSector(MercatorSector sector, int levelNumber) { ArrayList<Integer> li = GetRect(sector,levelNumber); if(li == null) return 0; int seRow = li.get(2); int nwRow = li.get(3); int nwCol = li.get(1); int seCol = li.get(0); int numRows = nwRow - seRow + 1; int numCols = seCol - nwCol + 1; return numRows * numCols; } public MercatorTextureTile[][] getTilesInSector(MercatorSector sector, int levelNumber) { if (sector == null) { String msg = Logging.getMessage("nullValue.SectorIsNull"); Logging.logger().severe(msg); throw new IllegalArgumentException(msg); } Level targetLevel = this.levels.getLastLevel(); if (levelNumber >= 0) { for (int i = levelNumber; i < this.getLevels().getLastLevel() .getLevelNumber(); i++) { if (this.levels.isLevelEmpty(i)) continue; targetLevel = this.levels.getLevel(i); break; } } // Collect all the tiles intersecting the input sector. ArrayList<Integer> li = GetRect(sector,levelNumber); int seRow = li.get(2); int nwRow = li.get(3); int nwCol = li.get(1); int seCol = li.get(0); Angle lonOrigin = this.levels.getTileOrigin().getLongitude(); double dLat = targetLevel.getTileDelta().getLatitude().degrees/90; double dLon = targetLevel.getTileDelta().getLongitude().degrees; int numRows = nwRow - seRow + 1; int numCols = seCol - nwCol + 1; MercatorTextureTile[][] sectorTiles = new MercatorTextureTile[numRows][numCols]; for (int row = nwRow; row >= seRow; row--) { for (int col = nwCol; col <= seCol; col++) { MercatorSector mSector = new MercatorSector( -1 + dLat * row, -1 + dLat * row + dLat, lonOrigin.addDegrees( dLon * col ), lonOrigin.addDegrees( dLon * col + dLon)); sectorTiles[nwRow - row][col - nwCol] = new MercatorTextureTile( mSector, targetLevel, row, col); } } return sectorTiles; } public ArrayList<Integer> GetRect(Sector sector,int levelNumber) { if (sector == null) { return null; } Level targetLevel = this.levels.getLastLevel(); if (levelNumber >= 0) { for (int i = levelNumber; i < this.getLevels().getLastLevel() .getLevelNumber(); i++) { if (this.levels.isLevelEmpty(i)) continue; targetLevel = this.levels.getLevel(i); break; } } ArrayList<Integer> li = new ArrayList<Integer>(); LatLon delta = targetLevel.getTileDelta(); Angle latOrigin = this.levels.getTileOrigin().getLatitude(); Angle lonOrigin = this.levels.getTileOrigin().getLongitude(); double dLatMin = MercatorSector.gudermannianInverse(sector.getMinLatitude()); double dLatMax = MercatorSector.gudermannianInverse(sector.getMaxLatitude()); double dLat = delta.getLatitude().degrees/90; double dLon = delta.getLongitude().degrees; int seRow = (int) ((dLatMin + 1) / dLat); int nwRow = (int) ((dLatMax + 1) / dLat); int nwCol = Tile.computeColumn(delta.getLongitude(), sector .getMinLongitude(), lonOrigin); int seCol = Tile.computeColumn(delta.getLongitude(), sector .getMaxLongitude(), lonOrigin); li.add(seCol); li.add(nwCol); li.add(seRow); li.add(nwRow); return li; }}
- 实现Mercator图层的BulkRetrievalThread接口
仿照BasicTiledImageLayerBulkDownloader建立BasicMercatorTiledImageLayerCustomBulkDownloader,示例如下:
public class BasicMercatorTiledImageLayerCustomBulkDownloader extends BulkRetrievalThread{ protected final static int MAX_TILE_COUNT_PER_REGION = 200; protected final static long DEFAULT_AVERAGE_FILE_SIZE = 350000L; protected final BasicMercatorTiledImageLayerCustom layer; protected final int level; protected ArrayList<MercatorTextureTile> missingTiles; public BasicMercatorTiledImageLayerCustomBulkDownloader(BasicMercatorTiledImageLayerCustom layer, Sector sector, double resolution, BulkRetrievalListener listener) { this(layer,sector,resolution,layer.getDataFileStore(),listener); } public BasicMercatorTiledImageLayerCustomBulkDownloader(BasicMercatorTiledImageLayerCustom layer, Sector sector, double resolution, FileStore fileStore, BulkRetrievalListener listener) { // Arguments checked in parent constructor super(layer, sector, resolution, fileStore, listener); this.layer = layer; this.level = this.layer.computeLevelForResolution(sector, resolution); } public void run() { try { // Init progress with missing tile count estimate this.progress.setTotalCount(this.estimateMissingTilesCount(50)); this.progress.setTotalSize(this.progress.getTotalCount() * estimateAverageTileSize()); // Determine and request missing tiles by level/region for (int levelNumber = 0; levelNumber <= this.level; levelNumber++) { if (this.layer.getLevels().isLevelEmpty(levelNumber)) continue; int div = this.computeRegionDivisions(this.sector, levelNumber, MAX_TILE_COUNT_PER_REGION); Iterator<MercatorSector> regionsIterator = this.getRegionIterator(this.sector, div); MercatorSector region; while (regionsIterator.hasNext()) { region = regionsIterator.next(); // Determine missing tiles this.missingTiles = getMissingTilesInSector(region, levelNumber); // Submit missing tiles requests at intervals while (this.missingTiles.size() > 0) { submitMissingTilesRequests(); if (this.missingTiles.size() > 0) Thread.sleep(RETRIEVAL_SERVICE_POLL_DELAY); } } } // Set progress to 100% this.progress.setTotalCount(this.progress.getCurrentCount()); this.progress.setTotalSize(this.progress.getCurrentSize()); } catch (InterruptedException e) { String message = Logging.getMessage("generic.BulkRetrievalInterrupted", this.layer.getName()); Logging.logger().log(java.util.logging.Level.WARNING, message, e); } catch (Exception e) { String message = Logging.getMessage("generic.ExceptionDuringBulkRetrieval", this.layer.getName()); Logging.logger().severe(message); throw new RuntimeException(message); } } protected synchronized void submitMissingTilesRequests() throws InterruptedException { RetrievalService rs = WorldWind.getRetrievalService(); int i = 0; while (this.missingTiles.size() > i && rs.isAvailable()) { Thread.sleep(1); // generates InterruptedException if thread has been interrupted MercatorTextureTile tile = this.missingTiles.get(i); if (this.layer.getLevels().isResourceAbsent(tile)) { removeAbsentTile(tile); // tile is absent, count it off. continue; } URL url = this.fileStore.findFile(tile.getPath(), false); if (url != null) { // tile has been retrieved and is local now, count it as retrieved. removeRetrievedTile(tile); continue; } this.layer.retrieveTexture(tile, createBulkDownloadPostProcessor(tile)); //this.layer.downloadTexture(tile); i++; } } protected BasicMercatorTiledImageLayer.DownloadPostProcessor createBulkDownloadPostProcessor(MercatorTextureTile tile) { return new BulkDownloadPostProcessor(tile, this.layer, this.fileStore); } protected class BulkDownloadPostProcessor extends BasicMercatorTiledImageLayer.DownloadPostProcessor { public BulkDownloadPostProcessor(MercatorTextureTile tile, BasicMercatorTiledImageLayer layer, FileStore fileStore) { super(tile, layer, fileStore); } public ByteBuffer run(Retriever retriever) { ByteBuffer buffer = super.run(retriever); if (retriever.getState().equals(Retriever.RETRIEVER_STATE_SUCCESSFUL)) removeRetrievedTile(this.tile); try { if (hasRetrievalListeners()) callRetrievalListeners(retriever, this.tile); } catch (Exception e) { System.console().printf(e.getMessage()); } return buffer; } } protected void callRetrievalListeners(Retriever retriever, TextureTile tile) throws MalformedURLException { String eventType = (retriever.getState().equals(Retriever.RETRIEVER_STATE_SUCCESSFUL)) ? BulkRetrievalEvent.RETRIEVAL_SUCCEEDED : BulkRetrievalEvent.RETRIEVAL_FAILED; String strPre=""; if(retriever instanceof URLRetriever) strPre = ((URLRetriever) retriever).getUrl().toString()+"\t"; super.callRetrievalListeners(new BulkRetrievalEvent(this.layer, eventType, strPre+tile.getPath())); } protected synchronized void removeRetrievedTile(MercatorTextureTile tile) { this.missingTiles.remove(tile); // Update progress this.progress.setCurrentCount(this.progress.getCurrentCount() + 1); this.progress.setCurrentSize(this.progress.getCurrentSize() + estimateAverageTileSize()); this.progress.setLastUpdateTime(System.currentTimeMillis()); this.normalizeProgress(); } protected synchronized void removeAbsentTile(TextureTile tile) { this.missingTiles.remove(tile); // Decrease progress expected total count and size this.progress.setTotalCount(this.progress.getTotalCount() - 1); this.progress.setTotalSize(this.progress.getTotalSize() - estimateAverageTileSize()); this.progress.setLastUpdateTime(System.currentTimeMillis()); this.normalizeProgress(); } protected void normalizeProgress() { if (this.progress.getTotalCount() < this.progress.getCurrentCount()) { this.progress.setTotalCount(this.progress.getCurrentCount()); this.progress.setTotalSize(this.progress.getCurrentSize()); } } protected long getEstimatedMissingDataSize() { // Get missing tiles count estimate long totMissing = estimateMissingTilesCount(6); // Get average tile size estimate long averageTileSize = estimateAverageTileSize(); return totMissing * averageTileSize; } protected long estimateMissingTilesCount(int numSamples) { int maxLevel = this.layer.computeLevelForResolution(this.sector, this.resolution); // Total expected tiles long totCount = 0; for (int levelNumber = 0; levelNumber <= maxLevel; levelNumber++) { if (!this.layer.getLevels().isLevelEmpty(levelNumber)) totCount += this.layer.countImagesInSector(sector, levelNumber); } // Sample random small sized sectors at finest level int div = this.computeRegionDivisions(this.sector, maxLevel, 36); // max 6x6 tiles per region MercatorSector[] regions = computeRandomRegions(this.sector, div, numSamples); long regionMissing = 0; long regionCount = 0; try { if (regions.length < numSamples) { regionCount = this.layer.countImagesInSector(this.sector, maxLevel); regionMissing = getMissingTilesInSector(MercatorSector.fromSector(this.sector), maxLevel).size(); } else { for (MercatorSector region : regions) { // Count how many tiles are missing in each sample region regionCount += this.layer.countImagesInSector(region, maxLevel); regionMissing += getMissingTilesInSector(region, maxLevel).size(); } } } catch (InterruptedException e) { return 0; } catch (Exception e) { String message = Logging.getMessage("generic.ExceptionDuringDataSizeEstimate", this.layer.getName()); Logging.logger().severe(message); throw new RuntimeException(message); } // Extrapolate total missing count return (long)(totCount * ((double)regionMissing / regionCount)); } protected int computeRegionDivisions(Sector sector, int levelNumber, int maxCount) { long tileCount = this.layer.countImagesInSector(sector, levelNumber); if (tileCount <= maxCount) return 1; // Divide sector in regions that will contain no more tiles then maxCount return (int) Math.ceil(Math.sqrt((double) tileCount / maxCount)); } public MercatorSector[] subdivide(Sector sector, int div) { double l1 = MercatorSector.gudermannianInverse(sector.getMaxLatitude()); double l2 = MercatorSector.gudermannianInverse(sector.getMinLatitude()); //final double dLat = sector.getDeltaLat().degrees / div; final double dLat = (l1-l2) / div; double dLon = sector.getDeltaLon().degrees / div; MercatorSector[] sectors = new MercatorSector[div * div]; int idx = 0; for (int row = 0; row < div; row++) { for (int col = 0; col < div; col++) { sectors[idx++] = MercatorSector.fromDegrees( l2 + dLat * row, l2 + dLat * row + dLat, sector.getMinLongitude().degrees + dLon * col, sector.getMaxLongitude().degrees + dLon * col + dLon); } } return sectors; } protected MercatorSector[] computeRandomRegions(Sector sector, int div, int numRegions) { if (numRegions > div * div) return subdivide(sector,div); double l1 = MercatorSector.gudermannianInverse(sector.getMaxLatitude()); double l2 = MercatorSector.gudermannianInverse(sector.getMinLatitude()); //final double dLat = sector.getDeltaLat().degrees / div; final double dLat = (l1-l2) / div; final double dLon = sector.getDeltaLon().degrees / div; ArrayList<MercatorSector> regions = new ArrayList<MercatorSector>(numRegions); Random rand = new Random(); while (regions.size() < numRegions) { int row = rand.nextInt(div); int col = rand.nextInt(div); MercatorSector s = MercatorSector.fromDegrees( l2 + dLat * row, l2 + dLat * row + dLat, sector.getMinLongitude().degrees + dLon * col, sector.getMinLongitude().degrees + dLon * col + dLon); if (!regions.contains(s)) regions.add(s); } return regions.toArray(new MercatorSector[numRegions]); } protected Iterator<MercatorSector> getRegionIterator(final Sector sector, final int div) { double l1 = MercatorSector.gudermannianInverse(sector.getMaxLatitude()); double l2 = MercatorSector.gudermannianInverse(sector.getMinLatitude()); //final double dLat = sector.getDeltaLat().degrees / div; final double dLat = (l1-l2) / div; final double dLon = sector.getDeltaLon().degrees / div; return new Iterator<MercatorSector>() { int row = 0; int col = 0; public boolean hasNext() { return row < div; } public MercatorSector next() { double l2 = MercatorSector.gudermannianInverse(sector.getMinLatitude()); MercatorSector s = MercatorSector.fromDegrees( l2 + dLat * row, l2 + dLat * row + dLat, sector.getMinLongitude().degrees + dLon * col, sector.getMinLongitude().degrees + dLon * col + dLon); col++; if (col >= div) { col = 0; row++; } return s; } public void remove() { } }; } protected ArrayList<MercatorTextureTile> getMissingTilesInSector(MercatorSector sector, int levelNumber) throws InterruptedException { ArrayList<MercatorTextureTile> tiles = new ArrayList<MercatorTextureTile>(); MercatorTextureTile[][] tileArray = this.layer.getTilesInSector((sector), levelNumber); for (MercatorTextureTile[] row : tileArray) { for (MercatorTextureTile tile : row) { Thread.sleep(1); // generates InterruptedException if thread has been interrupted if (tile == null) continue; if (isTileLocalOrAbsent(tile)) continue; // tile is local or absent tiles.add(tile); } } return tiles; } protected boolean isTileLocalOrAbsent(MercatorTextureTile tile) { if (this.layer.getLevels().isResourceAbsent(tile)) return true; // tile is absent URL url = this.fileStore.findFile(tile.getPath(), false); //return url != null && !this.layer.isTextureFileExpired(tile, url, fileStore); return url != null && !this.layer.isTextureExpired(tile, url); } protected long estimateAverageTileSize() { Long previouslyComputedSize = (Long) this.layer.getValue(AVKey.AVERAGE_TILE_SIZE); if (previouslyComputedSize != null) return previouslyComputedSize; long size = 0; long count = 0; // Average cached tile files size in a few directories from first non empty level Level targetLevel = this.layer.getLevels().getFirstLevel(); while (targetLevel.isEmpty() && !targetLevel.equals(this.layer.getLevels().getLastLevel())) { targetLevel = this.layer.getLevels().getLevel(targetLevel.getLevelNumber() + 1); } File cacheRoot = new File(this.fileStore.getWriteLocation(), targetLevel.getPath()); if (cacheRoot.exists()) { File[] rowDirs = cacheRoot.listFiles(new FileFilter() { public boolean accept(File file) { return file.isDirectory(); } }); for (File dir : rowDirs) { long averageSize = computeAverageTileSize(dir); if (averageSize > 0) { size += averageSize; count++; } if (count >= 2) // average content from up to 2 cache folders break; } } Long averageTileSize = DEFAULT_AVERAGE_FILE_SIZE; if (count > 0 && size > 0) { averageTileSize = size / count; this.layer.setValue(AVKey.AVERAGE_TILE_SIZE, averageTileSize); } return averageTileSize; } protected long computeAverageTileSize(File dir) { long size = 0; int count = 0; File[] files = dir.listFiles(); for (File file : files) { try { FileInputStream fis = new FileInputStream(file); size += fis.available(); fis.close(); count++; } catch (IOException e) { count += 0; } } return count > 0 ? size / count : 0; }}
- worldwind java批量下载Mercator数据
- worldwind java中Mercator层的图片不清晰问题
- Worldwind下载
- WorldWind数据
- 批量下载GLDAS数据
- java批量下载
- java 批量下载文件
- java 批量下载文件
- java实现批量下载
- java批量下载
- java 批量下载文件
- java批量下载文件
- JAVA批量下载
- java打包批量下载
- 使用Python批量下载数据
- java 批量添加数据
- java 批量插入数据
- Java批量插入数据
- 超神之路------我独行
- sap 公司代码和工厂代码的关系
- MySQL为什么需要一个主键(自增长)
- 每天laravel-20160824|Base Encrypter
- Selenium Webdriver元素定位的八种常用方式
- worldwind java批量下载Mercator数据
- linux 环境下开发的权限问题
- c++ primer(第五版)学习笔记及习题答案代码版(第十四章)重载运算与类型转换
- Java接口,多态的解析图
- web.xml加载顺序
- Oracle ORA-01033: ORACLE initialization or shutdown in progress 错误解决办法
- 为什么是三次握手而不是两次握手为什么是四次挥手
- 为什么选用检索引擎
- Android开篇的基础知识归纳(狠基础)