From b06896ccc4d496779c160597094c7aa2f84ddafa Mon Sep 17 00:00:00 2001 From: Wiehann Matthysen Date: Mon, 5 Sep 2016 12:37:33 +0200 Subject: [PATCH] Added procedural layer generation. - Added a ProceduralTiledImageLayer that I harvested from the blog: http://patmurris.blogspot.com/2008/02/procedural-image-layers-for-worldwind.html - The Heightmaplayer that I added was also taken from the abovementioned source (the name being ProceduralLayerTest), but with a slightly modified calculation algorithm. Instead of doing a modulous on the different heights, the elevation values was transformed with a arctan function, to give the effect where low elevation values would be blue and green (below sea level in general), and elevation levels above sea level would be yellow, going up to red. A future improvement for this could probably be to provide a pluggable function that calculates the colour value, given an elevation value. Also, a color legend would be useful to have on the side of the screen. --- .../nasa/worldwind/layers/HeightmapLayer.java | 79 +++++++++++++++++++ .../layers/ProceduralTiledImageLayer.java | 60 ++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 src/gov/nasa/worldwind/layers/HeightmapLayer.java create mode 100644 src/gov/nasa/worldwind/layers/ProceduralTiledImageLayer.java diff --git a/src/gov/nasa/worldwind/layers/HeightmapLayer.java b/src/gov/nasa/worldwind/layers/HeightmapLayer.java new file mode 100644 index 0000000000..248affa326 --- /dev/null +++ b/src/gov/nasa/worldwind/layers/HeightmapLayer.java @@ -0,0 +1,79 @@ +/** + * Copyright (C) 2014, United States Government as represented by the + * Administrator of the National Aeronautics and Space Administration, + * All Rights Reserved. + */ +package gov.nasa.worldwind.layers; + +import gov.nasa.worldwind.avlist.AVKey; +import gov.nasa.worldwind.avlist.AVList; +import gov.nasa.worldwind.avlist.AVListImpl; +import gov.nasa.worldwind.geom.Angle; +import gov.nasa.worldwind.geom.LatLon; +import gov.nasa.worldwind.geom.Sector; +import gov.nasa.worldwind.globes.Globe; +import gov.nasa.worldwind.util.LevelSet; + +import java.awt.Color; +import java.awt.image.BufferedImage; + +/** + * Procedural height-map layer. + * @author Patrick Murris + * @version $Id:$ + */ +public class HeightmapLayer extends ProceduralTiledImageLayer +{ + + private final Globe globe; + + public HeightmapLayer(Globe globe) + { + super(makeLevels()); + this.globe = globe; + } + + private static LevelSet makeLevels() + { + AVList params = new AVListImpl(); + params.setValue(AVKey.TILE_WIDTH, 128); + params.setValue(AVKey.TILE_HEIGHT, 128); + params.setValue(AVKey.DATA_CACHE_NAME, "Earth/Heightmap"); + params.setValue(AVKey.DATASET_NAME, "Heightmap"); + params.setValue(AVKey.FORMAT_SUFFIX, ".png"); + params.setValue(AVKey.NUM_LEVELS, 10); + params.setValue(AVKey.NUM_EMPTY_LEVELS, 0); + params.setValue(AVKey.LEVEL_ZERO_TILE_DELTA, new LatLon(Angle.fromDegrees(36.0), Angle.fromDegrees(36.0))); + params.setValue(AVKey.SECTOR, Sector.FULL_SPHERE); + return new LevelSet(params); + } + + @Override + protected BufferedImage createTileImage(TextureTile tile, BufferedImage image) + { + int width = tile.getLevel().getTileWidth(); + int height = tile.getLevel().getTileHeight(); + double latStep = tile.getSector().getDeltaLatDegrees() / height; + double lonStep = tile.getSector().getDeltaLonDegrees() / width; + + for (int x = 0; x < width; x++) + { + double lon = tile.getSector().getMinLongitude().degrees + lonStep * x + (lonStep / 2.0); + for (int y = 0; y < height; y++) + { + double lat = tile.getSector().getMaxLatitude().degrees - latStep * y - (latStep / 2.0); + double elevation = this.globe.getElevation(Angle.fromDegrees(lat), Angle.fromDegrees(lon)); + double ratio = (elevation - this.globe.getMinElevation()) / (this.globe.getMaxElevation() - this.globe.getMinElevation()); + float hue = (float)Math.atan(Math.pow(1.0 - ratio, 2.0)); + image.setRGB(x, y, Color.HSBtoRGB(hue, 1f, 1f)); + } + } + return image; + } + + @Override + public String toString() + { + return "Heightmap Layer"; + } +} \ No newline at end of file diff --git a/src/gov/nasa/worldwind/layers/ProceduralTiledImageLayer.java b/src/gov/nasa/worldwind/layers/ProceduralTiledImageLayer.java new file mode 100644 index 0000000000..e9d7803fcc --- /dev/null +++ b/src/gov/nasa/worldwind/layers/ProceduralTiledImageLayer.java @@ -0,0 +1,60 @@ +/** + * Copyright (C) 2014, United States Government as represented by the + * Administrator of the National Aeronautics and Space Administration, + * All Rights Reserved. + */ +package gov.nasa.worldwind.layers; + + +import gov.nasa.worldwind.WorldWind; +import gov.nasa.worldwind.avlist.AVList; +import gov.nasa.worldwind.util.LevelSet; +import gov.nasa.worldwind.util.Logging; + +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; + +import javax.imageio.ImageIO; + +/** + * @author Patrick Murris + * @version $Id:$ + */ +public abstract class ProceduralTiledImageLayer extends BasicTiledImageLayer +{ + public ProceduralTiledImageLayer(LevelSet levelSet) + { + super(levelSet); + } + + public ProceduralTiledImageLayer(AVList params) + { + super(params); + } + + abstract BufferedImage createTileImage(TextureTile tile, BufferedImage image); + + @Override + protected void retrieveTexture(final TextureTile tile, DownloadPostProcessor postProcessor) + { + final File outFile = WorldWind.getDataFileStore().newFile(tile.getPath()); + if (outFile == null || outFile.exists()) + return; + + // Create and save tile texture image. + int width = tile.getLevel().getTileWidth(); + int height = tile.getLevel().getTileHeight(); + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); + image = createTileImage(tile, image); + try + { + ImageIO.write(image, "png", outFile); + } + catch (IOException e) + { + String msg = Logging.getMessage("layers.TextureLayer.ExceptionSavingRetrievedTextureFile", outFile.getPath()); + Logging.logger().log(java.util.logging.Level.SEVERE, msg, e); + } + } +} \ No newline at end of file