1
+ package gov .nasa .worldwind .layer .mercator ;
2
+
3
+ import android .graphics .Bitmap ;
4
+
5
+ import java .util .Collection ;
6
+
7
+ import gov .nasa .worldwind .render .ImageTile ;
8
+ import gov .nasa .worldwind .util .DownloadPostprocessor ;
9
+ import gov .nasa .worldwind .util .Level ;
10
+ import gov .nasa .worldwind .util .LevelSet ;
11
+ import gov .nasa .worldwind .util .Logger ;
12
+ import gov .nasa .worldwind .util .Tile ;
13
+ import gov .nasa .worldwind .util .TileFactory ;
14
+
15
+ class MercatorImageTile extends ImageTile implements DownloadPostprocessor <Bitmap > {
16
+
17
+ /**
18
+ * Constructs a tile with a specified sector, level, row and column.
19
+ *
20
+ * @param sector the sector spanned by the tile
21
+ * @param level the tile's level in a {@link LevelSet}
22
+ * @param row the tile's row within the specified level
23
+ * @param column the tile's column within the specified level
24
+ */
25
+ MercatorImageTile (MercatorSector sector , Level level , int row , int column ) {
26
+ super (sector , level , row , column );
27
+ }
28
+
29
+ /**
30
+ * Creates all Mercator tiles for a specified level within a {@link LevelSet}.
31
+ *
32
+ * @param level the level to create the tiles for
33
+ * @param tileFactory the tile factory to use for creating tiles.
34
+ * @param result an pre-allocated Collection in which to store the results
35
+ */
36
+ static void assembleMercatorTilesForLevel (Level level , TileFactory tileFactory , Collection <Tile > result ) {
37
+ if (level == null ) {
38
+ throw new IllegalArgumentException (
39
+ Logger .logMessage (Logger .ERROR , "Tile" , "assembleTilesForLevel" , "missingLevel" ));
40
+ }
41
+
42
+ if (tileFactory == null ) {
43
+ throw new IllegalArgumentException (
44
+ Logger .logMessage (Logger .ERROR , "Tile" , "assembleTilesForLevel" , "missingTileFactory" ));
45
+ }
46
+
47
+ if (result == null ) {
48
+ throw new IllegalArgumentException (
49
+ Logger .logMessage (Logger .ERROR , "Tile" , "assembleTilesForLevel" , "missingResult" ));
50
+ }
51
+
52
+ // NOTE LevelSet.sector is final Sector attribute and thus can not be cast to MercatorSector!
53
+ MercatorSector sector = MercatorSector .fromSector (level .parent .sector );
54
+ double dLat = level .tileDelta / 2 ;
55
+ double dLon = level .tileDelta ;
56
+
57
+ int firstRow = Tile .computeRow (dLat , sector .minLatitude ());
58
+ int lastRow = Tile .computeLastRow (dLat , sector .maxLatitude ());
59
+ int firstCol = Tile .computeColumn (dLon , sector .minLongitude ());
60
+ int lastCol = Tile .computeLastColumn (dLon , sector .maxLongitude ());
61
+
62
+ double deltaLat = dLat / 90 ;
63
+ double d1 = sector .minLatPercent () + deltaLat * firstRow ;
64
+ for (int row = firstRow ; row <= lastRow ; row ++) {
65
+ double d2 = d1 + deltaLat ;
66
+ double t1 = sector .minLongitude () + (firstCol * dLon );
67
+ for (int col = firstCol ; col <= lastCol ; col ++) {
68
+ double t2 ;
69
+ t2 = t1 + dLon ;
70
+ result .add (tileFactory .createTile (MercatorSector .fromDegrees (d1 , d2 , t1 , t2 ), level , row , col ));
71
+ t1 = t2 ;
72
+ }
73
+ d1 = d2 ;
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Returns the four children formed by subdividing this tile. This tile's sector is subdivided into four quadrants
79
+ * as follows: Southwest; Southeast; Northwest; Northeast. A new tile is then constructed for each quadrant and
80
+ * configured with the next level within this tile's LevelSet and its corresponding row and column within that
81
+ * level. This returns null if this tile's level is the last level within its {@link LevelSet}.
82
+ *
83
+ * @param tileFactory the tile factory to use to create the children
84
+ *
85
+ * @return an array containing the four child tiles, or null if this tile's level is the last level
86
+ */
87
+ @ Override
88
+ public Tile [] subdivide (TileFactory tileFactory ) {
89
+ if (tileFactory == null ) {
90
+ throw new IllegalArgumentException (
91
+ Logger .logMessage (Logger .ERROR , "Tile" , "subdivide" , "missingTileFactory" ));
92
+ }
93
+
94
+ Level childLevel = this .level .nextLevel ();
95
+ if (childLevel == null ) {
96
+ return null ;
97
+ }
98
+
99
+ MercatorSector sector = (MercatorSector ) this .sector ;
100
+
101
+ double d0 = sector .minLatPercent ();
102
+ double d2 = sector .maxLatPercent ();
103
+ double d1 = d0 + (d2 - d0 ) / 2.0 ;
104
+
105
+ double t0 = sector .minLongitude ();
106
+ double t2 = sector .maxLongitude ();
107
+ double t1 = 0.5 * (t0 + t2 );
108
+
109
+ int northRow = 2 * this .row ;
110
+ int southRow = northRow + 1 ;
111
+ int westCol = 2 * this .column ;
112
+ int eastCol = westCol + 1 ;
113
+
114
+ Tile [] children = new Tile [4 ];
115
+ children [0 ] = tileFactory .createTile (MercatorSector .fromDegrees (d0 , d1 , t0 , t1 ), childLevel , northRow , westCol );
116
+ children [1 ] = tileFactory .createTile (MercatorSector .fromDegrees (d0 , d1 , t1 , t2 ), childLevel , northRow , eastCol );
117
+ children [2 ] = tileFactory .createTile (MercatorSector .fromDegrees (d1 , d2 , t0 , t1 ), childLevel , southRow , westCol );
118
+ children [3 ] = tileFactory .createTile (MercatorSector .fromDegrees (d1 , d2 , t1 , t2 ), childLevel , southRow , eastCol );
119
+
120
+ return children ;
121
+ }
122
+
123
+ @ Override
124
+ public Bitmap process (Bitmap resource ) {
125
+ // Re-project mercator tile to equirectangular
126
+ int [] pixels = new int [resource .getWidth () * resource .getHeight ()];
127
+ int [] result = new int [resource .getWidth () * resource .getHeight ()];
128
+ resource .getPixels (pixels , 0 , resource .getWidth (), 0 , 0 , resource .getWidth (), resource .getHeight ());
129
+ double miny = ((MercatorSector ) sector ).minLatPercent ();
130
+ double maxy = ((MercatorSector ) sector ).maxLatPercent ();
131
+ for (int y = 0 ; y < resource .getHeight (); y ++) {
132
+ double sy = 1.0 - y / (double ) (resource .getHeight () - 1 );
133
+ double lat = sy * (sector .maxLatitude () - sector .minLatitude ()) + sector .minLatitude ();
134
+ double dy = 1.0 - (MercatorSector .gudermannianInverse (lat ) - miny ) / (maxy - miny );
135
+ dy = Math .max (0.0 , Math .min (1.0 , dy ));
136
+ int iy = (int ) (dy * (resource .getHeight () - 1 ));
137
+ for (int x = 0 ; x < resource .getWidth (); x ++) {
138
+ result [x + y * resource .getWidth ()] = pixels [x + iy * resource .getWidth ()];
139
+ }
140
+ }
141
+ return Bitmap .createBitmap (result , resource .getWidth (), resource .getHeight (), resource .getConfig ());
142
+ }
143
+
144
+ }
0 commit comments