GoogleEarthLayer

  1 import gov.nasa.worldwind.avlist.AVKey;
  2 import gov.nasa.worldwind.avlist.AVList;
  3 import gov.nasa.worldwind.avlist.AVListImpl;
  4 import gov.nasa.worldwind.geom.Angle;
  5 import gov.nasa.worldwind.geom.LatLon;
  6 import gov.nasa.worldwind.layers.Mercator.BasicMercatorTiledImageLayer;
  7 import gov.nasa.worldwind.layers.Mercator.MercatorSector;
  8 import gov.nasa.worldwind.util.LevelSet;
  9 import gov.nasa.worldwind.util.Tile;
 10 import gov.nasa.worldwind.util.TileUrlBuilder;
 11 
 12 import java.awt.image.BufferedImage;
 13 import java.net.MalformedURLException;
 14 import java.net.URL;
 15 
 16 public class GoogleEarthLayer extends BasicMercatorTiledImageLayer {
 17     public static enum Dataset {
 18         AERIAL("Aerial", "a", ".jpg",
 19                 "http://khm%d.google.com/kh/v=57&x=%d&y=%d&z=%d&s=Galile");
 20 
 21         public final String label;
 22         public final String dataset;
 23         public final String formatSuffix;
 24         public final String urlFormat;
 25 
 26         private Dataset(String label, String dataset, String formatSuffix,
 27                 String urlFormat) {
 28             this.label = label;
 29             this.dataset = dataset;
 30             this.formatSuffix = formatSuffix;
 31             this.urlFormat = urlFormat;
 32         }
 33     }
 34 
 35     private final Dataset dataset;
 36 
 37     public GoogleEarthLayer() {
 38         this(Dataset.AERIAL);
 39     }
 40 
 41     public GoogleEarthLayer(Dataset dataset) {
 42         super(makeLevels(dataset));
 43         if (dataset == null)
 44             throw new NullPointerException("Dataset cannot be null");
 45         this.dataset = dataset;
 46         this.setValue(AVKey.DISPLAY_NAME, "Google Earth " + dataset.label);
 47         this.setSplitScale(1.3);
 48     }
 49 
 50     protected static LevelSet makeLevels(Dataset dataset) {
 51         AVList params = new AVListImpl();
 52 
 53         params.setValue(AVKey.TILE_WIDTH, 256);
 54         params.setValue(AVKey.TILE_HEIGHT, 256);
 55         params
 56                 .setValue(AVKey.DATA_CACHE_NAME, "Google Earth7 "
 57                         + dataset.label);
 58         params.setValue(AVKey.SERVICE,
 59                 "http://kh0.google.com/kh?n=404&v=17&t=t");
 60         params.setValue(AVKey.DATASET_NAME, dataset.dataset);
 61         params.setValue(AVKey.FORMAT_SUFFIX, dataset.formatSuffix);
 62         params.setValue(AVKey.NUM_LEVELS, 16);
 63         params.setValue(AVKey.NUM_EMPTY_LEVELS, 0);
 64         params.setValue(AVKey.LEVEL_ZERO_TILE_DELTA, new LatLon(Angle
 65                 .fromDegrees(22.5d), Angle.fromDegrees(45d)));
 66         params.setValue(AVKey.SECTOR, new MercatorSector(-1.0, 1.0,
 67                 Angle.NEG180, Angle.POS180));
 68         params.setValue(AVKey.TILE_URL_BUILDER, new URLBuilder(dataset));
 69         params.setValue(AVKey.DISPLAY_NAME, "Google Maps " + dataset.label);
 70 
 71         return new LevelSet(params);
 72     }
 73 
 74     public static class URLBuilder implements TileUrlBuilder {
 75 
 76         private Dataset dataset;
 77 
 78         public URLBuilder(Dataset dataset) {
 79             this.dataset = dataset;
 80         }
 81 
 82         public URL getURL(Tile tile, String imageFormat)
 83                 throws MalformedURLException {
 84             LatLon center = tile.getSector().getCentroid();
 85             String urlString = computeTileUrl(dataset.urlFormat, center
 86                     .getLatitude().degrees, center.getLongitude().degrees, tile
 87                     .getLevelNumber() + 3);
 88             System.out.println("Need:" + urlString);
 89             URL url = new URL(urlString);
 90             return url;
 91         }
 92         
 93         private static String computeTileUrl(String urlFormat, double lat, double lon, int zoom) {
 94 
 95             if (lon > 180.0) {
 96                 lon -= 360.0;
 97             }
 98 
 99             lon = (180.0 + lon) / 360.0;
100             lat = 0.5
101                     - Math.log(Math.tan((Math.PI / 4.0)
102                             + ((Math.PI * lat) / (2.0 * 180.0)))) / (2.0 * Math.PI);
103 
104             int scale = 1 << (int) zoom;
105 
106             // can just truncate to integer, this looses the fractional
107             // "pixel offset"
108             int x = (int) (lon * scale);
109             int y = (int) (lat * scale);
110             return String.format(urlFormat, (int) (Math.random() * 4), x, y, zoom);
111         }
112 
113     }
114 
115     @Override
116     protected boolean isTileValid(BufferedImage image) {
117         // return false if the tile is white (this will mark the tile as absent)
118         boolean white = true;
119         // JPEG compression will cause white to be not quite white
120         String lowercaseFormat = getDataset().formatSuffix.toLowerCase();
121         int threshold = lowercaseFormat.contains("jpg")
122                 || lowercaseFormat.contains("jpeg") ? 200 : 250;
123         for (int x = 0; x < image.getWidth(); x++) {
124             for (int y = 0; y < image.getHeight(); y++) {
125                 int rgb = image.getRGB(x, y);
126                 white = isWhite(rgb, threshold);
127                 if (!white)
128                     break;
129             }
130             if (!white)
131                 break;
132         }
133         return !white;
134     }
135 
136     private boolean isWhite(int rgb, int threshold) {
137         int r = (rgb >> 16) & 0xff;
138         int g = (rgb >> 8) & 0xff;
139         int b = (rgb >> 0) & 0xff;
140         return r + b + g > threshold * 3;
141     }
142 
143     public Dataset getDataset() {
144         return dataset;
145     }
146 }

 

posted @ 2014-09-19 14:35  zhh  阅读(572)  评论(0编辑  收藏  举报