From 1685e4b8fc0a225fb527d6f436028d9030f6b222 Mon Sep 17 00:00:00 2001
From: Luc Maisonobe <luc@orekit.org>
Date: Mon, 10 Mar 2014 08:46:02 +0100
Subject: [PATCH] Added global min/max handling for any tile.

---
 .../orekit/rugged/core/dem/AbstractTile.java  | 82 ++++++++++++++++++-
 .../orekit/rugged/core/dem/SimpleTile.java    | 18 ++--
 .../java/org/orekit/rugged/core/dem/Tile.java | 10 +++
 .../rugged/core/duvenhage/MinMaxTreeTile.java | 18 ++--
 ...va => CheckedPatternElevationUpdater.java} | 16 ++--
 .../rugged/core/dem/TilesCacheTest.java       | 14 +++-
 6 files changed, 123 insertions(+), 35 deletions(-)
 rename rugged-core/src/test/java/orekit/rugged/core/dem/{ConstantElevationUpdater.java => CheckedPatternElevationUpdater.java} (76%)

diff --git a/rugged-core/src/main/java/org/orekit/rugged/core/dem/AbstractTile.java b/rugged-core/src/main/java/org/orekit/rugged/core/dem/AbstractTile.java
index af448dae..22b3f050 100644
--- a/rugged-core/src/main/java/org/orekit/rugged/core/dem/AbstractTile.java
+++ b/rugged-core/src/main/java/org/orekit/rugged/core/dem/AbstractTile.java
@@ -43,6 +43,12 @@ public abstract class AbstractTile implements Tile {
     /** Number of longitude columns. */
     private int longitudeColumns;
 
+    /** Minimum elevation. */
+    private double minElevation;
+
+    /** Maximum elevation. */
+    private double maxElevation;
+
     /** Simple constructor.
      * <p>
      * Creates an empty tile.
@@ -62,8 +68,27 @@ public abstract class AbstractTile implements Tile {
         this.longitudeStep    = longitudeStep;
         this.latitudeRows     = latitudeRows;
         this.longitudeColumns = longitudeColumns;
+        this.minElevation     = Double.POSITIVE_INFINITY;
+        this.maxElevation     = Double.NEGATIVE_INFINITY;
+        doSetGeometry(minLatitude, minLongitude, latitudeStep, longitudeStep, latitudeRows, longitudeColumns);
     }
 
+    /** Set the tile global geometry.
+     * <p>
+     * This method is called by {@link #setGeometry(double, double, double,
+     * double, int, int)} after boilerplate processing has been performed.
+     * </p>
+     * @param minLatitude minimum latitude
+     * @param minLongitude minimum longitude
+     * @param latitudeStep step in latitude (size of one raster element)
+     * @param longitudeStep step in longitude (size of one raster element)
+     * @param latitudeRows number of latitude rows
+     * @param longitudeColumns number of longitude columns
+     */
+    protected abstract void doSetGeometry(double minLatitude, double minLongitude,
+                                          double latitudeStep, double longitudeStep,
+                                          int latitudeRows, int longitudeColumns);
+
     /** {@inheritDoc} */
     @Override
     public void tileUpdateCompleted() throws RuggedException {
@@ -106,6 +131,61 @@ public abstract class AbstractTile implements Tile {
         return longitudeColumns;
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public double getMinElevation() {
+        return minElevation;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public double getMaxElevation() {
+        return maxElevation;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void setElevation(final int latitudeIndex, final int longitudeIndex,
+                             final double elevation) throws RuggedException {
+        checkIndices(latitudeIndex, longitudeIndex);
+        minElevation = FastMath.min(minElevation, elevation);
+        maxElevation = FastMath.max(maxElevation, elevation);
+        doSetElevation(latitudeIndex, longitudeIndex, elevation);
+    }
+
+    /** Set the elevation for one raster element.
+     * <p>
+     * This method is called by {@link #setElevation(int, int, double)} after
+     * boilerplate processing has been performed, including indices checks.
+     * </p>
+     * @param latitudeIndex index of latitude (row index)
+     * @param longitudeIndex index of longitude (column index)
+     * @param elevation elevation (m)
+     * @exception RuggedException if indices are out of bound
+     */
+    protected abstract void doSetElevation(int latitudeIndex, int longitudeIndex, double elevation)
+        throws RuggedException;
+
+    /** {@inheritDoc} */
+    @Override
+    public double getElevationAtIndices(int latitudeIndex, int longitudeIndex)
+        throws RuggedException {
+        checkIndices(latitudeIndex, longitudeIndex);
+        return doGetElevationAtIndices(latitudeIndex, longitudeIndex);
+    }
+
+    /** Get the elevation of an exact grid point.
+     * <p>
+     * This method is called by {@link #getElevationAtIndices(int, int)} after
+     * boilerplate processing has been performed, including indices checks.
+     * </p>
+     * @param latitudeIndex
+     * @param longitudeIndex
+     * @return elevation
+     */
+    protected abstract double doGetElevationAtIndices(int latitudeIndex, int longitudeIndex)
+        throws RuggedException;
+
     /** {@inheritDoc} */
     @Override
     public boolean covers(final double latitude, final double longitude) {
@@ -120,7 +200,7 @@ public abstract class AbstractTile implements Tile {
      * @param longitudeIndex
      * @exception IllegalArgumentException if indices are out of bound
      */
-    protected void checkIndices(int latitudeIndex, int longitudeIndex)
+    private void checkIndices(int latitudeIndex, int longitudeIndex)
         throws RuggedException {
         if (latitudeIndex  < 0 || latitudeIndex  >= latitudeRows ||
             longitudeIndex < 0 || longitudeIndex >= longitudeColumns) {
diff --git a/rugged-core/src/main/java/org/orekit/rugged/core/dem/SimpleTile.java b/rugged-core/src/main/java/org/orekit/rugged/core/dem/SimpleTile.java
index f7e49a90..33ae236c 100644
--- a/rugged-core/src/main/java/org/orekit/rugged/core/dem/SimpleTile.java
+++ b/rugged-core/src/main/java/org/orekit/rugged/core/dem/SimpleTile.java
@@ -16,7 +16,6 @@
  */
 package org.orekit.rugged.core.dem;
 
-import org.orekit.rugged.api.RuggedException;
 
 /** Simple implementation of a {@link Tile}.
  * @see SimpleTileFactory
@@ -37,27 +36,22 @@ public class SimpleTile extends AbstractTile {
 
     /** {@inheritDoc} */
     @Override
-    public void setGeometry(final double minLatitude, final double minLongitude,
-                            final double latitudeStep, final double longitudeStep,
-                            final int latitudeRows, final int longitudeColumns) {
-        super.setGeometry(minLatitude, minLongitude, latitudeStep, longitudeStep,
-                          latitudeRows, longitudeColumns);
+    protected void doSetGeometry(final double minLatitude, final double minLongitude,
+                                 final double latitudeStep, final double longitudeStep,
+                                 final int latitudeRows, final int longitudeColumns) {
         this.elevations = new double[latitudeRows * longitudeColumns];
     }
 
     /** {@inheritDoc} */
     @Override
-    public void setElevation(final int latitudeIndex, final int longitudeIndex,
-                             final double elevation) throws RuggedException {
-        checkIndices(latitudeIndex, longitudeIndex);
+    protected void doSetElevation(final int latitudeIndex, final int longitudeIndex,
+                                  final double elevation) {
         elevations[latitudeIndex * getLongitudeColumns() + longitudeIndex] = elevation;
     }
 
     /** {@inheritDoc} */
     @Override
-    public double getElevationAtIndices(int latitudeIndex, int longitudeIndex)
-        throws RuggedException {
-        checkIndices(latitudeIndex, longitudeIndex);
+    protected double doGetElevationAtIndices(int latitudeIndex, int longitudeIndex) {
         return elevations[latitudeIndex * getLongitudeColumns() + longitudeIndex];
     }
 
diff --git a/rugged-core/src/main/java/org/orekit/rugged/core/dem/Tile.java b/rugged-core/src/main/java/org/orekit/rugged/core/dem/Tile.java
index cea32b73..c72ca783 100644
--- a/rugged-core/src/main/java/org/orekit/rugged/core/dem/Tile.java
+++ b/rugged-core/src/main/java/org/orekit/rugged/core/dem/Tile.java
@@ -60,6 +60,16 @@ public interface Tile extends UpdatableTile {
      */
     int getLongitudeColumns();
 
+    /** Get the minimum elevation in the tile.
+     * @return minimum elevation in the tile
+     */
+    double getMinElevation();
+
+    /** Get the maximum elevation in the tile.
+     * @return maximum elevation in the tile
+     */
+    double getMaxElevation();
+
     /** Get the elevation of an exact grid point.
      * @param latitudeIndex
      * @param longitudeIndex
diff --git a/rugged-core/src/main/java/org/orekit/rugged/core/duvenhage/MinMaxTreeTile.java b/rugged-core/src/main/java/org/orekit/rugged/core/duvenhage/MinMaxTreeTile.java
index 21fc4761..80fa5377 100644
--- a/rugged-core/src/main/java/org/orekit/rugged/core/duvenhage/MinMaxTreeTile.java
+++ b/rugged-core/src/main/java/org/orekit/rugged/core/duvenhage/MinMaxTreeTile.java
@@ -39,11 +39,9 @@ public class MinMaxTreeTile extends AbstractTile {
 
     /** {@inheritDoc} */
     @Override
-    public void setGeometry(final double minLatitude, final double minLongitude,
-                            final double latitudeStep, final double longitudeStep,
-                            final int latitudeRows, final int longitudeColumns) {
-        super.setGeometry(minLatitude, minLongitude, latitudeStep, longitudeStep,
-                          latitudeRows, longitudeColumns);
+    protected void doSetGeometry(final double minLatitude, final double minLongitude,
+                                 final double latitudeStep, final double longitudeStep,
+                                 final int latitudeRows, final int longitudeColumns) {
         this.elevations = new double[latitudeRows * longitudeColumns];
     }
 
@@ -56,18 +54,16 @@ public class MinMaxTreeTile extends AbstractTile {
 
     /** {@inheritDoc} */
     @Override
-    public void setElevation(final int latitudeIndex, final int longitudeIndex,
-                             final double elevation) throws RuggedException {
-        checkIndices(latitudeIndex, longitudeIndex);
+    protected void doSetElevation(final int latitudeIndex, final int longitudeIndex,
+                                  final double elevation) {
         elevations[latitudeIndex * getLongitudeColumns() + longitudeIndex] = elevation;
     }
 
     /** {@inheritDoc} */
     @Override
-    public double getElevationAtIndices(int latitudeIndex, int longitudeIndex)
-        throws RuggedException {
-        checkIndices(latitudeIndex, longitudeIndex);
+    protected double doGetElevationAtIndices(int latitudeIndex, int longitudeIndex) {
         return elevations[latitudeIndex * getLongitudeColumns() + longitudeIndex];
     }
 
+
 }
diff --git a/rugged-core/src/test/java/orekit/rugged/core/dem/ConstantElevationUpdater.java b/rugged-core/src/test/java/orekit/rugged/core/dem/CheckedPatternElevationUpdater.java
similarity index 76%
rename from rugged-core/src/test/java/orekit/rugged/core/dem/ConstantElevationUpdater.java
rename to rugged-core/src/test/java/orekit/rugged/core/dem/CheckedPatternElevationUpdater.java
index 00adab3e..8957e4bf 100644
--- a/rugged-core/src/test/java/orekit/rugged/core/dem/ConstantElevationUpdater.java
+++ b/rugged-core/src/test/java/orekit/rugged/core/dem/CheckedPatternElevationUpdater.java
@@ -21,16 +21,18 @@ import org.orekit.rugged.api.RuggedException;
 import org.orekit.rugged.api.TileUpdater;
 import org.orekit.rugged.api.UpdatableTile;
 
-public class ConstantElevationUpdater implements TileUpdater {
+public class CheckedPatternElevationUpdater implements TileUpdater {
 
     private double size;
     private int    n;
-    private double elevation;
+    private double elevation1;
+    private double elevation2;
 
-    public ConstantElevationUpdater(double size, int n, double elevation) {
-        this.size      = size;
-        this.n         = n;
-        this.elevation = elevation;
+    public CheckedPatternElevationUpdater(double size, int n, double elevation1, double elevation2) {
+        this.size       = size;
+        this.n          = n;
+        this.elevation1 = elevation1;
+        this.elevation2 = elevation2;
     }
 
     public void updateTile(double latitude, double longitude, UpdatableTile tile)
@@ -40,7 +42,7 @@ public class ConstantElevationUpdater implements TileUpdater {
                          size / n, size / n, n, n);
         for (int i = 0; i < n; ++i) {
             for (int j = 0; j < n; ++j) {
-                tile.setElevation(i, j, elevation);
+                tile.setElevation(i, j, (((i ^ j) & 0x1) == 0) ? elevation1 : elevation2);
             }
         }
     }
diff --git a/rugged-core/src/test/java/orekit/rugged/core/dem/TilesCacheTest.java b/rugged-core/src/test/java/orekit/rugged/core/dem/TilesCacheTest.java
index f17275f0..377f7fa4 100644
--- a/rugged-core/src/test/java/orekit/rugged/core/dem/TilesCacheTest.java
+++ b/rugged-core/src/test/java/orekit/rugged/core/dem/TilesCacheTest.java
@@ -31,20 +31,22 @@ public class TilesCacheTest {
     public void testSingleTile() throws RuggedException {
         CountingFactory factory = new CountingFactory();
         TilesCache<SimpleTile> cache = new TilesCache<SimpleTile>(factory,
-                new ConstantElevationUpdater(FastMath.toRadians(3.0), 10, 10.0), 1000);
+                new CheckedPatternElevationUpdater(FastMath.toRadians(3.0), 10, 10.0, 20.0), 1000);
         SimpleTile tile = cache.getTile(FastMath.toRadians(-23.2), FastMath.toRadians(137.5));
         Assert.assertEquals(1, factory.getCount());
         Assert.assertEquals(-24.0, FastMath.toDegrees(tile.getMinimumLatitude()),  1.0e-10);
         Assert.assertEquals(135.0, FastMath.toDegrees(tile.getMinimumLongitude()), 1.0e-10);
         Assert.assertEquals(  0.3, FastMath.toDegrees(tile.getLatitudeStep()),     1.0e-10);
         Assert.assertEquals(  0.3, FastMath.toDegrees(tile.getLongitudeStep()),    1.0e-10);
+        Assert.assertEquals(10.0, tile.getMinElevation(), 1.0e-10);
+        Assert.assertEquals(20.0, tile.getMaxElevation(), 1.0e-10);
     }
 
     @Test
     public void testEviction() throws RuggedException {
         CountingFactory factory = new CountingFactory();
         TilesCache<SimpleTile> cache = new TilesCache<SimpleTile>(factory,
-                new ConstantElevationUpdater(FastMath.toRadians(1.0), 10, 10.0), 12);
+                new CheckedPatternElevationUpdater(FastMath.toRadians(1.0), 10, 10.0, 20.0), 12);
 
         // fill up the 12 tiles we can keep in cache
         for (int i = 0; i < 4; ++i) {
@@ -90,7 +92,7 @@ public class TilesCacheTest {
         CountingFactory factory = new CountingFactory();
         TilesCache<SimpleTile> cache =
                 new TilesCache<SimpleTile>(factory,
-                                           new ConstantElevationUpdater(0.125, 8, 10.0),
+                                           new CheckedPatternElevationUpdater(0.125, 8, 10.0, 20.0),
                                            12);
 
         SimpleTile regularTile = cache.getTile(0.2, 0.6);
@@ -99,6 +101,8 @@ public class TilesCacheTest {
         Assert.assertEquals(0.5,      regularTile.getMinimumLongitude(), 1.0e-10);
         Assert.assertEquals(0.015625, regularTile.getLatitudeStep(),     1.0e-10);
         Assert.assertEquals(0.015625, regularTile.getLongitudeStep(),    1.0e-10);
+        Assert.assertEquals(10.0,     regularTile.getMinElevation(),     1.0e-10);
+        Assert.assertEquals(20.0,     regularTile.getMaxElevation(),     1.0e-10);
 
         SimpleTile tileAtEnd = cache.getTile(0.250, 0.625);
         Assert.assertEquals(1, factory.getCount());
@@ -106,6 +110,8 @@ public class TilesCacheTest {
         Assert.assertEquals(0.5,      tileAtEnd.getMinimumLongitude(), 1.0e-10);
         Assert.assertEquals(0.015625, tileAtEnd.getLatitudeStep(),     1.0e-10);
         Assert.assertEquals(0.015625, tileAtEnd.getLongitudeStep(),    1.0e-10);
+        Assert.assertEquals(10.0,     tileAtEnd.getMinElevation(),     1.0e-10);
+        Assert.assertEquals(20.0,     tileAtEnd.getMaxElevation(),     1.0e-10);
 
     }
 
@@ -114,7 +120,7 @@ public class TilesCacheTest {
         CountingFactory factory = new CountingFactory();
         TilesCache<SimpleTile> cache =
                 new TilesCache<SimpleTile>(factory,
-                                           new ConstantElevationUpdater(FastMath.toRadians(1.0), 10, 10.0),
+                                           new CheckedPatternElevationUpdater(FastMath.toRadians(1.0), 10, 10.0, 20.0),
                                            16);
 
         cache.getTile(FastMath.toRadians(1.5), FastMath.toRadians(0.5));
-- 
GitLab