Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/feature/geopackage' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
ComBatVision committed Jul 25, 2022
2 parents 625953b + 6d01bab commit 6d66205
Show file tree
Hide file tree
Showing 14 changed files with 107 additions and 103 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 @@ -279,7 +279,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 @@ -665,7 +668,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 @@ -5,15 +5,15 @@
import java.util.Collection;

import gov.nasa.worldwind.geom.Location;
import gov.nasa.worldwind.render.ImageSource;
import gov.nasa.worldwind.render.ImageTile;
import gov.nasa.worldwind.util.DownloadPostprocessor;
import gov.nasa.worldwind.util.Level;
import gov.nasa.worldwind.util.LevelSet;
import gov.nasa.worldwind.util.Logger;
import gov.nasa.worldwind.util.Tile;
import gov.nasa.worldwind.util.TileFactory;

class MercatorImageTile extends ImageTile implements ImageSource.Transformer {
class MercatorImageTile extends ImageTile implements DownloadPostprocessor<Bitmap> {

/**
* Constructs a tile with a specified sector, level, row and column.
Expand Down Expand Up @@ -53,23 +53,25 @@ 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);
int firstCol = Tile.computeColumn(dLon, sector.minLongitude(), tileOrigin.longitude);
int lastCol = Tile.computeLastColumn(dLon, sector.maxLongitude(), tileOrigin.longitude);

double deltaLat = dLat / 90;
double d1 = sector.minLatPercent() + deltaLat * firstRow;
double dLatPercent = dLat / sector.deltaLatitude() * (sector.maxLatPercent() - sector.minLatPercent());
double firstRowPercent = MercatorSector.gudermannianInverse(tileOrigin.latitude) + firstRow * dLatPercent;
double firstColLon = tileOrigin.longitude + firstCol * dLon;

double d1 = firstRowPercent;
for (int row = firstRow; row <= lastRow; row++) {
double d2 = d1 + deltaLat;
double t1 = tileOrigin.longitude + (firstCol * dLon);
double d2 = d1 + dLatPercent;
double t1 = firstColLon;
for (int col = firstCol; col <= lastCol; col++) {
double t2;
t2 = t1 + dLon;
result.add(tileFactory.createTile(MercatorSector.fromDegrees(d1, d2, t1, t2), level, row, col));
double t2 = t1 + dLon;
result.add(tileFactory.createTile(new MercatorSector(d1, d2, t1, t2), level, row, col));
t1 = t2;
}
d1 = d2;
Expand Down Expand Up @@ -114,31 +116,33 @@ public Tile[] subdivide(TileFactory tileFactory) {
int eastCol = westCol + 1;

Tile[] children = new Tile[4];
children[0] = tileFactory.createTile(MercatorSector.fromDegrees(d0, d1, t0, t1), childLevel, northRow, westCol);
children[1] = tileFactory.createTile(MercatorSector.fromDegrees(d0, d1, t1, t2), childLevel, northRow, eastCol);
children[2] = tileFactory.createTile(MercatorSector.fromDegrees(d1, d2, t0, t1), childLevel, southRow, westCol);
children[3] = tileFactory.createTile(MercatorSector.fromDegrees(d1, d2, t1, t2), childLevel, southRow, eastCol);
children[0] = tileFactory.createTile(new MercatorSector(d0, d1, t0, t1), childLevel, northRow, westCol);
children[1] = tileFactory.createTile(new MercatorSector(d0, d1, t1, t2), childLevel, northRow, eastCol);
children[2] = tileFactory.createTile(new MercatorSector(d1, d2, t0, t1), childLevel, southRow, westCol);
children[3] = tileFactory.createTile(new MercatorSector(d1, d2, t1, t2), childLevel, southRow, eastCol);

return children;
}

@Override
public Bitmap transform(Bitmap bitmap) {
public Bitmap process(Bitmap resource) {
// Re-project mercator tile to equirectangular
Bitmap trans = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
int[] pixels = new int[resource.getWidth() * resource.getHeight()];
int[] result = new int[resource.getWidth() * resource.getHeight()];
resource.getPixels(pixels, 0, resource.getWidth(), 0, 0, resource.getWidth(), resource.getHeight());
double miny = ((MercatorSector) sector).minLatPercent();
double maxy = ((MercatorSector) sector).maxLatPercent();
for (int y = 0; y < bitmap.getHeight(); y++) {
double sy = 1.0 - y / (double) (bitmap.getHeight() - 1);
for (int y = 0; y < resource.getHeight(); y++) {
double sy = 1.0 - y / (double) (resource.getHeight() - 1);
double lat = sy * (sector.maxLatitude() - sector.minLatitude()) + sector.minLatitude();
double dy = 1.0 - (MercatorSector.gudermannianInverse(lat) - miny) / (maxy - miny);
dy = Math.max(0.0, Math.min(1.0, dy));
int iy = (int) (dy * (bitmap.getHeight() - 1));
for (int x = 0; x < bitmap.getWidth(); x++) {
trans.setPixel(x, y, bitmap.getPixel(x, iy));
int iy = (int) (dy * (resource.getHeight() - 1));
for (int x = 0; x < resource.getWidth(); x++) {
result[x + y * resource.getWidth()] = pixels[x + iy * resource.getWidth()];
}
}
return trans;
return Bitmap.createBitmap(result, resource.getWidth(), resource.getHeight(), resource.getConfig());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ public class MercatorSector extends Sector {

private final double minLatPercent, maxLatPercent;

private MercatorSector(double minLatPercent, double maxLatPercent,
double minLongitude, double maxLongitude) {
public MercatorSector(double minLatPercent, double maxLatPercent, double minLongitude, double maxLongitude) {
this.minLatPercent = minLatPercent;
this.maxLatPercent = maxLatPercent;
this.minLatitude = gudermannian(minLatPercent);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@

public abstract class MercatorTiledImageLayer extends RenderableLayer implements TileFactory {

private static final double FULL_SPHERE = 360;

private final int firstLevelOffset;

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

MercatorSector sector = new MercatorSector(-1.0, 1.0, -180.0, 180.0);
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
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.net.URL;

import gov.nasa.worldwind.WorldWind;
import gov.nasa.worldwind.util.DownloadPostprocessor;
import gov.nasa.worldwind.util.Logger;
import gov.nasa.worldwind.util.Retriever;

Expand Down Expand Up @@ -71,7 +72,7 @@ protected Bitmap decodeImage(ImageSource imageSource, ImageOptions imageOptions)
}

if (imageSource.isUrl()) {
return this.decodeUrl(imageSource.asUrl(), imageOptions, imageSource.transformer);
return this.decodeUrl(imageSource.asUrl(), imageOptions, imageSource.postprocessor);
}

return this.decodeUnrecognized(imageSource);
Expand All @@ -87,7 +88,7 @@ protected Bitmap decodeFilePath(String pathName, ImageOptions imageOptions) {
return BitmapFactory.decodeFile(pathName, factoryOptions);
}

protected Bitmap decodeUrl(String urlString, ImageOptions imageOptions, ImageSource.Transformer transformer) throws IOException {
protected Bitmap decodeUrl(String urlString, ImageOptions imageOptions, DownloadPostprocessor<Bitmap> postprocessor) throws IOException {
// TODO establish a file caching service for remote resources
// TODO retry absent resources, they are currently handled but suppressed entirely after the first failure
// TODO configurable connect and read timeouts
Expand All @@ -104,8 +105,8 @@ protected Bitmap decodeUrl(String urlString, ImageOptions imageOptions, ImageSou
Bitmap bitmap = BitmapFactory.decodeStream(stream, null, factoryOptions);

// Apply bitmap transformation if required
if (transformer != null && bitmap != null) {
bitmap = transformer.transform(bitmap);
if (postprocessor != null && bitmap != null) {
bitmap = postprocessor.process(bitmap);
}

return bitmap;
Expand Down
21 changes: 5 additions & 16 deletions worldwind/src/main/java/gov/nasa/worldwind/render/ImageSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import java.util.Arrays;
import java.util.HashMap;

import gov.nasa.worldwind.util.DownloadPostprocessor;
import gov.nasa.worldwind.util.Logger;
import gov.nasa.worldwind.util.WWUtil;

Expand Down Expand Up @@ -52,18 +53,6 @@ public interface BitmapFactory {
Bitmap createBitmap();
}

/**
* Interface for remote image source post-transformation
*/
public interface Transformer {
/**
* Transforms image according to specified algorithm implementation
* @param bitmap original bitmap
* @return transformed bitmap
*/
Bitmap transform(Bitmap bitmap);
}

protected static final HashMap<Object, BitmapFactory> lineStippleFactories = new HashMap<>();

protected static final int TYPE_UNRECOGNIZED = 0;
Expand All @@ -82,7 +71,7 @@ public interface Transformer {

protected Object source;

protected Transformer transformer;
protected DownloadPostprocessor<Bitmap> postprocessor;

protected ImageSource() {
}
Expand Down Expand Up @@ -194,15 +183,15 @@ public static ImageSource fromUrl(String urlString) {
* application's manifest must include the permissions that allow network connections.
*
* @param urlString complete URL string
* @param transformer implementation of image post-transformation routine
* @param postprocessor implementation of image post-transformation routine
*
* @return the new image source
*
* @throws IllegalArgumentException If the URL string is null
*/
public static ImageSource fromUrl(String urlString, Transformer transformer) {
public static ImageSource fromUrl(String urlString, DownloadPostprocessor<Bitmap> postprocessor) {
ImageSource imageSource = fromUrl(urlString);
imageSource.transformer = transformer;
imageSource.postprocessor = postprocessor;
return imageSource;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package gov.nasa.worldwind.util;

/**
* Interface for resource download post-processing
*/
public interface DownloadPostprocessor<T> {
/**
* Process resource according to specified algorithm implementation
*
* @param resource original resource
* @return processed resource
*/
T process(T resource);
}
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
Loading

0 comments on commit 6d66205

Please sign in to comment.