Skip to content

Commit

Permalink
Separate first level delta in Level Set for latitude and longitude.
Browse files Browse the repository at this point in the history
  • Loading branch information
ComBatVision committed Jun 29, 2022
1 parent c17e8b0 commit fba5af4
Show file tree
Hide file tree
Showing 10 changed files with 55 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
public class BasicTessellator implements Tessellator, TileFactory {

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

protected double detailControl = 80;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public BlueMarbleLandsatLayer(String serviceAddress) {

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

if (metersPerPixel < 2.0e3) { // switch to Landsat at 2km resolution
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,10 @@ protected void createFromGeoPackageAsync(String pathName, Layer layer, Callback
tileMatrixSet.getMaxY() - tileMatrixSet.getMinY(),
tileMatrixSet.getMaxX() - tileMatrixSet.getMinX());
config.tileOrigin.set(tileMatrixSet.getMinY(), tileMatrixSet.getMinX());
config.firstLevelDelta = (tileMatrixSet.getMaxY() - tileMatrixSet.getMinY()) / tileMatrix.valueAt(0).getMatrixHeight();
config.firstLevelDelta.set(
(tileMatrixSet.getMaxY() - tileMatrixSet.getMinY()) / tileMatrix.valueAt(0).getMatrixHeight(),
(tileMatrixSet.getMaxX() - tileMatrixSet.getMinX()) / tileMatrix.valueAt(0).getMatrixWidth()
);
config.numLevels = tileMatrix.keyAt(tileMatrix.size() - 1) - tileMatrix.keyAt(0) + 1;

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

return new LevelSet(boundingBox, new Location(-90, -180), 90, compatibleTileMatrixSet.tileMatrices.size(), imageSize, imageSize);
return new LevelSet(boundingBox, new Location(-90, -180), new Location(90, 90), compatibleTileMatrixSet.tileMatrices.size(), imageSize, imageSize);
}

protected String buildWmtsKvpTemplate(String kvpServiceAddress, String layer, String format, String styleIdentifier, String tileMatrixSet) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ static void assembleMercatorTilesForLevel(Level level, TileFactory tileFactory,
// NOTE LevelSet.sector is final Sector attribute and thus can not be cast to MercatorSector!
MercatorSector sector = MercatorSector.fromSector(level.parent.sector);
Location tileOrigin = level.parent.tileOrigin;
double dLat = level.tileDelta / 2;
double dLon = level.tileDelta;
double dLat = level.tileDelta.latitude;
double dLon = level.tileDelta.longitude;

int firstRow = Tile.computeRow(dLat, sector.minLatitude(), tileOrigin.latitude);
int lastRow = Tile.computeLastRow(dLat, sector.maxLatitude(), tileOrigin.latitude);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ public MercatorTiledImageLayer(String name, int numLevels, int firstLevelOffset,
this.setPickEnabled(false);
this.firstLevelOffset = firstLevelOffset;

MercatorSector sector = MercatorSector.fromDegrees(-1.0, 1.0, - FULL_SPHERE / 2, FULL_SPHERE / 2);
Location tileOrigin = new Location(sector.minLatitude(), sector.minLongitude());
int n = 1 << firstLevelOffset;
Location firstLevelDelta = new Location(sector.deltaLatitude() / n, sector.deltaLongitude() / n);
MercatorTiledSurfaceImage surfaceImage = new MercatorTiledSurfaceImage();
surfaceImage.setLevelSet(new LevelSet(
MercatorSector.fromDegrees(-1.0, 1.0, - FULL_SPHERE / 2, FULL_SPHERE / 2), new Location(-90, -180),
FULL_SPHERE / (1 << firstLevelOffset), numLevels - firstLevelOffset, tileSize, tileSize));
surfaceImage.setLevelSet(new LevelSet(sector, tileOrigin, firstLevelDelta, numLevels - firstLevelOffset, tileSize, tileSize));
surfaceImage.setTileFactory(this);
if(!overlay) {
surfaceImage.setImageOptions(new ImageOptions(WorldWind.RGB_565)); // reduce memory usage by using a 16-bit configuration with no alpha
Expand Down
12 changes: 7 additions & 5 deletions worldwind/src/main/java/gov/nasa/worldwind/util/Level.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

package gov.nasa.worldwind.util;

import gov.nasa.worldwind.geom.Location;

/**
* Represents a level of a specific resolution in a {@link LevelSet}.
*/
Expand Down Expand Up @@ -35,7 +37,7 @@ public class Level {
/**
* The geographic width and height in degrees of tiles within this level.
*/
public final double tileDelta;
public final Location tileDelta;

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

if (tileDelta <= 0) {
if (tileDelta == null || tileDelta.latitude <= 0 || tileDelta.longitude <= 0) {
throw new IllegalArgumentException(
Logger.logMessage(Logger.ERROR, "Level", "constructor", "The tile delta is zero"));
}

this.parent = parent;
this.levelNumber = levelNumber;
this.levelWidth = (int) Math.round(parent.tileWidth * parent.sector.deltaLongitude() / tileDelta);
this.levelHeight = (int) Math.round(parent.tileHeight * parent.sector.deltaLatitude() / tileDelta);
this.levelWidth = (int) Math.round(parent.tileWidth * parent.sector.deltaLongitude() / tileDelta.longitude);
this.levelHeight = (int) Math.round(parent.tileHeight * parent.sector.deltaLatitude() / tileDelta.latitude);
this.tileDelta = tileDelta;
this.tileWidth = parent.tileWidth;
this.tileHeight = parent.tileHeight;
Expand Down
25 changes: 10 additions & 15 deletions worldwind/src/main/java/gov/nasa/worldwind/util/LevelSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ public class LevelSet {
public final Location tileOrigin = new Location();

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

/**
* The width in pixels of images associated with tiles in this level set, or the number of sample points in the
Expand All @@ -51,7 +51,6 @@ public class LevelSet {
* <code>firstLevel</code> and <code>lastLevel</code> always return null.
*/
public LevelSet() {
this.firstLevelDelta = 0;
this.tileWidth = 0;
this.tileHeight = 0;
this.levels = new Level[0];
Expand All @@ -74,7 +73,7 @@ public LevelSet() {
*
* @throws IllegalArgumentException If any argument is null, or if any dimension is zero
*/
public LevelSet(Sector sector, Location tileOrigin, double firstLevelDelta, int numLevels, int tileWidth, int tileHeight) {
public LevelSet(Sector sector, Location tileOrigin, Location firstLevelDelta, int numLevels, int tileWidth, int tileHeight) {
if (sector == null) {
throw new IllegalArgumentException(
Logger.logMessage(Logger.ERROR, "LevelSet", "constructor", "missingSector"));
Expand All @@ -85,7 +84,7 @@ public LevelSet(Sector sector, Location tileOrigin, double firstLevelDelta, int
Logger.logMessage(Logger.ERROR, "LevelSet", "constructor", "missingTileOrigin"));
}

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

this.sector.set(sector);
this.tileOrigin.set(tileOrigin);
this.firstLevelDelta = firstLevelDelta;
this.firstLevelDelta.set(firstLevelDelta);
this.tileWidth = tileWidth;
this.tileHeight = tileHeight;
this.levels = new Level[numLevels];
Expand All @@ -129,12 +128,7 @@ public LevelSet(LevelSetConfig config) {
Logger.logMessage(Logger.ERROR, "LevelSet", "constructor", "missingSector"));
}

if (config.tileOrigin == null) {
throw new IllegalArgumentException(
Logger.logMessage(Logger.ERROR, "LevelSet", "constructor", "missingTileOrigin"));
}

if (config.firstLevelDelta <= 0) {
if (config.firstLevelDelta.latitude <= 0 || config.firstLevelDelta.longitude <= 0) {
throw new IllegalArgumentException(
Logger.logMessage(Logger.ERROR, "LevelSet", "constructor", "invalidTileDelta"));
}
Expand All @@ -151,7 +145,7 @@ public LevelSet(LevelSetConfig config) {

this.sector.set(config.sector);
this.tileOrigin.set(config.tileOrigin);
this.firstLevelDelta = config.firstLevelDelta;
this.firstLevelDelta.set(config.firstLevelDelta);
this.tileWidth = config.tileWidth;
this.tileHeight = config.tileHeight;
this.levels = new Level[config.numLevels];
Expand All @@ -160,7 +154,8 @@ public LevelSet(LevelSetConfig config) {

protected void assembleLevels() {
for (int i = 0, len = this.levels.length; i < len; i++) {
double delta = firstLevelDelta / (1 << i);
int n = 1 << i;
Location delta = new Location(firstLevelDelta.latitude / n, firstLevelDelta.longitude / n);
this.levels[i] = new Level(this, i, delta);
}
}
Expand Down Expand Up @@ -209,7 +204,7 @@ public Level levelForResolution(double radiansPerPixel) {
}

double degreesPerPixel = Math.toDegrees(radiansPerPixel);
double firstLevelDegreesPerPixel = this.firstLevelDelta / Math.min(this.tileWidth, this.tileHeight);
double firstLevelDegreesPerPixel = Math.max(this.firstLevelDelta.longitude / this.tileWidth, this.firstLevelDelta.latitude / this.tileHeight);
double level = Math.log(firstLevelDegreesPerPixel / degreesPerPixel) / Math.log(2); // fractional level address
int levelNumber = (int) Math.round(level); // nearest neighbor level

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ public class LevelSetConfig {
public final Location tileOrigin = new Location(-90, -180);

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

/**
* The number of levels in the level set.
Expand Down Expand Up @@ -69,12 +69,12 @@ public LevelSetConfig() {
* sample points in the latitudinal direction of elevation tiles associate with the level
* set
*/
public LevelSetConfig(Sector sector, double firstLevelDelta, int numLevels, int tileWidth, int tileHeight) {
public LevelSetConfig(Sector sector, Location firstLevelDelta, int numLevels, int tileWidth, int tileHeight) {
if (sector != null) {
this.sector.set(sector);
}

this.firstLevelDelta = firstLevelDelta;
this.firstLevelDelta.set(firstLevelDelta);
this.numLevels = numLevels;
this.tileWidth = tileWidth;
this.tileHeight = tileHeight;
Expand All @@ -97,7 +97,7 @@ public int numLevelsForResolution(double radiansPerPixel) {
}

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

Expand Down Expand Up @@ -126,7 +126,7 @@ public int numLevelsForMinResolution(double radiansPerPixel) {
}

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

Expand Down
33 changes: 17 additions & 16 deletions worldwind/src/main/java/gov/nasa/worldwind/util/Tile.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public Tile(Sector sector, Level level, int row, int column) {
this.row = row;
this.column = column;
this.tileKey = level.levelNumber + "." + row + "." + column;
this.texelSizeFactor = Math.toRadians(level.tileDelta / level.tileWidth) * Math.cos(Math.toRadians(sector.centroidLatitude()));
this.texelSizeFactor = Math.toRadians(level.tileDelta.longitude / level.tileWidth) * Math.cos(Math.toRadians(sector.centroidLatitude()));
}

/**
Expand Down Expand Up @@ -217,29 +217,29 @@ public static Collection<Tile> assembleTilesForLevel(Level level, TileFactory ti

Sector sector = level.parent.sector;
Location tileOrigin = level.parent.tileOrigin;
double tileDelta = level.tileDelta;
Location tileDelta = level.tileDelta;

int firstRow = Tile.computeRow(tileDelta, sector.minLatitude(), tileOrigin.latitude);
int lastRow = Tile.computeLastRow(tileDelta, sector.maxLatitude(), tileOrigin.latitude);
int firstCol = Tile.computeColumn(tileDelta, sector.minLongitude(), tileOrigin.longitude);
int lastCol = Tile.computeLastColumn(tileDelta, sector.maxLongitude(), tileOrigin.longitude);
int firstRow = Tile.computeRow(tileDelta.latitude, sector.minLatitude(), tileOrigin.latitude);
int lastRow = Tile.computeLastRow(tileDelta.latitude, sector.maxLatitude(), tileOrigin.latitude);
int firstCol = Tile.computeColumn(tileDelta.longitude, sector.minLongitude(), tileOrigin.longitude);
int lastCol = Tile.computeLastColumn(tileDelta.longitude, sector.maxLongitude(), tileOrigin.longitude);

double firstRowLat = tileOrigin.latitude + firstRow * tileDelta;
double firstRowLon = tileOrigin.longitude + firstCol * tileDelta;
double firstRowLat = tileOrigin.latitude + firstRow * tileDelta.latitude;
double firstRowLon = tileOrigin.longitude + firstCol * tileDelta.longitude;
double lat = firstRowLat;
double lon;

for (int row = firstRow; row <= lastRow; row++) {
lon = firstRowLon;

for (int col = firstCol; col <= lastCol; col++) {
Sector tileSector = new Sector(lat, lon, tileDelta, tileDelta);
Sector tileSector = new Sector(lat, lon, tileDelta.latitude, tileDelta.longitude);
result.add(tileFactory.createTile(tileSector, level, row, col));

lon += tileDelta;
lon += tileDelta.longitude;
}

lat += tileDelta;
lat += tileDelta.latitude;
}

return result;
Expand Down Expand Up @@ -334,26 +334,27 @@ public Tile[] subdivide(TileFactory tileFactory) {
double lonMin = this.sector.minLongitude();
double latMid = this.sector.centroidLatitude();
double lonMid = this.sector.centroidLongitude();
double childDelta = this.level.tileDelta * 0.5;
double childDeltaLat = this.level.tileDelta.latitude * 0.5;
double childDeltaLon = this.level.tileDelta.longitude * 0.5;

int childRow = 2 * this.row;
int childCol = 2 * this.column;
Sector childSector = new Sector(latMin, lonMin, childDelta, childDelta);
Sector childSector = new Sector(latMin, lonMin, childDeltaLat, childDeltaLon);
children[0] = tileFactory.createTile(childSector, childLevel, childRow, childCol); // Southwest

childRow = 2 * this.row;
childCol = 2 * this.column + 1;
childSector = new Sector(latMin, lonMid, childDelta, childDelta);
childSector = new Sector(latMin, lonMid, childDeltaLat, childDeltaLon);
children[1] = tileFactory.createTile(childSector, childLevel, childRow, childCol); // Southeast

childRow = 2 * this.row + 1;
childCol = 2 * this.column;
childSector = new Sector(latMid, lonMin, childDelta, childDelta);
childSector = new Sector(latMid, lonMin, childDeltaLat, childDeltaLon);
children[2] = tileFactory.createTile(childSector, childLevel, childRow, childCol); // Northwest

childRow = 2 * this.row + 1;
childCol = 2 * this.column + 1;
childSector = new Sector(latMid, lonMid, childDelta, childDelta);
childSector = new Sector(latMid, lonMid, childDeltaLat, childDeltaLon);
children[3] = tileFactory.createTile(childSector, childLevel, childRow, childCol); // Northeast

return children;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public void setUp() {
this.terrain = new BasicTerrain();

// Add a terrain tile used to the mocked terrain
LevelSet levelSet = new LevelSet(new Sector().setFullSphere(), new Location(-90, -180), 1.0, 1, 5, 5); // tiles with 5x5 vertices
LevelSet levelSet = new LevelSet(new Sector().setFullSphere(), new Location(-90, -180), new Location(1.0, 1.0), 1, 5, 5); // tiles with 5x5 vertices
TerrainTile tile = new TerrainTile(new Sector(0, 0, 1, 1), levelSet.firstLevel(), 90, 180);
((BasicTerrain) this.terrain).addTile(tile);

Expand Down

0 comments on commit fba5af4

Please sign in to comment.