diff --git a/src/config/worldwind.layers.xml b/src/config/worldwind.layers.xml
index d7ffef9a59..3b5d6d4297 100644
--- a/src/config/worldwind.layers.xml
+++ b/src/config/worldwind.layers.xml
@@ -30,8 +30,10 @@
+
+
diff --git a/src/gov/nasa/worldwind/layers/Earth/OSMCycleMapLayer.java b/src/gov/nasa/worldwind/layers/Earth/OSMCycleMapLayer.java
index 6e85210c2e..8dd13a0592 100644
--- a/src/gov/nasa/worldwind/layers/Earth/OSMCycleMapLayer.java
+++ b/src/gov/nasa/worldwind/layers/Earth/OSMCycleMapLayer.java
@@ -5,10 +5,7 @@
*/
package gov.nasa.worldwind.layers.Earth;
-import gov.nasa.worldwind.avlist.*;
-import gov.nasa.worldwind.geom.*;
import gov.nasa.worldwind.layers.mercator.*;
-import gov.nasa.worldwind.util.*;
import java.net.*;
@@ -17,45 +14,38 @@
*/
public class OSMCycleMapLayer extends BasicMercatorTiledImageLayer
{
- public OSMCycleMapLayer()
- {
- super(makeLevels());
+ public OSMCycleMapLayer()
+ {
+ super("h", "Earth/OSM-Mercator/OpenStreetMap Cycle", 19, 256, false, ".png", new URLBuilder());
+ }
+
+ private static class URLBuilder extends MercatorTileUrlBuilder
+ {
+ private String apiKey;
+
+ @Override
+ protected URL getMercatorURL(int x, int y, int z) throws MalformedURLException
+ {
+ String urlPostfix = (this.apiKey != null) ? "?apikey=" + this.apiKey : "";
+ return new URL("https://a.tile.thunderforest.com/cycle/" + z + "/" + x + "/" + y + ".png" + urlPostfix);
+ }
+ }
+
+ public void setAPIKey(String apiKey)
+ {
+ URLBuilder urlBuilder = (URLBuilder)getURLBuilder();
+ urlBuilder.apiKey = apiKey;
+ }
+
+ public String getAPIKey()
+ {
+ URLBuilder urlBuilder = (URLBuilder)getURLBuilder();
+ return urlBuilder.apiKey;
}
- private static LevelSet makeLevels()
- {
- AVList params = new AVListImpl();
-
- params.setValue(AVKey.TILE_WIDTH, 256);
- params.setValue(AVKey.TILE_HEIGHT, 256);
- params.setValue(AVKey.DATA_CACHE_NAME, "Earth/OSM-Mercator/OpenStreetMap Cycle");
- params.setValue(AVKey.SERVICE, "http://b.andy.sandbox.cloudmade.com/tiles/cycle/");
- params.setValue(AVKey.DATASET_NAME, "*");
- params.setValue(AVKey.FORMAT_SUFFIX, ".png");
- params.setValue(AVKey.NUM_LEVELS, 16);
- params.setValue(AVKey.NUM_EMPTY_LEVELS, 0);
- 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, new URLBuilder());
-
- return new LevelSet(params);
- }
-
- private static class URLBuilder implements TileUrlBuilder
- {
- public URL getURL(Tile tile, String imageFormat)
- throws MalformedURLException
- {
- return new URL(tile.getLevel().getService()
- + (tile.getLevelNumber() + 3) +"/"+ tile.getColumn()+"/"+ ((1 << (tile.getLevelNumber()) + 3) - 1 - tile.getRow()) + ".png");
- }
- }
-
- @Override
- public String toString()
- {
- return "OpenStreetMap Cycle";
- }
+ @Override
+ public String toString()
+ {
+ return "OpenStreetMap Cycle";
+ }
}
diff --git a/src/gov/nasa/worldwind/layers/Earth/OSMMapnikLayer.java b/src/gov/nasa/worldwind/layers/Earth/OSMMapnikLayer.java
index 94c56d1069..f62f1ffa42 100644
--- a/src/gov/nasa/worldwind/layers/Earth/OSMMapnikLayer.java
+++ b/src/gov/nasa/worldwind/layers/Earth/OSMMapnikLayer.java
@@ -5,10 +5,7 @@
*/
package gov.nasa.worldwind.layers.Earth;
-import gov.nasa.worldwind.avlist.*;
-import gov.nasa.worldwind.geom.*;
import gov.nasa.worldwind.layers.mercator.*;
-import gov.nasa.worldwind.util.*;
import java.net.*;
@@ -19,37 +16,15 @@ public class OSMMapnikLayer extends BasicMercatorTiledImageLayer
{
public OSMMapnikLayer()
{
- super(makeLevels());
+ super("h", "Earth/OSM-Mercator/OpenStreetMap Mapnik", 19, 256, false, ".png", new URLBuilder());
}
- private static LevelSet makeLevels()
+ private static class URLBuilder extends MercatorTileUrlBuilder
{
- AVList params = new AVListImpl();
-
- params.setValue(AVKey.TILE_WIDTH, 256);
- params.setValue(AVKey.TILE_HEIGHT, 256);
- params.setValue(AVKey.DATA_CACHE_NAME, "Earth/OSM-Mercator/OpenStreetMap Mapnik");
- params.setValue(AVKey.SERVICE, "http://a.tile.openstreetmap.org/");
- params.setValue(AVKey.DATASET_NAME, "h");
- params.setValue(AVKey.FORMAT_SUFFIX, ".png");
- params.setValue(AVKey.NUM_LEVELS, 16);
- params.setValue(AVKey.NUM_EMPTY_LEVELS, 0);
- 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, new URLBuilder());
-
- return new LevelSet(params);
- }
-
- private static class URLBuilder implements TileUrlBuilder
- {
- public URL getURL(Tile tile, String imageFormat)
- throws MalformedURLException
+ @Override
+ protected URL getMercatorURL(int x, int y, int z) throws MalformedURLException
{
- return new URL(tile.getLevel().getService()
- + (tile.getLevelNumber() + 3) + "/" + tile.getColumn() + "/"
- + ((1 << (tile.getLevelNumber()) + 3) - 1 - tile.getRow()) + ".png");
+ return new URL("https://a.tile.openstreetmap.org/" + z + "/" + x + "/" + y + ".png");
}
}
diff --git a/src/gov/nasa/worldwind/layers/Earth/OpenTopoMapLayer.java b/src/gov/nasa/worldwind/layers/Earth/OpenTopoMapLayer.java
new file mode 100644
index 0000000000..b948cd84ce
--- /dev/null
+++ b/src/gov/nasa/worldwind/layers/Earth/OpenTopoMapLayer.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2012 United States Government as represented by the Administrator of the
+ * National Aeronautics and Space Administration.
+ * All Rights Reserved.
+ */
+package gov.nasa.worldwind.layers.Earth;
+
+import gov.nasa.worldwind.layers.mercator.*;
+
+import java.net.*;
+
+/**
+ * @author Sufaev
+ */
+public class OpenTopoMapLayer extends BasicMercatorTiledImageLayer
+{
+ public OpenTopoMapLayer()
+ {
+ super("otm", "Earth/OpenTopoMap", 17, 256, false, ".png", new URLBuilder());
+ }
+
+ private static class URLBuilder extends MercatorTileUrlBuilder
+ {
+ @Override
+ protected URL getMercatorURL(int x, int y, int z) throws MalformedURLException
+ {
+ return new URL("https://a.tile.opentopomap.org/" + z + "/" + x + "/" + y + ".png");
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return "OpenTopoMap";
+ }
+}
diff --git a/src/gov/nasa/worldwind/layers/Earth/WikimapiaLayer.java b/src/gov/nasa/worldwind/layers/Earth/WikimapiaLayer.java
new file mode 100644
index 0000000000..6cf1ca0130
--- /dev/null
+++ b/src/gov/nasa/worldwind/layers/Earth/WikimapiaLayer.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2012 United States Government as represented by the Administrator of the
+ * National Aeronautics and Space Administration.
+ * All Rights Reserved.
+ */
+package gov.nasa.worldwind.layers.Earth;
+
+import gov.nasa.worldwind.layers.mercator.*;
+
+import java.net.*;
+
+/**
+ * @author Sufaev
+ */
+public class WikimapiaLayer extends BasicMercatorTiledImageLayer
+{
+ public enum Type {MAP, HYBRID}
+
+ public WikimapiaLayer()
+ {
+ super("wm", "Earth/Wikimapia", 19, 256, true, ".png", new URLBuilder());
+ }
+
+ private static class URLBuilder extends MercatorTileUrlBuilder
+ {
+ private Type type;
+
+ private URLBuilder()
+ {
+ this.type = Type.HYBRID;
+ }
+
+ @Override
+ protected URL getMercatorURL(int x, int y, int z) throws MalformedURLException
+ {
+ int i = x % 4 + (y % 4) * 4;
+ return new URL("http://i" + i + ".wikimapia.org/?lng=0&x=" + x + "&y=" + y + "&zoom=" + z + "&type=" + this.type.name().toLowerCase());
+ }
+ }
+
+ public void setType(String type)
+ {
+ URLBuilder urlBuilder = (URLBuilder)getURLBuilder();
+ urlBuilder.type = Type.valueOf(type);
+
+ // Toggle overlay based on whether it is a hybrid map or not.
+ boolean isHybrid = urlBuilder.type.equals(Type.HYBRID);
+ setUseTransparentTextures(isHybrid);
+ }
+
+ public String getType()
+ {
+ URLBuilder urlBuilder = (URLBuilder)getURLBuilder();
+ return urlBuilder.type.name();
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Wikimapia";
+ }
+}
\ No newline at end of file
diff --git a/src/gov/nasa/worldwind/layers/mercator/BasicMercatorTiledImageLayer.java b/src/gov/nasa/worldwind/layers/mercator/BasicMercatorTiledImageLayer.java
index 62a045f6b0..ce91b6a9e6 100644
--- a/src/gov/nasa/worldwind/layers/mercator/BasicMercatorTiledImageLayer.java
+++ b/src/gov/nasa/worldwind/layers/mercator/BasicMercatorTiledImageLayer.java
@@ -3,490 +3,177 @@
* National Aeronautics and Space Administration.
* All Rights Reserved.
*/
-
package gov.nasa.worldwind.layers.mercator;
-import com.jogamp.opengl.util.texture.*;
-import gov.nasa.worldwind.*;
import gov.nasa.worldwind.avlist.*;
-import gov.nasa.worldwind.cache.*;
import gov.nasa.worldwind.geom.*;
+import gov.nasa.worldwind.layers.*;
import gov.nasa.worldwind.render.DrawContext;
-import gov.nasa.worldwind.retrieve.*;
import gov.nasa.worldwind.util.*;
import javax.imageio.ImageIO;
import java.awt.image.*;
import java.io.*;
-import java.net.*;
-import java.nio.ByteBuffer;
+import java.util.ArrayList;
/**
- * BasicTiledImageLayer modified 2009-02-03 to add support for Mercator projections.
- *
- * @author tag
- * @version $Id: BasicMercatorTiledImageLayer.java 1171 2013-02-11 21:45:02Z dcollins $
+ * @author Sufaev
*/
-public class BasicMercatorTiledImageLayer extends MercatorTiledImageLayer
+public class BasicMercatorTiledImageLayer extends BasicTiledImageLayer
{
- private final Object fileLock = new Object();
-
- public BasicMercatorTiledImageLayer(LevelSet levelSet)
+ private static LevelSet makeLevels(String datasetName, String dataCacheName, int numLevels, int tileSize, String formatSuffix, MercatorTileUrlBuilder buider)
{
- super(levelSet);
-
- if (!WorldWind.getMemoryCacheSet().containsCache(MercatorTextureTile.class.getName()))
- {
- long size = Configuration.getLongValue(
- AVKey.TEXTURE_IMAGE_CACHE_SIZE, 3000000L);
- MemoryCache cache = new BasicMemoryCache((long) (0.85 * size), size);
- cache.setName("Texture Tiles");
- WorldWind.getMemoryCacheSet().addCache(MercatorTextureTile.class.getName(), cache);
- }
+ double delta = Angle.POS360.degrees / (1 << buider.getFirstLevelOffset());
+ AVList params = new AVListImpl();
+ params.setValue(AVKey.SECTOR, new MercatorSector(-1.0, 1.0, Angle.NEG180, Angle.POS180));
+ params.setValue(AVKey.LEVEL_ZERO_TILE_DELTA, new LatLon(Angle.fromDegrees(delta / 2), Angle.fromDegrees(delta)));
+ params.setValue(AVKey.NUM_LEVELS, numLevels - buider.getFirstLevelOffset());
+ params.setValue(AVKey.FORMAT_SUFFIX, formatSuffix);
+ params.setValue(AVKey.TILE_WIDTH, tileSize);
+ params.setValue(AVKey.TILE_HEIGHT, tileSize);
+ params.setValue(AVKey.DATASET_NAME, datasetName);
+ params.setValue(AVKey.DATA_CACHE_NAME, dataCacheName);
+ params.setValue(AVKey.TILE_URL_BUILDER, buider);
+ return new LevelSet(params);
}
- public BasicMercatorTiledImageLayer(AVList params)
+ public BasicMercatorTiledImageLayer(String datasetName, String dataCacheName, int numLevels, int tileSize, boolean overlay, String formatSuffix, MercatorTileUrlBuilder builder)
{
- this(new LevelSet(params));
- this.setValue(AVKey.CONSTRUCTION_PARAMETERS, params);
+ this(makeLevels(datasetName, dataCacheName, numLevels, tileSize, formatSuffix, builder));
+ setUseTransparentTextures(overlay);
}
- protected void forceTextureLoad(MercatorTextureTile tile)
+ public BasicMercatorTiledImageLayer(LevelSet levelSet)
{
- final URL textureURL = this.getDataFileStore().findFile(
- tile.getPath(), true);
-
- if (textureURL != null && !this.isTextureExpired(tile, textureURL))
- {
- this.loadTexture(tile, textureURL);
- }
+ super(levelSet);
}
- protected void requestTexture(DrawContext dc, MercatorTextureTile tile)
+ @Override
+ protected void createTopLevelTiles()
{
- Vec4 centroid = tile.getCentroidPoint(dc.getGlobe());
- if (this.getReferencePoint() != null)
- tile.setPriority(centroid.distanceTo3(this.getReferencePoint()));
+ MercatorSector sector = (MercatorSector) this.levels.getSector();
- RequestTask task = new RequestTask(tile, this);
- this.getRequestQ().add(task);
- }
+ Level level = levels.getFirstLevel();
+ Angle dLat = level.getTileDelta().getLatitude();
+ Angle dLon = level.getTileDelta().getLongitude();
- private static class RequestTask implements Runnable,
- Comparable
- {
- private final BasicMercatorTiledImageLayer layer;
- private final MercatorTextureTile tile;
+ Angle latOrigin = this.levels.getTileOrigin().getLatitude();
+ Angle lonOrigin = this.levels.getTileOrigin().getLongitude();
- private RequestTask(MercatorTextureTile tile,
- BasicMercatorTiledImageLayer layer)
- {
- this.layer = layer;
- this.tile = tile;
- }
+ // Determine the row and column offset from the common WorldWind global tiling origin.
+ int firstRow = Tile.computeRow(dLat, sector.getMinLatitude(), latOrigin);
+ int firstCol = Tile.computeColumn(dLon, sector.getMinLongitude(), lonOrigin);
+ int lastRow = Tile.computeRow(dLat, sector.getMaxLatitude(), latOrigin);
+ int lastCol = Tile.computeColumn(dLon, sector.getMaxLongitude(), lonOrigin);
- public void run()
- {
- // TODO: check to ensure load is still needed
+ int nLatTiles = lastRow - firstRow + 1;
+ int nLonTiles = lastCol - firstCol + 1;
- final java.net.URL textureURL = this.layer.getDataFileStore()
- .findFile(tile.getPath(), false);
- if (textureURL != null
- && !this.layer.isTextureExpired(tile, textureURL))
- {
- if (this.layer.loadTexture(tile, textureURL))
- {
- layer.getLevels().unmarkResourceAbsent(tile);
- this.layer.firePropertyChange(AVKey.LAYER, null, this);
- return;
- }
- else
- {
- // Assume that something's wrong with the file and delete it.
- this.layer.getDataFileStore().removeFile(
- textureURL);
- layer.getLevels().markResourceAbsent(tile);
- String message = Logging.getMessage(
- "generic.DeletedCorruptDataFile", textureURL);
- Logging.logger().info(message);
- }
- }
-
- this.layer.downloadTexture(this.tile);
- }
+ this.topLevels = new ArrayList(nLatTiles * nLonTiles);
- /**
- * @param that the task to compare
- *
- * @return -1 if this less than that, 1 if greater than, 0 if equal
- *
- * @throws IllegalArgumentException if that is null
- */
- public int compareTo(RequestTask that)
+ double deltaLat = dLat.degrees / 90;
+ double d1 = sector.getMinLatPercent() + deltaLat * firstRow;
+ for (int row = firstRow; row <= lastRow; row++)
{
- if (that == null)
+ double d2 = d1 + deltaLat;
+ Angle t1 = Tile.computeColumnLongitude(firstCol, dLon, lonOrigin);
+ for (int col = firstCol; col <= lastCol; col++)
{
- String msg = Logging.getMessage("nullValue.RequestTaskIsNull");
- Logging.logger().severe(msg);
- throw new IllegalArgumentException(msg);
+ Angle t2;
+ t2 = t1.add(dLon);
+ this.topLevels.add(new MercatorTextureTile(new MercatorSector(d1, d2, t1, t2), level, row, col));
+ t1 = t2;
}
- return this.tile.getPriority() == that.tile.getPriority() ? 0
- : this.tile.getPriority() < that.tile.getPriority() ? -1
- : 1;
- }
-
- public boolean equals(Object o)
- {
- if (this == o)
- return true;
- if (o == null || getClass() != o.getClass())
- return false;
-
- final RequestTask that = (RequestTask) o;
-
- // Don't include layer in comparison so that requests are shared among layers
- return !(tile != null ? !tile.equals(that.tile) : that.tile != null);
- }
-
- public int hashCode()
- {
- return (tile != null ? tile.hashCode() : 0);
- }
-
- public String toString()
- {
- return this.tile.toString();
+ d1 = d2;
}
}
-
- private boolean isTextureExpired(MercatorTextureTile tile,
- java.net.URL textureURL)
+
+ protected MercatorTileUrlBuilder getURLBuilder()
{
- if (!WWIO.isFileOutOfDate(textureURL, tile.getLevel().getExpiryTime()))
- return false;
-
- // The file has expired. Delete it.
- this.getDataFileStore().removeFile(textureURL);
- String message = Logging.getMessage("generic.DataFileExpired",
- textureURL);
- Logging.logger().fine(message);
- return true;
+ LevelSet levelSet = getLevels();
+ Level firstLevel = levelSet.getFirstLevel();
+ AVList params = firstLevel.getParams();
+ Object value = params.getValue(AVKey.TILE_URL_BUILDER);
+ MercatorTileUrlBuilder urlBuilder = (MercatorTileUrlBuilder)value;
+ return urlBuilder;
}
- private boolean loadTexture(MercatorTextureTile tile,
- java.net.URL textureURL)
+ @Override
+ protected boolean needToSplit(DrawContext dc, Sector sector, Level level)
{
- TextureData textureData;
-
- synchronized (this.fileLock)
- {
- textureData = readTexture(textureURL, this.isUseMipMaps());
- }
-
- if (textureData == null)
- return false;
-
- tile.setTextureData(textureData);
- if (tile.getLevelNumber() != 0 || !this.isRetainLevelZeroTiles())
- this.addTileToCache(tile);
-
- return true;
+ double texelSize = level.getTexelSize() * dc.getGlobe().getRadius();
+ double pixelSize = dc.getView().computePixelSizeAtDistance(sector.distanceTo(dc, dc.getView().getEyePoint()));
+ return texelSize > pixelSize * this.getDetailFactor();
}
- private static TextureData readTexture(java.net.URL url, boolean useMipMaps)
+ @Override
+ protected DownloadPostProcessor createDownloadPostProcessor(TextureTile tile)
{
- try
- {
- return OGLUtil.newTextureData(Configuration.getMaxCompatibleGLProfile(), url, useMipMaps);
- }
- catch (Exception e)
- {
- String msg = Logging.getMessage("layers.TextureLayer.ExceptionAttemptingToReadTextureFile", url.toString());
- Logging.logger().log(java.util.logging.Level.SEVERE, msg, e);
- return null;
- }
+ return new MercatorDownloadPostProcessor((MercatorTextureTile) tile, this);
}
- private void addTileToCache(MercatorTextureTile tile)
+ private static class MercatorDownloadPostProcessor extends DownloadPostProcessor
{
- WorldWind.getMemoryCache(MercatorTextureTile.class.getName()).add(
- tile.getTileKey(), tile);
- }
-
- protected void downloadTexture(final MercatorTextureTile tile)
- {
- if (!WorldWind.getRetrievalService().isAvailable())
- return;
-
- java.net.URL url;
- try
- {
- url = tile.getResourceURL();
- if (url == null)
- return;
-
- if (WorldWind.getNetworkStatus().isHostUnavailable(url))
- 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 ("http".equalsIgnoreCase(url.getProtocol()))
- {
- retriever = new HTTPRetriever(url, new DownloadPostProcessor(tile, this));
- retriever.setValue(URLRetriever.EXTRACT_ZIP_ENTRY, "true"); // supports legacy layers
- }
- else
- {
- Logging.logger().severe(
- Logging.getMessage("layers.TextureLayer.UnknownRetrievalProtocol", url.toString()));
- return;
- }
-
- // 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());
- }
- private void saveBuffer(java.nio.ByteBuffer buffer, java.io.File outFile)
- throws java.io.IOException
- {
- synchronized (this.fileLock) // synchronized with read of file in RequestTask.run()
+ MercatorDownloadPostProcessor(MercatorTextureTile tile, BasicMercatorTiledImageLayer layer)
{
- WWIO.saveBuffer(buffer, outFile);
+ super(tile, layer);
}
- }
- private static class DownloadPostProcessor implements
- RetrievalPostProcessor
- {
- // TODO: Rewrite this inner class, factoring out the generic parts.
- private final MercatorTextureTile tile;
- private final BasicMercatorTiledImageLayer layer;
-
- public DownloadPostProcessor(MercatorTextureTile tile,
- BasicMercatorTiledImageLayer layer)
+ @Override
+ protected BufferedImage transformPixels()
{
- this.tile = tile;
- this.layer = layer;
- }
+ // Make parent transformations
+ BufferedImage image = super.transformPixels();
- public ByteBuffer run(Retriever retriever)
- {
- if (retriever == null)
+ // Read image from buffer
+ if (image == null)
{
- String msg = Logging.getMessage("nullValue.RetrieverIsNull");
- Logging.logger().severe(msg);
- throw new IllegalArgumentException(msg);
+ try
+ {
+ image = ImageIO.read(new ByteArrayInputStream(this.getRetriever().getBuffer().array()));
+ }
+ catch (IOException ignored)
+ {
+ return null;
+ }
}
- try
+ // Transform mercator tile to equirectangular projection
+ if (image != null)
{
- if (!retriever.getState().equals(
- Retriever.RETRIEVER_STATE_SUCCESSFUL))
- return null;
-
- URLRetriever r = (URLRetriever) retriever;
- ByteBuffer buffer = r.getBuffer();
-
- if (retriever instanceof HTTPRetriever)
+ int type = image.getType();
+ if (type == BufferedImage.TYPE_CUSTOM)
{
- HTTPRetriever htr = (HTTPRetriever) retriever;
- if (htr.getResponseCode() == HttpURLConnection.HTTP_NO_CONTENT)
- {
- // Mark tile as missing to avoid excessive attempts
- this.layer.getLevels().markResourceAbsent(this.tile);
- return null;
- }
- else if (htr.getResponseCode() != HttpURLConnection.HTTP_OK)
- {
- // Also mark tile as missing, but for an unknown reason.
- this.layer.getLevels().markResourceAbsent(this.tile);
- return null;
- }
+ type = BufferedImage.TYPE_INT_RGB;
}
-
- final File outFile = this.layer.getDataFileStore().newFile(
- this.tile.getPath());
- if (outFile == null)
- return null;
-
- if (outFile.exists())
- return buffer;
-
- // TODO: Better, more generic and flexible handling of file-format type
- if (buffer != null)
+ else if (type == BufferedImage.TYPE_BYTE_INDEXED)
{
- String contentType = r.getContentType();
- if (contentType == null)
- {
- // TODO: logger message
- return null;
- }
-
- if (contentType.contains("xml")
- || contentType.contains("html")
- || contentType.contains("text"))
- {
- this.layer.getLevels().markResourceAbsent(this.tile);
-
- StringBuffer sb = new StringBuffer();
- while (buffer.hasRemaining())
- {
- sb.append((char) buffer.get());
- }
- // TODO: parse out the message if the content is xml or html.
- Logging.logger().severe(sb.toString());
-
- return null;
- }
- else if (contentType.contains("dds"))
- {
- this.layer.saveBuffer(buffer, outFile);
- }
- else if (contentType.contains("zip"))
- {
- // Assume it's zipped DDS, which the retriever would have unzipped into the buffer.
- this.layer.saveBuffer(buffer, outFile);
- }
-// else if (outFile.getName().endsWith(".dds"))
-// {
-// // Convert to DDS and save the result.
-// buffer = DDSConverter.convertToDDS(buffer, contentType);
-// if (buffer != null)
-// this.layer.saveBuffer(buffer, outFile);
-// }
- else if (contentType.contains("image"))
- {
- BufferedImage image = this.layer.convertBufferToImage(buffer);
- if (image != null)
- {
- image = this.layer.modifyImage(image);
- if (this.layer.isTileValid(image))
- {
- if (!this.layer.transformAndSave(image, tile.getMercatorSector(), outFile))
- image = null;
- }
- else
- {
- this.layer.getLevels().markResourceAbsent(this.tile);
- return null;
- }
- }
- if (image == null)
- {
- // Just save whatever it is to the cache.
- this.layer.saveBuffer(buffer, outFile);
- }
- }
+ type = BufferedImage.TYPE_INT_ARGB;
+ }
- if (buffer != null)
+ BufferedImage trans = new BufferedImage(image.getWidth(), image.getHeight(), type);
+ double miny = ((MercatorSector) tile.getSector()).getMinLatPercent();
+ double maxy = ((MercatorSector) tile.getSector()).getMaxLatPercent();
+ for (int y = 0; y < image.getHeight(); y++)
+ {
+ double sy = 1.0 - y / (double) (image.getHeight() - 1);
+ Angle lat = Angle.fromRadians(sy * tile.getSector().getDeltaLatRadians() + tile.getSector().getMinLatitude().radians);
+ double dy = 1.0 - (MercatorSector.gudermannianInverse(lat) - miny) / (maxy - miny);
+ dy = Math.max(0.0, Math.min(1.0, dy));
+ int iy = (int) (dy * (image.getHeight() - 1));
+ for (int x = 0; x < image.getWidth(); x++)
{
- this.layer.firePropertyChange(AVKey.LAYER, null, this);
+ trans.setRGB(x, y, image.getRGB(x, iy));
}
- return buffer;
}
- }
- catch (java.io.IOException e)
- {
- this.layer.getLevels().markResourceAbsent(this.tile);
- Logging.logger().log(java.util.logging.Level.SEVERE,
- Logging.getMessage("layers.TextureLayer.ExceptionSavingRetrievedTextureFile", tile.getPath()), e);
- }
- return null;
- }
- }
- protected boolean isTileValid(BufferedImage image)
- {
- //override in subclass to check image tile
- //if false is returned, then tile is marked absent
- return true;
- }
-
- protected BufferedImage modifyImage(BufferedImage image)
- {
- //override in subclass to modify image tile
- return image;
- }
-
- private BufferedImage convertBufferToImage(ByteBuffer buffer)
- {
- try
- {
- InputStream is = new ByteArrayInputStream(buffer.array());
- return ImageIO.read(is);
- }
- catch (IOException e)
- {
- return null;
- }
- }
-
- private boolean transformAndSave(BufferedImage image, MercatorSector sector,
- File outFile)
- {
- try
- {
- 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 trans;
}
- }
- catch (IOException e)
- {
- return false;
- }
- }
-
- private BufferedImage transform(BufferedImage image, MercatorSector sector)
- {
- int type = image.getType();
- if (type == 0)
- type = BufferedImage.TYPE_INT_RGB;
- BufferedImage trans = new BufferedImage(image.getWidth(), image
- .getHeight(), type);
- double miny = sector.getMinLatPercent();
- double maxy = sector.getMaxLatPercent();
- for (int y = 0; y < image.getHeight(); y++)
- {
- double sy = 1.0 - y / (double) (image.getHeight() - 1);
- Angle lat = Angle.fromRadians(sy * sector.getDeltaLatRadians()
- + sector.getMinLatitude().radians);
- double dy = 1.0 - (MercatorSector.gudermannianInverse(lat) - miny)
- / (maxy - miny);
- dy = Math.max(0.0, Math.min(1.0, dy));
- int iy = (int) (dy * (image.getHeight() - 1));
-
- for (int x = 0; x < image.getWidth(); x++)
+ else
{
- trans.setRGB(x, y, image.getRGB(x, iy));
+ return null;
}
}
- return trans;
}
-}
+}
\ No newline at end of file
diff --git a/src/gov/nasa/worldwind/layers/mercator/MercatorTextureTile.java b/src/gov/nasa/worldwind/layers/mercator/MercatorTextureTile.java
index 8f8a8fd562..d2287d6295 100644
--- a/src/gov/nasa/worldwind/layers/mercator/MercatorTextureTile.java
+++ b/src/gov/nasa/worldwind/layers/mercator/MercatorTextureTile.java
@@ -5,7 +5,6 @@
*/
package gov.nasa.worldwind.layers.mercator;
-import gov.nasa.worldwind.WorldWind;
import gov.nasa.worldwind.geom.Angle;
import gov.nasa.worldwind.layers.TextureTile;
import gov.nasa.worldwind.util.*;
@@ -15,17 +14,21 @@
*/
public class MercatorTextureTile extends TextureTile
{
- private MercatorSector mercatorSector;
public MercatorTextureTile(MercatorSector mercatorSector, Level level,
int row, int col)
{
super(mercatorSector, level, row, col);
- this.mercatorSector = mercatorSector;
}
@Override
- public MercatorTextureTile[] createSubTiles(Level nextLevel)
+ public MercatorSector getSector()
+ {
+ return (MercatorSector) super.getSector();
+ }
+
+ @Override
+ public TextureTile[] createSubTiles(Level nextLevel)
{
if (nextLevel == null)
{
@@ -33,8 +36,8 @@ public MercatorTextureTile[] createSubTiles(Level nextLevel)
Logging.logger().severe(msg);
throw new IllegalArgumentException(msg);
}
- double d0 = this.getMercatorSector().getMinLatPercent();
- double d2 = this.getMercatorSector().getMaxLatPercent();
+ double d0 = this.getSector().getMinLatPercent();
+ double d2 = this.getSector().getMaxLatPercent();
double d1 = d0 + (d2 - d0) / 2.0;
Angle t0 = this.getSector().getMinLongitude();
@@ -43,58 +46,27 @@ public MercatorTextureTile[] createSubTiles(Level nextLevel)
String nextLevelCacheName = nextLevel.getCacheName();
int nextLevelNum = nextLevel.getLevelNumber();
- int row = this.getRow();
- int col = this.getColumn();
- MercatorTextureTile[] subTiles = new MercatorTextureTile[4];
+ int northRow = 2 * this.getRow();
+ int southRow = northRow + 1;
+ int westCol = 2 * this.getColumn();
+ int eastCol = westCol + 1;
- TileKey key = new TileKey(nextLevelNum, 2 * row, 2 * col,
- nextLevelCacheName);
- MercatorTextureTile subTile = this.getTileFromMemoryCache(key);
- if (subTile != null)
- subTiles[0] = subTile;
- else
- subTiles[0] = new MercatorTextureTile(new MercatorSector(d0, d1,
- t0, t1), nextLevel, 2 * row, 2 * col);
+ TextureTile[] subTiles = new TextureTile[4];
- key = new TileKey(nextLevelNum, 2 * row, 2 * col + 1,
- nextLevelCacheName);
- subTile = this.getTileFromMemoryCache(key);
- if (subTile != null)
- subTiles[1] = subTile;
- else
- subTiles[1] = new MercatorTextureTile(new MercatorSector(d0, d1,
- t1, t2), nextLevel, 2 * row, 2 * col + 1);
+ TextureTile subTile = this.getTileFromMemoryCache(new TileKey(nextLevelNum, northRow, westCol, nextLevelCacheName));
+ subTiles[0] = subTile != null ? subTile : new MercatorTextureTile(new MercatorSector(d0, d1, t0, t1), nextLevel, northRow, westCol);
- key = new TileKey(nextLevelNum, 2 * row + 1, 2 * col,
- nextLevelCacheName);
- subTile = this.getTileFromMemoryCache(key);
- if (subTile != null)
- subTiles[2] = subTile;
- else
- subTiles[2] = new MercatorTextureTile(new MercatorSector(d1, d2,
- t0, t1), nextLevel, 2 * row + 1, 2 * col);
+ subTile = this.getTileFromMemoryCache(new TileKey(nextLevelNum, northRow, eastCol, nextLevelCacheName));
+ subTiles[1] = subTile != null ? subTile : new MercatorTextureTile(new MercatorSector(d0, d1, t1, t2), nextLevel, northRow, eastCol);
- key = new TileKey(nextLevelNum, 2 * row + 1, 2 * col + 1,
- nextLevelCacheName);
- subTile = this.getTileFromMemoryCache(key);
- if (subTile != null)
- subTiles[3] = subTile;
- else
- subTiles[3] = new MercatorTextureTile(new MercatorSector(d1, d2,
- t1, t2), nextLevel, 2 * row + 1, 2 * col + 1);
+ subTile = this.getTileFromMemoryCache(new TileKey(nextLevelNum, southRow, westCol, nextLevelCacheName));
+ subTiles[2] = subTile != null ? subTile : new MercatorTextureTile(new MercatorSector(d1, d2, t0, t1), nextLevel, southRow, westCol);
- return subTiles;
- }
+ subTile = this.getTileFromMemoryCache(new TileKey(nextLevelNum, southRow, eastCol, nextLevelCacheName));
+ subTiles[3] = subTile != null ? subTile : new MercatorTextureTile(new MercatorSector(d1, d2, t1, t2), nextLevel, southRow, eastCol);
- protected MercatorTextureTile getTileFromMemoryCache(TileKey tileKey)
- {
- return (MercatorTextureTile) WorldWind.getMemoryCache(
- MercatorTextureTile.class.getName()).getObject(tileKey);
+ return subTiles;
}
- public MercatorSector getMercatorSector()
- {
- return mercatorSector;
- }
-}
+}
\ No newline at end of file
diff --git a/src/gov/nasa/worldwind/layers/mercator/MercatorTileUrlBuilder.java b/src/gov/nasa/worldwind/layers/mercator/MercatorTileUrlBuilder.java
new file mode 100644
index 0000000000..66d6918ea4
--- /dev/null
+++ b/src/gov/nasa/worldwind/layers/mercator/MercatorTileUrlBuilder.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2019 United States Government as represented by the Administrator of the
+ * National Aeronautics and Space Administration.
+ * All Rights Reserved.
+ */
+
+package gov.nasa.worldwind.layers.mercator;
+
+import gov.nasa.worldwind.util.*;
+
+import java.net.*;
+
+/**
+ * @author Sufaev
+ */
+public abstract class MercatorTileUrlBuilder implements TileUrlBuilder
+{
+ private static final int DEFAULT_FIRST_LEVEL_OFFSET = 3;
+
+ private int firstLevelOffset;
+
+ protected MercatorTileUrlBuilder()
+ {
+ this.firstLevelOffset = DEFAULT_FIRST_LEVEL_OFFSET;
+ }
+
+ public MercatorTileUrlBuilder setFirstLevelOffset(int firstLevelOffset) {
+ this.firstLevelOffset = firstLevelOffset;
+ return this;
+ }
+
+ public int getFirstLevelOffset() {
+ return firstLevelOffset;
+ }
+
+ @Override
+ public URL getURL(Tile tile, String imageFormat) throws MalformedURLException
+ {
+ return getMercatorURL(tile.getColumn(), (1 << (tile.getLevelNumber() + firstLevelOffset)) - 1 - tile.getRow(), tile.getLevelNumber() + firstLevelOffset);
+ }
+
+ protected abstract URL getMercatorURL(int x, int y, int z) throws MalformedURLException;
+}
diff --git a/src/gov/nasa/worldwind/layers/mercator/MercatorTiledImageLayer.java b/src/gov/nasa/worldwind/layers/mercator/MercatorTiledImageLayer.java
deleted file mode 100644
index c81ebda904..0000000000
--- a/src/gov/nasa/worldwind/layers/mercator/MercatorTiledImageLayer.java
+++ /dev/null
@@ -1,1139 +0,0 @@
-/*
- * Copyright (C) 2012 United States Government as represented by the Administrator of the
- * National Aeronautics and Space Administration.
- * All Rights Reserved.
- */
-package gov.nasa.worldwind.layers.mercator;
-
-import gov.nasa.worldwind.*;
-import gov.nasa.worldwind.geom.*;
-import gov.nasa.worldwind.geom.Cylinder;
-import gov.nasa.worldwind.globes.Globe;
-import gov.nasa.worldwind.layers.AbstractLayer;
-import gov.nasa.worldwind.render.*;
-import gov.nasa.worldwind.retrieve.*;
-import gov.nasa.worldwind.util.*;
-
-import javax.imageio.ImageIO;
-import com.jogamp.opengl.*;
-import java.awt.*;
-import java.awt.geom.*;
-import java.awt.image.*;
-import java.io.*;
-import java.net.*;
-import java.nio.ByteBuffer;
-import java.util.*;
-import java.util.List;
-import java.util.concurrent.PriorityBlockingQueue;
-
-/**
- * TiledImageLayer modified 2009-02-03 to add support for Mercator projections.
- *
- * @author tag
- * @version $Id: MercatorTiledImageLayer.java 2053 2014-06-10 20:16:57Z tgaskins $
- */
-public abstract class MercatorTiledImageLayer extends AbstractLayer
-{
- // Infrastructure
- private static final LevelComparer levelComparer = new LevelComparer();
- private final LevelSet levels;
- private ArrayList topLevels;
- private boolean forceLevelZeroLoads = false;
- private boolean levelZeroLoaded = false;
- private boolean retainLevelZeroTiles = false;
- private String tileCountName;
- @SuppressWarnings({"FieldCanBeLocal"})
- private double splitScale = 0.9; // TODO: Make configurable
- private boolean useMipMaps = false;
- private ArrayList supportedImageFormats = new ArrayList();
-
- // Diagnostic flags
- private boolean showImageTileOutlines = false;
- private boolean drawTileBoundaries = false;
- private boolean useTransparentTextures = false;
- private boolean drawTileIDs = false;
- private boolean drawBoundingVolumes = false;
-
- // Stuff computed each frame
- private ArrayList currentTiles = new ArrayList();
- private MercatorTextureTile currentResourceTile;
- private Vec4 referencePoint;
- private boolean atMaxResolution = false;
- private PriorityBlockingQueue requestQ = new PriorityBlockingQueue(
- 200);
-
- abstract protected void requestTexture(DrawContext dc, MercatorTextureTile tile);
-
- abstract protected void forceTextureLoad(MercatorTextureTile tile);
-
- public MercatorTiledImageLayer(LevelSet levelSet)
- {
- if (levelSet == null)
- {
- String message = Logging.getMessage("nullValue.LevelSetIsNull");
- Logging.logger().severe(message);
- throw new IllegalArgumentException(message);
- }
-
- this.levels = new LevelSet(levelSet); // the caller's levelSet may change internally, so we copy it.
-
- this.createTopLevelTiles();
-
- this.setPickEnabled(false); // textures are assumed to be terrain unless specifically indicated otherwise.
- this.tileCountName = this.getName() + " Tiles";
- }
-
- @Override
- public void setName(String name)
- {
- super.setName(name);
- this.tileCountName = this.getName() + " Tiles";
- }
-
- public boolean isUseTransparentTextures()
- {
- return this.useTransparentTextures;
- }
-
- public void setUseTransparentTextures(boolean useTransparentTextures)
- {
- this.useTransparentTextures = useTransparentTextures;
- }
-
- public boolean isForceLevelZeroLoads()
- {
- return this.forceLevelZeroLoads;
- }
-
- public void setForceLevelZeroLoads(boolean forceLevelZeroLoads)
- {
- this.forceLevelZeroLoads = forceLevelZeroLoads;
- }
-
- public boolean isRetainLevelZeroTiles()
- {
- return retainLevelZeroTiles;
- }
-
- public void setRetainLevelZeroTiles(boolean retainLevelZeroTiles)
- {
- this.retainLevelZeroTiles = retainLevelZeroTiles;
- }
-
- public boolean isDrawTileIDs()
- {
- return drawTileIDs;
- }
-
- public void setDrawTileIDs(boolean drawTileIDs)
- {
- this.drawTileIDs = drawTileIDs;
- }
-
- public boolean isDrawTileBoundaries()
- {
- return drawTileBoundaries;
- }
-
- public void setDrawTileBoundaries(boolean drawTileBoundaries)
- {
- this.drawTileBoundaries = drawTileBoundaries;
- }
-
- public boolean isShowImageTileOutlines()
- {
- return showImageTileOutlines;
- }
-
- public void setShowImageTileOutlines(boolean showImageTileOutlines)
- {
- this.showImageTileOutlines = showImageTileOutlines;
- }
-
- public boolean isDrawBoundingVolumes()
- {
- return drawBoundingVolumes;
- }
-
- public void setDrawBoundingVolumes(boolean drawBoundingVolumes)
- {
- this.drawBoundingVolumes = drawBoundingVolumes;
- }
-
- protected LevelSet getLevels()
- {
- return levels;
- }
-
- protected PriorityBlockingQueue getRequestQ()
- {
- return requestQ;
- }
-
- public boolean isMultiResolution()
- {
- return this.getLevels() != null && this.getLevels().getNumLevels() > 1;
- }
-
- public boolean isAtMaxResolution()
- {
- return this.atMaxResolution;
- }
-
- public boolean isUseMipMaps()
- {
- return useMipMaps;
- }
-
- public void setUseMipMaps(boolean useMipMaps)
- {
- this.useMipMaps = useMipMaps;
- }
-
- private void createTopLevelTiles()
- {
- MercatorSector sector = (MercatorSector) this.levels.getSector();
-
- Level level = levels.getFirstLevel();
- Angle dLat = level.getTileDelta().getLatitude();
- Angle dLon = level.getTileDelta().getLongitude();
-
- Angle latOrigin = this.levels.getTileOrigin().getLatitude();
- Angle lonOrigin = this.levels.getTileOrigin().getLongitude();
-
- // Determine the row and column offset from the common WorldWind global tiling origin.
- int firstRow = Tile.computeRow(dLat, sector.getMinLatitude(), latOrigin);
- int firstCol = Tile.computeColumn(dLon, sector.getMinLongitude(), lonOrigin);
- int lastRow = Tile.computeRow(dLat, sector.getMaxLatitude(), latOrigin);
- int lastCol = Tile.computeColumn(dLon, sector.getMaxLongitude(), lonOrigin);
-
- int nLatTiles = lastRow - firstRow + 1;
- int nLonTiles = lastCol - firstCol + 1;
-
- this.topLevels = new ArrayList(nLatTiles
- * nLonTiles);
-
- //Angle p1 = Tile.computeRowLatitude(firstRow, dLat);
- double deltaLat = dLat.degrees / 90;
- double d1 = -1.0 + deltaLat * firstRow;
- for (int row = firstRow; row <= lastRow; row++)
- {
- //Angle p2;
- //p2 = p1.add(dLat);
- double d2 = d1 + deltaLat;
-
- Angle t1 = Tile.computeColumnLongitude(firstCol, dLon, lonOrigin);
- for (int col = firstCol; col <= lastCol; col++)
- {
- Angle t2;
- t2 = t1.add(dLon);
-
- this.topLevels.add(new MercatorTextureTile(new MercatorSector(
- d1, d2, t1, t2), level, row, col));
- t1 = t2;
- }
- d1 = d2;
- }
- }
-
- private void loadAllTopLevelTextures(DrawContext dc)
- {
- for (MercatorTextureTile tile : this.topLevels)
- {
- if (!tile.isTextureInMemory(dc.getTextureCache()))
- this.forceTextureLoad(tile);
- }
-
- this.levelZeroLoaded = true;
- }
-
- // ============== Tile Assembly ======================= //
- // ============== Tile Assembly ======================= //
- // ============== Tile Assembly ======================= //
-
- private void assembleTiles(DrawContext dc)
- {
- this.currentTiles.clear();
-
- for (MercatorTextureTile tile : this.topLevels)
- {
- if (this.isTileVisible(dc, tile))
- {
- this.currentResourceTile = null;
- this.addTileOrDescendants(dc, tile);
- }
- }
- }
-
- 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;
- }
- }
-
- private void addTile(DrawContext dc, MercatorTextureTile tile)
- {
- tile.setFallbackTile(null);
-
- if (tile.isTextureInMemory(dc.getTextureCache()))
- {
- // System.out.printf("Sector %s, min = %f, max = %f\n", tile.getSector(),
- // dc.getGlobe().getMinElevation(tile.getSector()), dc.getGlobe().getMaxElevation(tile.getSector()));
- this.addTileToCurrent(tile);
- return;
- }
-
- // Level 0 loads may be forced
- if (tile.getLevelNumber() == 0 && this.forceLevelZeroLoads
- && !tile.isTextureInMemory(dc.getTextureCache()))
- {
- this.forceTextureLoad(tile);
- if (tile.isTextureInMemory(dc.getTextureCache()))
- {
- this.addTileToCurrent(tile);
- return;
- }
- }
-
- // Tile's texture isn't available, so request it
- if (tile.getLevelNumber() < this.levels.getNumLevels())
- {
- // Request only tiles with data associated at this level
- if (!this.levels.isResourceAbsent(tile))
- this.requestTexture(dc, tile);
- }
-
- // Set up to use the currentResource tile's texture
- if (this.currentResourceTile != null)
- {
- if (this.currentResourceTile.getLevelNumber() == 0
- && this.forceLevelZeroLoads
- && !this.currentResourceTile.isTextureInMemory(dc
- .getTextureCache())
- && !this.currentResourceTile.isTextureInMemory(dc
- .getTextureCache()))
- this.forceTextureLoad(this.currentResourceTile);
-
- if (this.currentResourceTile
- .isTextureInMemory(dc.getTextureCache()))
- {
- tile.setFallbackTile(currentResourceTile);
- this.addTileToCurrent(tile);
- }
- }
- }
-
- private void addTileToCurrent(MercatorTextureTile tile)
- {
- this.currentTiles.add(tile);
- }
-
- private boolean isTileVisible(DrawContext dc, MercatorTextureTile tile)
- {
- // if (!(tile.getExtent(dc).intersects(dc.getView().getFrustumInModelCoordinates())
- // && (dc.getVisibleSector() == null || dc.getVisibleSector().intersects(tile.getSector()))))
- // return false;
- //
- // Position eyePos = dc.getView().getEyePosition();
- // LatLon centroid = tile.getSector().getCentroid();
- // Angle d = LatLon.greatCircleDistance(eyePos.getLatLon(), centroid);
- // if ((!tile.getLevelName().equals("0")) && d.compareTo(tile.getSector().getDeltaLat().multiply(2.5)) == 1)
- // return false;
- //
- // return true;
- //
- return tile.getExtent(dc).intersects(
- dc.getView().getFrustumInModelCoordinates())
- && (dc.getVisibleSector() == null || dc.getVisibleSector()
- .intersects(tile.getSector()));
- }
-
- //
- // private boolean meetsRenderCriteria2(DrawContext dc, TextureTile tile)
- // {
- // if (this.levels.isFinalLevel(tile.getLevelNumber()))
- // return true;
- //
- // Sector sector = tile.getSector();
- // Vec4[] corners = sector.computeCornerPoints(dc.getGlobe());
- // Vec4 centerPoint = sector.computeCenterPoint(dc.getGlobe());
- //
- // View view = dc.getView();
- // double d1 = view.getEyePoint().distanceTo3(corners[0]);
- // double d2 = view.getEyePoint().distanceTo3(corners[1]);
- // double d3 = view.getEyePoint().distanceTo3(corners[2]);
- // double d4 = view.getEyePoint().distanceTo3(corners[3]);
- // double d5 = view.getEyePoint().distanceTo3(centerPoint);
- //
- // double minDistance = d1;
- // if (d2 < minDistance)
- // minDistance = d2;
- // if (d3 < minDistance)
- // minDistance = d3;
- // if (d4 < minDistance)
- // minDistance = d4;
- // if (d5 < minDistance)
- // minDistance = d5;
- //
- // double r = 0;
- // if (minDistance == d1)
- // r = corners[0].getLength3();
- // if (minDistance == d2)
- // r = corners[1].getLength3();
- // if (minDistance == d3)
- // r = corners[2].getLength3();
- // if (minDistance == d4)
- // r = corners[3].getLength3();
- // if (minDistance == d5)
- // r = centerPoint.getLength3();
- //
- // double texelSize = tile.getLevel().getTexelSize(r);
- // double pixelSize = dc.getView().computePixelSizeAtDistance(minDistance);
- //
- // return 2 * pixelSize >= texelSize;
- // }
-
- private boolean meetsRenderCriteria(DrawContext dc, MercatorTextureTile tile)
- {
- return this.levels.isFinalLevel(tile.getLevelNumber())
- || !needToSplit(dc, tile.getSector());
- }
-
- private boolean needToSplit(DrawContext dc, Sector sector)
- {
- Vec4[] corners = sector.computeCornerPoints(dc.getGlobe(), dc.getVerticalExaggeration());
- Vec4 centerPoint = sector.computeCenterPoint(dc.getGlobe(), dc.getVerticalExaggeration());
-
- View view = dc.getView();
- double d1 = view.getEyePoint().distanceTo3(corners[0]);
- double d2 = view.getEyePoint().distanceTo3(corners[1]);
- double d3 = view.getEyePoint().distanceTo3(corners[2]);
- double d4 = view.getEyePoint().distanceTo3(corners[3]);
- double d5 = view.getEyePoint().distanceTo3(centerPoint);
-
- double minDistance = d1;
- if (d2 < minDistance)
- minDistance = d2;
- if (d3 < minDistance)
- minDistance = d3;
- if (d4 < minDistance)
- minDistance = d4;
- if (d5 < minDistance)
- minDistance = d5;
-
- double cellSize = (Math.PI * sector.getDeltaLatRadians() * dc
- .getGlobe().getRadius()) / 20; // TODO
-
- return !(Math.log10(cellSize) <= (Math.log10(minDistance) - this.splitScale));
- }
-
- private boolean atMaxLevel(DrawContext dc)
- {
- Position vpc = dc.getViewportCenterPosition();
- if (dc.getView() == null || this.getLevels() == null || vpc == null)
- return false;
-
- if (!this.getLevels().getSector().contains(vpc.getLatitude(),
- vpc.getLongitude()))
- return true;
-
- Level nextToLast = this.getLevels().getNextToLastLevel();
- if (nextToLast == null)
- return true;
-
- Sector centerSector = nextToLast.computeSectorForPosition(vpc.getLatitude(), vpc.getLongitude(),
- this.getLevels().getTileOrigin());
- return this.needToSplit(dc, centerSector);
- }
-
- // ============== Rendering ======================= //
- // ============== Rendering ======================= //
- // ============== Rendering ======================= //
-
- @Override
- public void render(DrawContext dc)
- {
- this.atMaxResolution = this.atMaxLevel(dc);
- super.render(dc);
- }
-
- @Override
- protected final void doRender(DrawContext dc)
- {
- if (this.forceLevelZeroLoads && !this.levelZeroLoaded)
- this.loadAllTopLevelTextures(dc);
- if (dc.getSurfaceGeometry() == null
- || dc.getSurfaceGeometry().size() < 1)
- return;
-
- dc.getGeographicSurfaceTileRenderer().setShowImageTileOutlines(
- this.showImageTileOutlines);
-
- draw(dc);
- }
-
- private void draw(DrawContext dc)
- {
- this.referencePoint = this.computeReferencePoint(dc);
-
- this.assembleTiles(dc); // Determine the tiles to draw.
-
- if (this.currentTiles.size() >= 1)
- {
- MercatorTextureTile[] sortedTiles = new MercatorTextureTile[this.currentTiles
- .size()];
- sortedTiles = this.currentTiles.toArray(sortedTiles);
- Arrays.sort(sortedTiles, levelComparer);
-
- GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
-
- if (this.isUseTransparentTextures() || this.getOpacity() < 1)
- {
- gl.glPushAttrib(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_POLYGON_BIT
- | GL2.GL_CURRENT_BIT);
- gl.glColor4d(1d, 1d, 1d, this.getOpacity());
- gl.glEnable(GL.GL_BLEND);
- gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
- }
- else
- {
- gl.glPushAttrib(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_POLYGON_BIT);
- }
-
- gl.glPolygonMode(GL2.GL_FRONT, GL2.GL_FILL);
- gl.glEnable(GL.GL_CULL_FACE);
- gl.glCullFace(GL.GL_BACK);
-
- dc.setPerFrameStatistic(PerformanceStatistic.IMAGE_TILE_COUNT,
- this.tileCountName, this.currentTiles.size());
- dc.getGeographicSurfaceTileRenderer().renderTiles(dc,
- this.currentTiles);
-
- gl.glPopAttrib();
-
- if (this.drawTileIDs)
- this.drawTileIDs(dc, this.currentTiles);
-
- if (this.drawBoundingVolumes)
- this.drawBoundingVolumes(dc, this.currentTiles);
-
- this.currentTiles.clear();
- }
-
- this.sendRequests();
- this.requestQ.clear();
- }
-
- private void sendRequests()
- {
- Runnable task = this.requestQ.poll();
- while (task != null)
- {
- if (!WorldWind.getTaskService().isFull())
- {
- WorldWind.getTaskService().addTask(task);
- }
- task = this.requestQ.poll();
- }
- }
-
- public boolean isLayerInView(DrawContext dc)
- {
- if (dc == null)
- {
- String message = Logging.getMessage("nullValue.DrawContextIsNull");
- Logging.logger().severe(message);
- throw new IllegalStateException(message);
- }
-
- if (dc.getView() == null)
- {
- String message = Logging
- .getMessage("layers.AbstractLayer.NoViewSpecifiedInDrawingContext");
- Logging.logger().severe(message);
- throw new IllegalStateException(message);
- }
-
- return !(dc.getVisibleSector() != null && !this.levels.getSector()
- .intersects(dc.getVisibleSector()));
- }
-
- private Vec4 computeReferencePoint(DrawContext dc)
- {
- if (dc.getViewportCenterPosition() != null)
- return dc.getGlobe().computePointFromPosition(
- dc.getViewportCenterPosition());
-
- java.awt.geom.Rectangle2D viewport = dc.getView().getViewport();
- int x = (int) viewport.getWidth() / 2;
- for (int y = (int) (0.5 * viewport.getHeight()); y >= 0; y--)
- {
- Position pos = dc.getView().computePositionFromScreenPoint(x, y);
- if (pos == null)
- continue;
-
- return dc.getGlobe().computePointFromPosition(pos.getLatitude(),
- pos.getLongitude(), 0d);
- }
-
- return null;
- }
-
- protected Vec4 getReferencePoint()
- {
- return this.referencePoint;
- }
-
- private static class LevelComparer implements
- Comparator
- {
- public int compare(MercatorTextureTile ta, MercatorTextureTile tb)
- {
- int la = ta.getFallbackTile() == null ? ta.getLevelNumber() : ta
- .getFallbackTile().getLevelNumber();
- int lb = tb.getFallbackTile() == null ? tb.getLevelNumber() : tb
- .getFallbackTile().getLevelNumber();
-
- return la < lb ? -1 : la == lb ? 0 : 1;
- }
- }
-
- private void drawTileIDs(DrawContext dc,
- ArrayList tiles)
- {
- java.awt.Rectangle viewport = dc.getView().getViewport();
- TextRenderer textRenderer = OGLTextRenderer.getOrCreateTextRenderer(dc.getTextRendererCache(),
- java.awt.Font.decode("Arial-Plain-13"));
-
- dc.getGL().glDisable(GL.GL_DEPTH_TEST);
- dc.getGL().glDisable(GL.GL_BLEND);
- dc.getGL().glDisable(GL.GL_TEXTURE_2D);
-
- textRenderer.setColor(java.awt.Color.YELLOW);
- textRenderer.beginRendering(viewport.width, viewport.height);
- for (MercatorTextureTile tile : tiles)
- {
- String tileLabel = tile.getLabel();
-
- if (tile.getFallbackTile() != null)
- tileLabel += "/" + tile.getFallbackTile().getLabel();
-
- LatLon ll = tile.getSector().getCentroid();
- Vec4 pt = dc.getGlobe().computePointFromPosition(
- ll.getLatitude(),
- ll.getLongitude(),
- dc.getGlobe().getElevation(ll.getLatitude(),
- ll.getLongitude()));
- pt = dc.getView().project(pt);
- textRenderer.draw(tileLabel, (int) pt.x, (int) pt.y);
- }
- textRenderer.endRendering();
- }
-
- private void drawBoundingVolumes(DrawContext dc,
- ArrayList tiles)
- {
- GL2 gl = dc.getGL().getGL2(); // GL initialization checks for GL2 compatibility.
-
- float[] previousColor = new float[4];
- gl.glGetFloatv(GL2.GL_CURRENT_COLOR, previousColor, 0);
- gl.glColor3d(0, 1, 0);
-
- for (MercatorTextureTile tile : tiles)
- {
- ((Cylinder) tile.getExtent(dc)).render(dc);
- }
-
- Cylinder c = Sector.computeBoundingCylinder(dc.getGlobe(), dc.getVerticalExaggeration(),
- this.levels.getSector());
- gl.glColor3d(1, 1, 0);
- c.render(dc);
-
- gl.glColor4fv(previousColor, 0);
- }
-
- // ============== Image Composition ======================= //
- // ============== Image Composition ======================= //
- // ============== Image Composition ======================= //
-
- public List getAvailableImageFormats()
- {
- return new ArrayList(this.supportedImageFormats);
- }
-
- public boolean isImageFormatAvailable(String imageFormat)
- {
- return imageFormat != null
- && this.supportedImageFormats.contains(imageFormat);
- }
-
- public String getDefaultImageFormat()
- {
- return this.supportedImageFormats.size() > 0 ? this.supportedImageFormats
- .get(0)
- : null;
- }
-
- protected void setAvailableImageFormats(String[] formats)
- {
- this.supportedImageFormats.clear();
-
- if (formats != null)
- {
- this.supportedImageFormats.addAll(Arrays.asList(formats));
- }
- }
-
- private BufferedImage requestImage(MercatorTextureTile tile, String mimeType)
- throws URISyntaxException
- {
- String pathBase = tile.getPath().substring(0,
- tile.getPath().lastIndexOf("."));
- String suffix = WWIO.makeSuffixForMimeType(mimeType);
- String path = pathBase + suffix;
- URL url = this.getDataFileStore().findFile(path, false);
-
- if (url == null) // image is not local
- return null;
-
- if (WWIO.isFileOutOfDate(url, tile.getLevel().getExpiryTime()))
- {
- // The file has expired. Delete it.
- this.getDataFileStore().removeFile(url);
- String message = Logging.getMessage("generic.DataFileExpired", url);
- Logging.logger().fine(message);
- }
- else
- {
- try
- {
- File imageFile = new File(url.toURI());
- BufferedImage image = ImageIO.read(imageFile);
- if (image == null)
- {
- String message = Logging.getMessage(
- "generic.ImageReadFailed", imageFile);
- throw new RuntimeException(message);
- }
-
- this.levels.unmarkResourceAbsent(tile);
- return image;
- }
- catch (IOException e)
- {
- // Assume that something's wrong with the file and delete it.
- this.getDataFileStore().removeFile(url);
- this.levels.markResourceAbsent(tile);
- String message = Logging.getMessage(
- "generic.DeletedCorruptDataFile", url);
- Logging.logger().info(message);
- }
- }
-
- return null;
- }
-
- private void downloadImage(final MercatorTextureTile tile, String mimeType)
- throws Exception
- {
- // System.out.println(tile.getPath());
- final URL resourceURL = tile.getResourceURL(mimeType);
- Retriever retriever;
-
- String protocol = resourceURL.getProtocol();
-
- if ("http".equalsIgnoreCase(protocol))
- {
- retriever = new HTTPRetriever(resourceURL, new HttpRetrievalPostProcessor(tile));
- retriever.setValue(URLRetriever.EXTRACT_ZIP_ENTRY, "true"); // supports legacy layers
- }
- else
- {
- String message = Logging
- .getMessage("layers.TextureLayer.UnknownRetrievalProtocol",
- resourceURL);
- throw new RuntimeException(message);
- }
-
- retriever.setConnectTimeout(10000);
- retriever.setReadTimeout(20000);
- retriever.call();
- }
-
- public int computeLevelForResolution(Sector sector, Globe globe,
- double resolution)
- {
- if (sector == null)
- {
- String message = Logging.getMessage("nullValue.SectorIsNull");
- Logging.logger().severe(message);
- throw new IllegalStateException(message);
- }
-
- if (globe == null)
- {
- String message = Logging.getMessage("nullValue.GlobeIsNull");
- Logging.logger().severe(message);
- throw new IllegalStateException(message);
- }
-
- double texelSize = 0;
- Level targetLevel = this.levels.getLastLevel();
- for (int i = 0; i < this.getLevels().getLastLevel().getLevelNumber(); i++)
- {
- if (this.levels.isLevelEmpty(i))
- continue;
-
- texelSize = this.levels.getLevel(i).getTexelSize();
- if (texelSize > resolution)
- continue;
-
- targetLevel = this.levels.getLevel(i);
- break;
- }
-
- Logging.logger().info(
- Logging.getMessage("layers.TiledImageLayer.LevelSelection",
- targetLevel.getLevelNumber(), texelSize));
- return targetLevel.getLevelNumber();
- }
-
- public BufferedImage composeImageForSector(Sector sector, int imageWidth,
- int imageHeight, int levelNumber, String mimeType,
- boolean abortOnError, BufferedImage image)
- {
- if (sector == null)
- {
- String message = Logging.getMessage("nullValue.SectorIsNull");
- Logging.logger().severe(message);
- throw new IllegalStateException(message);
- }
-
- if (levelNumber < 0)
- {
- levelNumber = this.levels.getLastLevel().getLevelNumber();
- }
- else if (levelNumber > this.levels.getLastLevel().getLevelNumber())
- {
- Logging.logger().warning(
- Logging.getMessage(
- "generic.LevelRequestedGreaterThanMaxLevel",
- levelNumber, this.levels.getLastLevel()
- .getLevelNumber()));
- levelNumber = this.levels.getLastLevel().getLevelNumber();
- }
-
- MercatorTextureTile[][] tiles = this.getTilesInSector(sector,
- levelNumber);
-
- if (tiles.length == 0 || tiles[0].length == 0)
- {
- Logging
- .logger()
- .severe(
- Logging
- .getMessage("layers.TiledImageLayer.NoImagesAvailable"));
- return null;
- }
-
- if (image == null)
- image = new BufferedImage(imageWidth, imageHeight,
- BufferedImage.TYPE_INT_RGB);
-
- Graphics2D g = image.createGraphics();
-
- for (MercatorTextureTile[] row : tiles)
- {
- for (MercatorTextureTile tile : row)
- {
- if (tile == null)
- continue;
-
- BufferedImage tileImage;
- try
- {
- tileImage = this.getImage(tile, mimeType);
-
- double sh = ((double) imageHeight / (double) tileImage
- .getHeight())
- * (tile.getSector().getDeltaLat().divide(sector
- .getDeltaLat()));
- double sw = ((double) imageWidth / (double) tileImage
- .getWidth())
- * (tile.getSector().getDeltaLon().divide(sector
- .getDeltaLon()));
-
- double dh = imageHeight
- * (-tile.getSector().getMaxLatitude().subtract(
- sector.getMaxLatitude()).degrees / sector
- .getDeltaLat().degrees);
- double dw = imageWidth
- * (tile.getSector().getMinLongitude().subtract(
- sector.getMinLongitude()).degrees / sector
- .getDeltaLon().degrees);
-
- AffineTransform txf = g.getTransform();
- g.translate(dw, dh);
- g.scale(sw, sh);
- g.drawImage(tileImage, 0, 0, null);
- g.setTransform(txf);
- }
- catch (Exception e)
- {
- if (abortOnError)
- throw new RuntimeException(e);
-
- String message = Logging.getMessage(
- "generic.ExceptionWhileRequestingImage", tile
- .getPath());
- Logging.logger().log(java.util.logging.Level.WARNING,
- message, e);
- }
- }
- }
-
- return image;
- }
-
- public int countImagesInSector(Sector 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.
- LatLon delta = targetLevel.getTileDelta();
- Angle latOrigin = this.levels.getTileOrigin().getLatitude();
- Angle lonOrigin = this.levels.getTileOrigin().getLongitude();
- final int nwRow = Tile.computeRow(delta.getLatitude(), sector
- .getMaxLatitude(), latOrigin);
- final int nwCol = Tile.computeColumn(delta.getLongitude(), sector
- .getMinLongitude(), lonOrigin);
- final int seRow = Tile.computeRow(delta.getLatitude(), sector
- .getMinLatitude(), latOrigin);
- final int seCol = Tile.computeColumn(delta.getLongitude(), sector
- .getMaxLongitude(), lonOrigin);
-
- int numRows = nwRow - seRow + 1;
- int numCols = seCol - nwCol + 1;
-
- return numRows * numCols;
- }
-
- private MercatorTextureTile[][] getTilesInSector(Sector 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.
- LatLon delta = targetLevel.getTileDelta();
- Angle latOrigin = this.levels.getTileOrigin().getLatitude();
- Angle lonOrigin = this.levels.getTileOrigin().getLongitude();
- final int nwRow = Tile.computeRow(delta.getLatitude(), sector
- .getMaxLatitude(), latOrigin);
- final int nwCol = Tile.computeColumn(delta.getLongitude(), sector
- .getMinLongitude(), lonOrigin);
- final int seRow = Tile.computeRow(delta.getLatitude(), sector
- .getMinLatitude(), latOrigin);
- final int seCol = Tile.computeColumn(delta.getLongitude(), sector
- .getMaxLongitude(), lonOrigin);
-
- 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++)
- {
- TileKey key = new TileKey(targetLevel.getLevelNumber(), row,
- col, targetLevel.getCacheName());
- Sector tileSector = this.levels.computeSectorForKey(key);
- MercatorSector mSector = MercatorSector.fromSector(tileSector); //TODO: check
- sectorTiles[nwRow - row][col - nwCol] = new MercatorTextureTile(
- mSector, targetLevel, row, col);
- }
- }
-
- return sectorTiles;
- }
-
- private BufferedImage getImage(MercatorTextureTile tile, String mimeType)
- throws Exception
- {
- // Read the image from disk.
- BufferedImage image = this.requestImage(tile, mimeType);
- if (image != null)
- return image;
-
- // Retrieve it from the net since it's not on disk.
- this.downloadImage(tile, mimeType);
-
- // Try to read from disk again after retrieving it from the net.
- image = this.requestImage(tile, mimeType);
- if (image == null)
- {
- String message = Logging.getMessage(
- "layers.TiledImageLayer.ImageUnavailable", tile.getPath());
- throw new RuntimeException(message);
- }
-
- return image;
- }
-
- private class HttpRetrievalPostProcessor implements RetrievalPostProcessor
- {
- private MercatorTextureTile tile;
-
- public HttpRetrievalPostProcessor(MercatorTextureTile tile)
- {
- this.tile = tile;
- }
-
- public ByteBuffer run(Retriever retriever)
- {
- if (!retriever.getState().equals(
- Retriever.RETRIEVER_STATE_SUCCESSFUL))
- return null;
-
- HTTPRetriever htr = (HTTPRetriever) retriever;
- if (htr.getResponseCode() == HttpURLConnection.HTTP_NO_CONTENT)
- {
- // Mark tile as missing to avoid excessive attempts
- MercatorTiledImageLayer.this.levels.markResourceAbsent(tile);
- return null;
- }
-
- if (htr.getResponseCode() != HttpURLConnection.HTTP_OK)
- return null;
-
- URLRetriever r = (URLRetriever) retriever;
- ByteBuffer buffer = r.getBuffer();
-
- String suffix = WWIO.makeSuffixForMimeType(htr.getContentType());
- if (suffix == null)
- {
- return null; // TODO: log error
- }
-
- String path = tile.getPath().substring(0,
- tile.getPath().lastIndexOf("."));
- path += suffix;
-
- final File outFile = getDataFileStore().newFile(path);
- if (outFile == null)
- return null;
-
- try
- {
- WWIO.saveBuffer(buffer, outFile);
- return buffer;
- }
- catch (IOException e)
- {
- e.printStackTrace(); // TODO: log error
- return null;
- }
- }
- }
-}
diff --git a/src/gov/nasa/worldwind/util/Tile.java b/src/gov/nasa/worldwind/util/Tile.java
index 8946c2a690..dd847d0867 100644
--- a/src/gov/nasa/worldwind/util/Tile.java
+++ b/src/gov/nasa/worldwind/util/Tile.java
@@ -218,7 +218,7 @@ public String getPathBase()
return path.contains(".") ? path.substring(0, path.lastIndexOf(".")) : path;
}
- public final Sector getSector()
+ public Sector getSector()
{
return sector;
}