Skip to content

Commit 99d1eab

Browse files
committed
Separate first level delta in Level Set for latitude and longitude.
1 parent c17e8b0 commit 99d1eab

11 files changed

Lines changed: 71 additions & 73 deletions

File tree

worldwind/src/main/java/gov/nasa/worldwind/globe/BasicTessellator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
public class BasicTessellator implements Tessellator, TileFactory {
3434

3535
// ~0.6 meter resolution
36-
protected LevelSet levelSet = new LevelSet(new Sector().setFullSphere(), new Location(-90, -180), 90, 20, 32, 32);
36+
protected LevelSet levelSet = new LevelSet(new Sector().setFullSphere(), new Location(-90, -180), new Location(90, 90), 20, 32, 32);
3737

3838
protected double detailControl = 80;
3939

worldwind/src/main/java/gov/nasa/worldwind/layer/BlueMarbleLandsatLayer.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public BlueMarbleLandsatLayer(String serviceAddress) {
8585

8686
@Override
8787
public Tile createTile(Sector sector, Level level, int row, int column) {
88-
double radiansPerPixel = Math.toRadians(level.tileDelta) / level.tileHeight;
88+
double radiansPerPixel = Math.toRadians(level.tileDelta.latitude) / level.tileHeight;
8989
double metersPerPixel = radiansPerPixel * WorldWind.WGS84_SEMI_MAJOR_AXIS;
9090

9191
if (metersPerPixel < 2.0e3) { // switch to Landsat at 2km resolution

worldwind/src/main/java/gov/nasa/worldwind/layer/LayerFactory.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,10 @@ protected void createFromGeoPackageAsync(String pathName, Layer layer, Callback
280280
tileMatrixSet.getMaxY() - tileMatrixSet.getMinY(),
281281
tileMatrixSet.getMaxX() - tileMatrixSet.getMinX());
282282
config.tileOrigin.set(tileMatrixSet.getMinY(), tileMatrixSet.getMinX());
283-
config.firstLevelDelta = (tileMatrixSet.getMaxY() - tileMatrixSet.getMinY()) / tileMatrix.valueAt(0).getMatrixHeight();
283+
config.firstLevelDelta.set(
284+
(tileMatrixSet.getMaxY() - tileMatrixSet.getMinY()) / tileMatrix.valueAt(0).getMatrixHeight(),
285+
(tileMatrixSet.getMaxX() - tileMatrixSet.getMinX()) / tileMatrix.valueAt(0).getMatrixWidth()
286+
);
284287
config.numLevels = tileMatrix.keyAt(tileMatrix.size() - 1) - tileMatrix.keyAt(0) + 1;
285288

286289
TiledSurfaceImage surfaceImage = new TiledSurfaceImage();
@@ -681,7 +684,7 @@ protected LevelSet createWmtsLevelSet(WmtsLayer wmtsLayer, CompatibleTileMatrixS
681684
}
682685
int imageSize = tileMatrixSet.getTileMatrices().get(0).getTileHeight();
683686

684-
return new LevelSet(boundingBox, new Location(-90, -180), 90, compatibleTileMatrixSet.tileMatrices.size(), imageSize, imageSize);
687+
return new LevelSet(boundingBox, new Location(-90, -180), new Location(90, 90), compatibleTileMatrixSet.tileMatrices.size(), imageSize, imageSize);
685688
}
686689

687690
protected String buildWmtsKvpTemplate(String kvpServiceAddress, String layer, String format, String styleIdentifier, String tileMatrixSet) {

worldwind/src/main/java/gov/nasa/worldwind/layer/mercator/MercatorImageTile.java

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,23 +53,25 @@ static void assembleMercatorTilesForLevel(Level level, TileFactory tileFactory,
5353
// NOTE LevelSet.sector is final Sector attribute and thus can not be cast to MercatorSector!
5454
MercatorSector sector = MercatorSector.fromSector(level.parent.sector);
5555
Location tileOrigin = level.parent.tileOrigin;
56-
double dLat = level.tileDelta / 2;
57-
double dLon = level.tileDelta;
56+
double dLat = level.tileDelta.latitude;
57+
double dLon = level.tileDelta.longitude;
5858

5959
int firstRow = Tile.computeRow(dLat, sector.minLatitude(), tileOrigin.latitude);
6060
int lastRow = Tile.computeLastRow(dLat, sector.maxLatitude(), tileOrigin.latitude);
6161
int firstCol = Tile.computeColumn(dLon, sector.minLongitude(), tileOrigin.longitude);
6262
int lastCol = Tile.computeLastColumn(dLon, sector.maxLongitude(), tileOrigin.longitude);
6363

64-
double deltaLat = dLat / 90;
65-
double d1 = sector.minLatPercent() + deltaLat * firstRow;
64+
double dLatPercent = dLat / sector.deltaLatitude() * (sector.maxLatPercent() - sector.minLatPercent());
65+
double firstRowPercent = MercatorSector.gudermannianInverse(tileOrigin.latitude) + firstRow * dLatPercent;
66+
double firstColLon = tileOrigin.longitude + firstCol * dLon;
67+
68+
double d1 = firstRowPercent;
6669
for (int row = firstRow; row <= lastRow; row++) {
67-
double d2 = d1 + deltaLat;
68-
double t1 = tileOrigin.longitude + (firstCol * dLon);
70+
double d2 = d1 + dLatPercent;
71+
double t1 = firstColLon;
6972
for (int col = firstCol; col <= lastCol; col++) {
70-
double t2;
71-
t2 = t1 + dLon;
72-
result.add(tileFactory.createTile(MercatorSector.fromDegrees(d1, d2, t1, t2), level, row, col));
73+
double t2 = t1 + dLon;
74+
result.add(tileFactory.createTile(new MercatorSector(d1, d2, t1, t2), level, row, col));
7375
t1 = t2;
7476
}
7577
d1 = d2;
@@ -114,10 +116,10 @@ public Tile[] subdivide(TileFactory tileFactory) {
114116
int eastCol = westCol + 1;
115117

116118
Tile[] children = new Tile[4];
117-
children[0] = tileFactory.createTile(MercatorSector.fromDegrees(d0, d1, t0, t1), childLevel, northRow, westCol);
118-
children[1] = tileFactory.createTile(MercatorSector.fromDegrees(d0, d1, t1, t2), childLevel, northRow, eastCol);
119-
children[2] = tileFactory.createTile(MercatorSector.fromDegrees(d1, d2, t0, t1), childLevel, southRow, westCol);
120-
children[3] = tileFactory.createTile(MercatorSector.fromDegrees(d1, d2, t1, t2), childLevel, southRow, eastCol);
119+
children[0] = tileFactory.createTile(new MercatorSector(d0, d1, t0, t1), childLevel, northRow, westCol);
120+
children[1] = tileFactory.createTile(new MercatorSector(d0, d1, t1, t2), childLevel, northRow, eastCol);
121+
children[2] = tileFactory.createTile(new MercatorSector(d1, d2, t0, t1), childLevel, southRow, westCol);
122+
children[3] = tileFactory.createTile(new MercatorSector(d1, d2, t1, t2), childLevel, southRow, eastCol);
121123

122124
return children;
123125
}

worldwind/src/main/java/gov/nasa/worldwind/layer/mercator/MercatorSector.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ public class MercatorSector extends Sector {
66

77
private final double minLatPercent, maxLatPercent;
88

9-
private MercatorSector(double minLatPercent, double maxLatPercent,
10-
double minLongitude, double maxLongitude) {
9+
public MercatorSector(double minLatPercent, double maxLatPercent, double minLongitude, double maxLongitude) {
1110
this.minLatPercent = minLatPercent;
1211
this.maxLatPercent = maxLatPercent;
1312
this.minLatitude = gudermannian(minLatPercent);

worldwind/src/main/java/gov/nasa/worldwind/layer/mercator/MercatorTiledImageLayer.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,19 @@
1313

1414
public abstract class MercatorTiledImageLayer extends RenderableLayer implements TileFactory {
1515

16-
private static final double FULL_SPHERE = 360;
17-
1816
private final int firstLevelOffset;
1917

2018
public MercatorTiledImageLayer(String name, int numLevels, int firstLevelOffset, int tileSize, boolean overlay) {
2119
super(name);
2220
this.setPickEnabled(false);
2321
this.firstLevelOffset = firstLevelOffset;
2422

23+
MercatorSector sector = new MercatorSector(-1.0, 1.0, -180.0, 180.0);
24+
Location tileOrigin = new Location(sector.minLatitude(), sector.minLongitude());
25+
int n = 1 << firstLevelOffset;
26+
Location firstLevelDelta = new Location(sector.deltaLatitude() / n, sector.deltaLongitude() / n);
2527
MercatorTiledSurfaceImage surfaceImage = new MercatorTiledSurfaceImage();
26-
surfaceImage.setLevelSet(new LevelSet(
27-
MercatorSector.fromDegrees(-1.0, 1.0, - FULL_SPHERE / 2, FULL_SPHERE / 2), new Location(-90, -180),
28-
FULL_SPHERE / (1 << firstLevelOffset), numLevels - firstLevelOffset, tileSize, tileSize));
28+
surfaceImage.setLevelSet(new LevelSet(sector, tileOrigin, firstLevelDelta, numLevels - firstLevelOffset, tileSize, tileSize));
2929
surfaceImage.setTileFactory(this);
3030
if(!overlay) {
3131
surfaceImage.setImageOptions(new ImageOptions(WorldWind.RGB_565)); // reduce memory usage by using a 16-bit configuration with no alpha

worldwind/src/main/java/gov/nasa/worldwind/util/Level.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
package gov.nasa.worldwind.util;
77

8+
import gov.nasa.worldwind.geom.Location;
9+
810
/**
911
* Represents a level of a specific resolution in a {@link LevelSet}.
1012
*/
@@ -35,7 +37,7 @@ public class Level {
3537
/**
3638
* The geographic width and height in degrees of tiles within this level.
3739
*/
38-
public final double tileDelta;
40+
public final Location tileDelta;
3941

4042
/**
4143
* The parent LevelSet's tileWidth.
@@ -54,21 +56,21 @@ public class Level {
5456
* @param levelNumber the level's ordinal within its parent level set
5557
* @param tileDelta the geographic width and height in degrees of tiles within this level
5658
*/
57-
public Level(LevelSet parent, int levelNumber, double tileDelta) {
59+
public Level(LevelSet parent, int levelNumber, Location tileDelta) {
5860
if (parent == null) {
5961
throw new IllegalArgumentException(
6062
Logger.logMessage(Logger.ERROR, "Level", "constructor", "The parent level set is null"));
6163
}
6264

63-
if (tileDelta <= 0) {
65+
if (tileDelta == null || tileDelta.latitude <= 0 || tileDelta.longitude <= 0) {
6466
throw new IllegalArgumentException(
6567
Logger.logMessage(Logger.ERROR, "Level", "constructor", "The tile delta is zero"));
6668
}
6769

6870
this.parent = parent;
6971
this.levelNumber = levelNumber;
70-
this.levelWidth = (int) Math.round(parent.tileWidth * parent.sector.deltaLongitude() / tileDelta);
71-
this.levelHeight = (int) Math.round(parent.tileHeight * parent.sector.deltaLatitude() / tileDelta);
72+
this.levelWidth = (int) Math.round(parent.tileWidth * parent.sector.deltaLongitude() / tileDelta.longitude);
73+
this.levelHeight = (int) Math.round(parent.tileHeight * parent.sector.deltaLatitude() / tileDelta.latitude);
7274
this.tileDelta = tileDelta;
7375
this.tileWidth = parent.tileWidth;
7476
this.tileHeight = parent.tileHeight;

worldwind/src/main/java/gov/nasa/worldwind/util/LevelSet.java

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ public class LevelSet {
2525
public final Location tileOrigin = new Location();
2626

2727
/**
28-
* The geographic width and height in degrees of tiles in the first level (lowest resolution) of this level set.
28+
* The geographic width and height in degrees of tiles in the first level (the lowest resolution) of this level set.
2929
*/
30-
public final double firstLevelDelta;
30+
public final Location firstLevelDelta = new Location();
3131

3232
/**
3333
* The width in pixels of images associated with tiles in this level set, or the number of sample points in the
@@ -51,7 +51,6 @@ public class LevelSet {
5151
* <code>firstLevel</code> and <code>lastLevel</code> always return null.
5252
*/
5353
public LevelSet() {
54-
this.firstLevelDelta = 0;
5554
this.tileWidth = 0;
5655
this.tileHeight = 0;
5756
this.levels = new Level[0];
@@ -74,7 +73,7 @@ public LevelSet() {
7473
*
7574
* @throws IllegalArgumentException If any argument is null, or if any dimension is zero
7675
*/
77-
public LevelSet(Sector sector, Location tileOrigin, double firstLevelDelta, int numLevels, int tileWidth, int tileHeight) {
76+
public LevelSet(Sector sector, Location tileOrigin, Location firstLevelDelta, int numLevels, int tileWidth, int tileHeight) {
7877
if (sector == null) {
7978
throw new IllegalArgumentException(
8079
Logger.logMessage(Logger.ERROR, "LevelSet", "constructor", "missingSector"));
@@ -85,7 +84,7 @@ public LevelSet(Sector sector, Location tileOrigin, double firstLevelDelta, int
8584
Logger.logMessage(Logger.ERROR, "LevelSet", "constructor", "missingTileOrigin"));
8685
}
8786

88-
if (firstLevelDelta <= 0) {
87+
if (firstLevelDelta == null || firstLevelDelta.latitude <= 0 || firstLevelDelta.longitude <= 0) {
8988
throw new IllegalArgumentException(
9089
Logger.logMessage(Logger.ERROR, "LevelSet", "constructor", "invalidTileDelta"));
9190
}
@@ -102,7 +101,7 @@ public LevelSet(Sector sector, Location tileOrigin, double firstLevelDelta, int
102101

103102
this.sector.set(sector);
104103
this.tileOrigin.set(tileOrigin);
105-
this.firstLevelDelta = firstLevelDelta;
104+
this.firstLevelDelta.set(firstLevelDelta);
106105
this.tileWidth = tileWidth;
107106
this.tileHeight = tileHeight;
108107
this.levels = new Level[numLevels];
@@ -129,12 +128,7 @@ public LevelSet(LevelSetConfig config) {
129128
Logger.logMessage(Logger.ERROR, "LevelSet", "constructor", "missingSector"));
130129
}
131130

132-
if (config.tileOrigin == null) {
133-
throw new IllegalArgumentException(
134-
Logger.logMessage(Logger.ERROR, "LevelSet", "constructor", "missingTileOrigin"));
135-
}
136-
137-
if (config.firstLevelDelta <= 0) {
131+
if (config.firstLevelDelta.latitude <= 0 || config.firstLevelDelta.longitude <= 0) {
138132
throw new IllegalArgumentException(
139133
Logger.logMessage(Logger.ERROR, "LevelSet", "constructor", "invalidTileDelta"));
140134
}
@@ -151,7 +145,7 @@ public LevelSet(LevelSetConfig config) {
151145

152146
this.sector.set(config.sector);
153147
this.tileOrigin.set(config.tileOrigin);
154-
this.firstLevelDelta = config.firstLevelDelta;
148+
this.firstLevelDelta.set(config.firstLevelDelta);
155149
this.tileWidth = config.tileWidth;
156150
this.tileHeight = config.tileHeight;
157151
this.levels = new Level[config.numLevels];
@@ -160,7 +154,8 @@ public LevelSet(LevelSetConfig config) {
160154

161155
protected void assembleLevels() {
162156
for (int i = 0, len = this.levels.length; i < len; i++) {
163-
double delta = firstLevelDelta / (1 << i);
157+
int n = 1 << i;
158+
Location delta = new Location(firstLevelDelta.latitude / n, firstLevelDelta.longitude / n);
164159
this.levels[i] = new Level(this, i, delta);
165160
}
166161
}
@@ -209,7 +204,7 @@ public Level levelForResolution(double radiansPerPixel) {
209204
}
210205

211206
double degreesPerPixel = Math.toDegrees(radiansPerPixel);
212-
double firstLevelDegreesPerPixel = this.firstLevelDelta / Math.min(this.tileWidth, this.tileHeight);
207+
double firstLevelDegreesPerPixel = Math.max(this.firstLevelDelta.longitude / this.tileWidth, this.firstLevelDelta.latitude / this.tileHeight);
213208
double level = Math.log(firstLevelDegreesPerPixel / degreesPerPixel) / Math.log(2); // fractional level address
214209
int levelNumber = (int) Math.round(level); // nearest neighbor level
215210

worldwind/src/main/java/gov/nasa/worldwind/util/LevelSetConfig.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ public class LevelSetConfig {
2525
public final Location tileOrigin = new Location(-90, -180);
2626

2727
/**
28-
* The geographic width and height in degrees of tiles in the first level (lowest resolution) of the level set.
28+
* The geographic width and height in degrees of tiles in the first level (the lowest resolution) of the level set.
2929
*/
30-
public double firstLevelDelta = 90;
30+
public final Location firstLevelDelta = new Location(90, 90);
3131

3232
/**
3333
* The number of levels in the level set.
@@ -69,12 +69,12 @@ public LevelSetConfig() {
6969
* sample points in the latitudinal direction of elevation tiles associate with the level
7070
* set
7171
*/
72-
public LevelSetConfig(Sector sector, double firstLevelDelta, int numLevels, int tileWidth, int tileHeight) {
72+
public LevelSetConfig(Sector sector, Location firstLevelDelta, int numLevels, int tileWidth, int tileHeight) {
7373
if (sector != null) {
7474
this.sector.set(sector);
7575
}
7676

77-
this.firstLevelDelta = firstLevelDelta;
77+
this.firstLevelDelta.set(firstLevelDelta);
7878
this.numLevels = numLevels;
7979
this.tileWidth = tileWidth;
8080
this.tileHeight = tileHeight;
@@ -97,7 +97,7 @@ public int numLevelsForResolution(double radiansPerPixel) {
9797
}
9898

9999
double degreesPerPixel = Math.toDegrees(radiansPerPixel);
100-
double firstLevelDegreesPerPixel = this.firstLevelDelta / Math.min(this.tileWidth, this.tileHeight);
100+
double firstLevelDegreesPerPixel = Math.max(this.firstLevelDelta.longitude / this.tileWidth, this.firstLevelDelta.latitude / this.tileHeight);
101101
double level = Math.log(firstLevelDegreesPerPixel / degreesPerPixel) / Math.log(2); // fractional level address
102102
int levelNumber = (int) Math.ceil(level); // ceiling captures the resolution
103103

@@ -126,7 +126,7 @@ public int numLevelsForMinResolution(double radiansPerPixel) {
126126
}
127127

128128
double degreesPerPixel = Math.toDegrees(radiansPerPixel);
129-
double firstLevelDegreesPerPixel = this.firstLevelDelta / this.tileHeight;
129+
double firstLevelDegreesPerPixel = Math.max(this.firstLevelDelta.longitude / this.tileWidth, this.firstLevelDelta.latitude / this.tileHeight);
130130
double level = Math.log(firstLevelDegreesPerPixel / degreesPerPixel) / Math.log(2); // fractional level address
131131
int levelNumber = (int) Math.floor(level); // floor prevents exceeding the min scale
132132

0 commit comments

Comments
 (0)