From 64e05c3dbc5d73d528a3986dab7358d8a4a20190 Mon Sep 17 00:00:00 2001
From: gprat <guylaine.prat@csgroup.eu>
Date: Wed, 7 Dec 2022 10:43:18 +0100
Subject: [PATCH] "zipper tile" creation for non overlapping DEM whatever tiles
 resolution

Fixes #375
---
 .../org/orekit/rugged/api/RuggedBuilder.java  |   8 +-
 .../orekit/rugged/errors/DumpReplayer.java    |   3 +
 .../tutorials/direct-location-with-DEM.md     |  19 +-
 .../orekit/rugged/raster/TilesCacheTest.java  | 532 ------------------
 4 files changed, 24 insertions(+), 538 deletions(-)

diff --git a/src/main/java/org/orekit/rugged/api/RuggedBuilder.java b/src/main/java/org/orekit/rugged/api/RuggedBuilder.java
index a7814774..f5a32583 100644
--- a/src/main/java/org/orekit/rugged/api/RuggedBuilder.java
+++ b/src/main/java/org/orekit/rugged/api/RuggedBuilder.java
@@ -241,7 +241,8 @@ public class RuggedBuilder {
      *   {@link AlgorithmId#DUVENHAGE_FLAT_BODY DUVENHAGE_FLAT_BODY}
      *   and {@link AlgorithmId#BASIC_SLOW_EXHAUSTIVE_SCAN_FOR_TESTS_ONLY
      *   BASIC_SLOW_EXHAUSTIVE_SCAN_FOR_TESTS_ONLY} all
-     *   require {@link #setDigitalElevationModel(TileUpdater, int) setDigitalElevationModel}
+     *   require {@link #setDigitalElevationModel(TileUpdater, int, boolean) setDigitalElevationModel}
+     *   or {@link #setDigitalElevationModel(TileUpdater, int) setDigitalElevationModel}
      *   to be called,</li>
      *   <li>{@link AlgorithmId#CONSTANT_ELEVATION_OVER_ELLIPSOID
      *   CONSTANT_ELEVATION_OVER_ELLIPSOID} requires
@@ -253,6 +254,7 @@ public class RuggedBuilder {
      *
      * @param newAlgorithmId identifier of algorithm to use for Digital Elevation Model intersection
      * @return the builder instance
+     * @see #setDigitalElevationModel(TileUpdater, int, boolean)
      * @see #setDigitalElevationModel(TileUpdater, int)
      * @see #getAlgorithm()
      */
@@ -286,6 +288,7 @@ public class RuggedBuilder {
      * @param newTileUpdater updater used to load Digital Elevation Model tiles
      * @param newMaxCachedTiles maximum number of tiles stored in the cache
      * @return the builder instance
+     * @see #setDigitalElevationModel(TileUpdater, int, boolean)
      * @see #setAlgorithm(AlgorithmId)
      * @see #getTileUpdater()
      * @see #getMaxCachedTiles()
@@ -309,6 +312,7 @@ public class RuggedBuilder {
      * @param newIsOverlappingTiles flag to tell if the DEM tiles are overlapping:
      *                              true if overlapping; false otherwise.
      * @return the builder instance
+     * @see #setDigitalElevationModel(TileUpdater, int)
      * @see #setAlgorithm(AlgorithmId)
      * @see #getTileUpdater()
      * @see #getMaxCachedTiles()
@@ -325,6 +329,7 @@ public class RuggedBuilder {
 
     /** Get the updater used to load Digital Elevation Model tiles.
      * @return updater used to load Digital Elevation Model tiles
+     * @see #setDigitalElevationModel(TileUpdater, int, boolean)
      * @see #setDigitalElevationModel(TileUpdater, int)
      * @see #getMaxCachedTiles()
      */
@@ -379,6 +384,7 @@ public class RuggedBuilder {
 
     /** Get the maximum number of tiles stored in the cache.
      * @return maximum number of tiles stored in the cache
+     * @see #setDigitalElevationModel(TileUpdater, int, boolean)
      * @see #setDigitalElevationModel(TileUpdater, int)
      * @see #getTileUpdater()
      */
diff --git a/src/main/java/org/orekit/rugged/errors/DumpReplayer.java b/src/main/java/org/orekit/rugged/errors/DumpReplayer.java
index a4bbf7ae..07a97316 100644
--- a/src/main/java/org/orekit/rugged/errors/DumpReplayer.java
+++ b/src/main/java/org/orekit/rugged/errors/DumpReplayer.java
@@ -319,6 +319,9 @@ public class DumpReplayer {
             if (algorithmId == AlgorithmId.CONSTANT_ELEVATION_OVER_ELLIPSOID) {
                 builder.setConstantElevation(constantElevation);
             } else if (algorithmId != AlgorithmId.IGNORE_DEM_USE_ELLIPSOID) {
+                // In the case of user used a non overlapping DEM: no need here to take it into account
+                // as Rugged during the run created if necessary zipper tiles.
+                // At this stage, the read DEM in the dump behave like an overlapping DEM.
                 builder.setDigitalElevationModel(new TileUpdater() {
 
                     /** {@inheritDoc} */
diff --git a/src/site/markdown/tutorials/direct-location-with-DEM.md b/src/site/markdown/tutorials/direct-location-with-DEM.md
index 13449228..93b3b7a2 100644
--- a/src/site/markdown/tutorials/direct-location-with-DEM.md
+++ b/src/site/markdown/tutorials/direct-location-with-DEM.md
@@ -18,7 +18,7 @@
 
 The aim of this tutorial is to compute a direct location grid by intersection of 
 the line of sight with a DEM (Digital Elevation Model), using Duvenhage's algorithm. 
-This algorithm is the most performant one in Rugged. 
+This algorithm is the most efficient one in Rugged. 
 
 The following figure shows the effects of taking into account the DEM in the computation of latitude, longitude and altitude:
 
@@ -28,7 +28,7 @@ The following figure shows the effects of taking into account the DEM in the com
 
 Rugged does not parse DEM files but takes buffers of elevation data as input. 
 It is up to the calling application to read the DEM and load the data into buffers. 
-Rugged provides a tile mecanism with cache for large DEMs allowing the user to load 
+Rugged provides a tile mechanism with cache for large DEMs allowing the user to load 
 one tile at a time. This is in line with the format of world coverage DEMs such as SRTM. 
 Rugged offers an interface for updating the DEM tiles in cache with a callback function 
 triggered everytime a coordinate falls outside the current region. 
@@ -108,14 +108,18 @@ Here's the source code of the class `VolcanicConeElevationUpdater` :
 
 ### Important notes on DEM tiles :
 
-* Ground point elevation are obtained by bilinear interpolation between 4 neighbouring cells. There is no specific algorithm for border management. As a consequence, a point falling on the border of the tile is considered outside. **DEM tiles must be overlapping by at least one line/column in all directions**.
+* Ground point elevation are obtained by bilinear interpolation between 4 neighbouring cells. There is no specific algorithm for border management in this computation. As a consequence, a point falling on the border of the tile is considered outside. **DEM tiles must be overlapping by at least one line/column in all directions**. Two options are available:
+
+  - until version 3.0, the DEM tiles should comply to the overlapping obligation.
+  - after version 3.0, the DEM tiles could be seamless (i.e. not overlapping). In that case, a specific algorithm creates zipper tiles on the fly, in order to comply to the overlapping obligation. The case of overlapping DEM tiles is still possible. The choice is given through the API `setDigitalElevationModel` (see below paragraph `Initializing Rugged with a DEM`).
 
 * In Rugged terminology, the minimum latitude and longitude correspond to the centre of the farthest Southwest cell of the DEM. Be careful if using GDAL to pass the correct information as there is half a pixel shift with respect to the lower left corner coordinates in gdalinfo.
 
-The following diagram illustrates proper DEM tiling with one line/column overlaps between neighbouring tiles :
+The following diagram illustrates needed DEM tiling with one line/column overlaps between neighbouring tiles :
 
 ![DEM-tiles-overlap.png](../images/DEM-tiles-overlap.png)
 
+
 This diagram tries to represent the meaning of the different parameters in the definition of a tile :
 
 ![tile-description.png](../images/tile-description.png)
@@ -131,12 +135,13 @@ Instantiate an object derived from TileUpdater :
 
     int nbTiles = 8 ; //number max of tiles in Rugged cache
     AlgorithmId algoId = AlgorithmId.DUVENHAGE;
+    boolean isOverlappingTiles = true;
 
  
 Initialize Rugged with these parameters :
 
     Rugged rugged = new RuggedBuilder().
-                    setDigitalElevationModel(updater, nbTiles).
+                    setDigitalElevationModel(updater, nbTiles, isOverlappingTiles).
                     setAlgorithm(algoId). 
                     setEllipsoid(EllipsoidId.WGS84, BodyRotatingFrameId.ITRF).
                     setTimeSpan(startDate, stopDate, 0.1, 10.0). 
@@ -146,6 +151,10 @@ Initialize Rugged with these parameters :
                     addLineSensor(lineSensor).
                     build();
 
+To be noticed:
+
+one can use `setDigitalElevationModel(updater, nbTiles)` in the case of overlapping tiles (the flag isOverlappingTiles = true by default)
+
 ## Computing a direct location grid
 
 In a similar way as in the first tutorial [Direct Location](./direct-location.html), 
diff --git a/src/test/java/org/orekit/rugged/raster/TilesCacheTest.java b/src/test/java/org/orekit/rugged/raster/TilesCacheTest.java
index a018563b..9c399e62 100644
--- a/src/test/java/org/orekit/rugged/raster/TilesCacheTest.java
+++ b/src/test/java/org/orekit/rugged/raster/TilesCacheTest.java
@@ -1230,335 +1230,6 @@ public class TilesCacheTest {
             Assert.fail(iae.getMessage());
         }
     }
-
-//    // Test for development purpose only: use a real DEM (SRTM)
-//    // Needs:
-//    // * install GDAL
-//    // * add in pom.xml
-//    // For <properties>:
-//    //    <!-- GDAL version -->
-//    //    <!--urugged.gdal.version>2.4.0</urugged.gdal.version-->
-//    //    <rugged.gdal.version>3.0.0</rugged.gdal.version>
-//    //    <!-- GDAL native library path -->
-//    //    <rugged.gdal.native.library.path>${env.GDAL_PATH}</rugged.gdal.native.library.path>
-//    // and for <dependencies>:
-//    //    <dependency>
-//    //      <groupId>org.gdal</groupId>
-//    //      <artifactId>gdal</artifactId>
-//    //      <version>${rugged.gdal.version}</version>
-//    //      <type>jar</type>
-//    //      <optional>false</optional>
-//    //      <scope>test</scope>
-//    //    </dependency>
-//    // * Get the following SRTM tiles (for instance from : http://dwtkns.com/srtm/
-//    //    01/{15,16}; 22/{02,03,04}; 23/{02,03,04}; 24/{02,03,04,17,18,19}; 25/{17,18,19}; 26/{17,18,19}; 
-//    //    38/{02,03,04}; 39/{02,03,04}; 40/{02,03,04,15,16,17}; 41/{15,16,17}; 42/{15,16,17}; 72/{15,16}
-//
-//    @Test
-//    public void testRealSRTM() throws URISyntaxException, FileNotFoundException, UnsupportedEncodingException {
-//
-//        // Initialize GDAL
-//        org.gdal.gdal.gdal.AllRegister();
-//
-//        String demRootDir = "/home/guylaine/RuggedAndCo/rugged/dem-data/SRTM";
-//        SRTMElevationUpdater srtmUpdater = new SRTMElevationUpdater(demRootDir);
-//
-//        CountingFactory factory = new CountingFactory();
-//        TilesCache<SimpleTile> cache = new TilesCache<SimpleTile>(factory, srtmUpdater , 5, false);
-//
-//        boolean isDifferentStep = false;
-//
-//        double epsilonLatLon = 1.e-5;
-//        double latTileDeg;
-//        double lonTileDeg;
-//        double latDeg;
-//        double lonDeg;
-//
-//        // North-East hemisphere 
-//        // =====================
-//        System.out.println("#################################");
-//        System.out.println("NORTH EAST hemisphere");
-//        // tile SRTM: 45N - 50N / 10E-15E
-//        latTileDeg = 47.;
-//        lonTileDeg = 12.3;
-//
-//        System.out.println(">>>> Search lat deg = " + latTileDeg + " lon deg= " + lonTileDeg + "\n");
-//        SimpleTile tileNEhemisphere = cache.getTile(FastMath.toRadians(latTileDeg), FastMath.toRadians(lonTileDeg));
-//        // same step and size in longitude and latitude
-//        double tileSizeDeg = FastMath.toDegrees(tileNEhemisphere.getLatitudeRows()*tileNEhemisphere.getLatitudeStep());
-//        double rasterStepDeg = FastMath.toDegrees(tileNEhemisphere.getLatitudeStep());
-//
-//
-//        // Latitude North of the tile
-//        System.out.println("##### Bord de tuile au niveau latitude North #####");
-//        latDeg = getNorthernEdgeOfTile(tileNEhemisphere);
-//        lonDeg = lonTileDeg;
-//
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.NORTH, tileNEhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//
-//        // Latitude South of the tile
-//        System.out.println("#### Bord de tuile au niveau latitude South #####");
-//        latDeg = getSouthernEdgeOfTile(tileNEhemisphere);
-//        lonDeg = lonTileDeg;
-//
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.SOUTH, tileNEhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//        // Longitude West of the tile
-//        System.out.println("#### Bord de tuile au niveau longitude West #####");
-//        latDeg = latTileDeg;
-//        lonDeg = getWesternEdgeOfTile(tileNEhemisphere);
-//
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.WEST, tileNEhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//
-//        // Longitude East of the tile
-//        System.out.println("#### Bord de tuile au niveau longitude East #####");
-//        latDeg = latTileDeg;
-//        lonDeg = getEasternEdgeOfTile(tileNEhemisphere);
-//
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.EAST,tileNEhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//
-//        // Check the 4 corner zipper tiles
-//        check4cornersZipperTiles(tileNEhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//        // South-East hemisphere 
-//        // =====================
-//        // Cleanup
-//        clearFactoryMaps(CountingFactory.class);
-//        factory = new CountingFactory();
-//        cache = new TilesCache<SimpleTile>(factory, srtmUpdater , 5, false);
-//
-//        System.out.println("#################################");
-//        System.out.println("SOUTH EAST hemisphere");
-//
-//        latTileDeg = -16.2;
-//        lonTileDeg = 22.3;
-//        System.out.println(">>>> Search lat deg = " + latTileDeg + " lon deg= " + lonTileDeg + "\n");
-//        SimpleTile tileSEhemisphere = cache.getTile(FastMath.toRadians(latTileDeg), FastMath.toRadians(lonTileDeg));
-//        tileSizeDeg = FastMath.toDegrees(tileSEhemisphere.getLatitudeRows()*tileSEhemisphere.getLatitudeStep());
-//        rasterStepDeg = FastMath.toDegrees(tileSEhemisphere.getLatitudeStep());
-//
-//        printTileInfo(tileSEhemisphere, rasterStepDeg, rasterStepDeg);
-//
-//
-//        // Latitude North of the tile
-//        System.out.println("##### Bord de tuile au niveau latitude North #####");
-//        latDeg = getNorthernEdgeOfTile(tileSEhemisphere);
-//        lonDeg = lonTileDeg;
-//
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.NORTH, tileSEhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//
-//        // Latitude South of the tile
-//        System.out.println("#### Bord de tuile au niveau latitude South #####");
-//        latDeg = getSouthernEdgeOfTile(tileSEhemisphere);
-//        lonDeg = lonTileDeg;
-//
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.SOUTH, tileSEhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//
-//        // Longitude West of the tile
-//        System.out.println("#### Bord de tuile au niveau longitude West #####");
-//        latDeg = latTileDeg;
-//        lonDeg = getWesternEdgeOfTile(tileSEhemisphere);
-//
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.WEST, tileSEhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//
-//        // Longitude East of the tile
-//        System.out.println("#### Bord de tuile au niveau longitude East #####");
-//        latDeg = latTileDeg;
-//        lonDeg = getEasternEdgeOfTile(tileSEhemisphere);
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.EAST, tileSEhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//        // Check the 4 corner zipper tiles
-//        check4cornersZipperTiles(tileSEhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//        // North-West hemisphere 
-//        // =====================
-//        // Cleanup
-//        clearFactoryMaps(CountingFactory.class);
-//        factory = new CountingFactory();
-//        cache = new TilesCache<SimpleTile>(factory, srtmUpdater , 5, false);
-//
-//        System.out.println("#################################");
-//        System.out.println("NORTH WEST hemisphere");
-//        latTileDeg = 46.8;
-//        lonTileDeg = -66.5; 
-//
-//        System.out.println(">>>> Search lat deg = " + latTileDeg + " lon deg= " + lonTileDeg + "\n");
-//        SimpleTile tileNWhemisphere = cache.getTile(FastMath.toRadians(latTileDeg), FastMath.toRadians(lonTileDeg));
-//        tileSizeDeg = FastMath.toDegrees(tileNWhemisphere.getLatitudeRows()*tileNWhemisphere.getLatitudeStep());
-//        rasterStepDeg = FastMath.toDegrees(tileNWhemisphere.getLatitudeStep());
-//        printTileInfo(tileNWhemisphere, rasterStepDeg, rasterStepDeg);
-//
-//
-//        // Latitude North of the tile
-//        System.out.println("##### Bord de tuile au niveau latitude North #####");
-//        latDeg = getNorthernEdgeOfTile(tileNWhemisphere);
-//        lonDeg = lonTileDeg;
-//
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.NORTH, tileNWhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//
-//        // Latitude South of the tile
-//        System.out.println("#### Bord de tuile au niveau latitude South #####");
-//        latDeg = getSouthernEdgeOfTile(tileNWhemisphere);
-//        lonDeg = lonTileDeg;
-//
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.SOUTH, tileNWhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//
-//        // Longitude West of the tile
-//        System.out.println("#### Bord de tuile au niveau longitude West #####");
-//        latDeg = latTileDeg;
-//        lonDeg = getWesternEdgeOfTile(tileNWhemisphere);
-//
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.WEST, tileNWhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//
-//        // Longitude East of the tile
-//        System.out.println("#### Bord de tuile au niveau longitude East #####");
-//        latDeg = latTileDeg;
-//        lonDeg = getEasternEdgeOfTile(tileNWhemisphere);
-//
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.EAST, tileNWhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//        // Check the 4 corner zipper tiles
-//        check4cornersZipperTiles(tileNWhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//        // South-West hemisphere 
-//        // =====================
-//        // Cleanup
-//        clearFactoryMaps(CountingFactory.class);
-//        factory = new CountingFactory();
-//        cache = new TilesCache<SimpleTile>(factory, srtmUpdater , 5, false);
-//
-//        System.out.println("#################################");
-//        System.out.println("SOUTH WEST hemisphere");
-//
-//        latTileDeg = -28.8  ;
-//        lonTileDeg = -58.4; 
-//        System.out.println(">>>> Search lat deg = " + latTileDeg + " lon deg= " + lonTileDeg + "\n");
-//        SimpleTile tileSWhemisphere = cache.getTile(FastMath.toRadians(latTileDeg), FastMath.toRadians(lonTileDeg));
-//        tileSizeDeg = FastMath.toDegrees(tileSWhemisphere.getLatitudeRows()*tileSWhemisphere.getLatitudeStep());
-//        rasterStepDeg = FastMath.toDegrees(tileSWhemisphere.getLatitudeStep());
-//        printTileInfo(tileSWhemisphere, rasterStepDeg, rasterStepDeg);
-//
-//        // Latitude North of the tile
-//        System.out.println("##### Bord de tuile au niveau latitude North #####");
-//        latDeg = getNorthernEdgeOfTile(tileSWhemisphere);
-//        lonDeg = lonTileDeg;
-//
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.NORTH, tileSWhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//
-//        // Latitude South of the tile
-//        System.out.println("#### Bord de tuile au niveau latitude South #####");
-//        latDeg = getSouthernEdgeOfTile(tileSWhemisphere);
-//        lonDeg = lonTileDeg;
-//
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.SOUTH, tileSWhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//
-//        // Longitude West of the tile
-//        System.out.println("#### Bord de tuile au niveau longitude West #####");
-//        latDeg = latTileDeg;
-//        lonDeg = getWesternEdgeOfTile(tileSWhemisphere);
-//
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.WEST, tileSWhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//        // Longitude East of the tile
-//        System.out.println("#### Bord de tuile au niveau longitude East #####");
-//        latDeg = latTileDeg;
-//        lonDeg = getEasternEdgeOfTile(tileSWhemisphere);
-//
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.EAST, tileSWhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//        // Check the 4 corner zipper tiles
-//        check4cornersZipperTiles(tileSWhemisphere, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//        
-//        // Cleanup
-//        clearFactoryMaps(CountingFactory.class);
-//        factory = new CountingFactory();
-//        cache = new TilesCache<SimpleTile>(factory, srtmUpdater , 5, false);
-//
-//        // Anti meridians  (180 degrees W/E)
-//        // =====================
-//        // Cleanup
-//        clearFactoryMaps(CountingFactory.class);
-//        factory = new CountingFactory();
-//        cache = new TilesCache<SimpleTile>(factory, srtmUpdater , 5, false);
-//
-//
-//        System.out.println("#################################");
-//        System.out.println("Anti meridien test (180 degre East)");
-//        // tile SRTM 72/16: 175 - 180 East / 15 - 20 South  
-//        latTileDeg = -18.;
-//        lonTileDeg = 178.;
-//        System.out.println(">>>> Search lat deg = " + latTileDeg + " lon deg= " + lonTileDeg + "\n");
-//        SimpleTile tileAntiMeridianEast = cache.getTile(FastMath.toRadians(latTileDeg), FastMath.toRadians(lonTileDeg));
-//        // same step and size in longitude and latitude
-//        tileSizeDeg = FastMath.toDegrees(tileAntiMeridianEast.getLatitudeRows()*tileAntiMeridianEast.getLatitudeStep());
-//        rasterStepDeg = FastMath.toDegrees(tileAntiMeridianEast.getLatitudeStep());
-//
-//        // Longitude East of the tile
-//        System.out.println("#### Bord de tuile au niveau longitude East #####");
-//        latDeg = latTileDeg;
-//        lonDeg = getEasternEdgeOfTile(tileAntiMeridianEast);
-//
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.EAST,tileAntiMeridianEast, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//
-//        System.out.println("#################################");
-//        System.out.println("Anti meridien test (180 degre West)");
-//        // tile SRTM 01/16: 175 - 180 West / 15 - 20 South  
-//        latTileDeg = -18.;
-//        lonTileDeg = -178.;
-//        System.out.println(">>>> Search lat deg = " + latTileDeg + " lon deg= " + lonTileDeg + "\n");
-//        SimpleTile tileAntiMeridianWest = cache.getTile(FastMath.toRadians(latTileDeg), FastMath.toRadians(lonTileDeg));
-//        // same step and size in longitude and latitude
-//        tileSizeDeg = FastMath.toDegrees(tileAntiMeridianWest.getLatitudeRows()*tileAntiMeridianWest.getLatitudeStep());
-//        rasterStepDeg = FastMath.toDegrees(tileAntiMeridianWest.getLatitudeStep());
-//
-//        // Longitude West of the tile
-//        System.out.println("#### Bord de tuile au niveau longitude West #####");
-//        latDeg = latTileDeg;
-//        lonDeg = getWesternEdgeOfTile(tileAntiMeridianWest);
-//
-//        searchAndVerifyZipperTile(latDeg, lonDeg, Tile.Location.WEST,tileAntiMeridianWest, tileSizeDeg, cache, epsilonLatLon, isDifferentStep);
-//
-//        
-//        // Change of resolution between tiles
-//        // ==================================
-//        // Cleanup
-//        clearFactoryMaps(CountingFactory.class);
-//        factory = new CountingFactory();
-//        cache = new TilesCache<SimpleTile>(factory, srtmUpdater , 5, false);
-//
-//        isDifferentStep = true;
-//
-////        // North-East hemisphere 
-////        // =====================
-////        System.out.println("#################################");
-////        System.out.println("NORTH EAST hemisphere");
-////        // tile SRTM: 45N - 50N / 10E-15E
-////        latTileDeg = 47.;
-////        lonTileDeg = 12.3;
-////
-////        System.out.println(">>>> Search lat deg = " + latTileDeg + " lon deg= " + lonTileDeg + "\n");
-////        SimpleTile tileNEhemisphere = cache.getTile(FastMath.toRadians(latTileDeg), FastMath.toRadians(lonTileDeg));
-////        // same step and size in longitude and latitude
-////        double tileSizeDeg = FastMath.toDegrees(tileNEhemisphere.getLatitudeRows()*tileNEhemisphere.getLatitudeStep());
-////        double rasterStepDeg = FastMath.toDegrees(tileNEhemisphere.getLatitudeStep());
-//
-//
-//
-//    }
-    
-
 }
 
 class SurroundingTiles {
@@ -1614,207 +1285,4 @@ class SurroundingTiles {
 	}
 }
 
-////Test for development purpose only: use a real DEM (SRTM)
-//
-///**
-//* To read SRTM tiles (get from http://dwtkns.com/srtm/)
-//* The tiles are seamless = no overlapping 
-//*/
-//class SRTMElevationUpdater implements TileUpdater {
-//
-///** Last lat value used to ask to update a tile. */
-//private double lastLat = Double.NaN;
-//
-///** Last lon value used to ask to update a tile. */
-//private double lastLon = Double.NaN;
-//
-///** Nb times the same lat/lon value is used to ask to update a tile (used to avoid infinite loop). */
-//private int nbCall = 0;
-//
-///** Nb time rugged ask exactly same DEM tile: means that infinite loop. */
-//private static final int NB_TIME_ASK_SAME_TILE = 1000;
-//
-///** Raster root directory, should contains raster files. */
-//private String rootDirectory;
-//
-//
-///**
-//* Constructor.
-//*/
-//public SRTMElevationUpdater(final String rootDirectory) {
-//   
-//   this.rootDirectory = rootDirectory;
-//   checkRasterDirectory(rootDirectory);
-//}
-//
-///** Update given tile using DEM elevation.
-//* @param latitude latitude that must be covered by the tile (rad)
-//* @param longitude longitude that must be covered by the tile (rad)
-//* @param tile to update
-//*/
-//@Override
-//public void updateTile(final double latitude, final double longitude, final UpdatableTile tile) {
-//
-//   // Check if latitude and longitude already known
-//   if (latitude == this.lastLat && longitude == this.lastLon) {
-//       this.nbCall++;
-//   } else {
-//       this.lastLat = latitude;
-//       this.lastLon = longitude;
-//       this.nbCall = 0;
-//   }
-//   if (this.nbCall > NB_TIME_ASK_SAME_TILE) {
-//       String str = String.format("infinite loop for %3.8f long %3.8f lat ", longitude, latitude);
-//       org.hipparchus.exception.DummyLocalizable message = new org.hipparchus.exception.DummyLocalizable(str);
-//       throw new org.orekit.rugged.errors.RuggedException(message);
-//   }
-//
-//   String rasterFileName = getRasterFilePath(latitude, longitude);
-//   
-////   java.io.FileFile rasterFile = new java.io.File(rasterFileName);
-////   if (!rasterFile.exists()) {
-////       // No DEM => we are on water => read geoid
-////       GeoidHandler geoidHandler = GeoidHandler.getInstance();
-////       geoidHandler.updateTile(latitude, longitude, tile);
-////       System.out.format("WARNING: No DEM tile found for latitude (deg) = %3.8f  and longitude (deg) = %3.8f." +
-////                         " DEM file %s doesn't exist. Use of Geoid data instead.%n",
-////                         FastMath.toDegrees(latitude), FastMath.toDegrees(longitude), rasterFileName);
-////       return;
-////   }
-//
-//   org.gdal.gdal.Dataset ds = org.gdal.gdal.gdal.Open(rasterFileName, org.gdal.gdalconst.gdalconst.GA_ReadOnly);
-//   int rasterLonSize = ds.GetRasterXSize();
-//   int rasterLatSize = ds.GetRasterYSize();
-//   double[] geoTransformInfo = ds.GetGeoTransform();
-//
-//   double minLat = Double.NaN;
-//   double minLon = Double.NaN;
-//   double lonStep = Double.NaN;
-//   double latStep = Double.NaN;
-//
-//   if (geoTransformInfo.length < 6) { // Check that the geoTransformInfo is correct
-//       String str = "GDALGeoTransform has < 6 elements";
-//       org.hipparchus.exception.DummyLocalizable message = new org.hipparchus.exception.DummyLocalizable(str);
-//       throw new org.orekit.rugged.errors.RuggedException(message);
-//   } else {
-//       lonStep = FastMath.abs(geoTransformInfo[1]);
-//       latStep = FastMath.abs(geoTransformInfo[5]);
-//
-//       minLon = geoTransformInfo[0] + 0.5 * lonStep;
-//       minLat = geoTransformInfo[3] - (rasterLatSize - 0.5) * latStep;
-//   }
-//
-//   org.gdal.gdal.Band band = ds.GetRasterBand(1);
-//
-//   // Define Tile Geometry
-//   tile.setGeometry(FastMath.toRadians(minLat), FastMath.toRadians(minLon), FastMath.toRadians(latStep), FastMath.toRadians(lonStep), rasterLatSize, rasterLonSize);
-//
-//   // Loop over raster values
-//   double[] data = new double[rasterLatSize * rasterLonSize];
-//
-////   // SRTM is given above the geoid
-////    GeoidHandler geoidHandler = GeoidHandler.getInstance();
-////    GdalTransformTools gtTools = new GdalTransformTools(geoTransformInfo, rasterLonSize, rasterLatSize);
-//
-//   // We read all raster at once to limit the numbers of Band.ReadRaster calls
-//   band.ReadRaster(0, 0, rasterLonSize, rasterLatSize, data);
-//
-//   // Get the no data value from the raster
-//   Double[] noDataValue = new Double[1];
-//   band.GetNoDataValue(noDataValue);
-//
-//   // test if the no data value exists
-//   Boolean noDataValueExist = false;
-//   if (noDataValue[0] != null) noDataValueExist = true;
-//
-//   // from bottom left to upper right corner
-//   for (int iLat = rasterLatSize - 1; iLat >= 0; iLat--) {
-//       for (int jLon = 0; jLon < rasterLonSize; jLon++) {
-//
-//           double elevationOverEllipsoid = 0.0;
-//           elevationOverEllipsoid = data[iLat * rasterLonSize + jLon];
-//
-//           if (noDataValueExist && (elevationOverEllipsoid == noDataValue[0])) {
-//               elevationOverEllipsoid = 0.0;
-//           }
-//           
-////           // The elevation value we send to rugged must be computed against ellipsoid
-////           // => when DEM is SRTM , we must add geoid value
-////           double lon = gtTools.getXFromPixelLine(jLon, iLat);
-////           double lat = gtTools.getYFromPixelLine(jLon, iLat);
-////           elevationOverEllipsoid = elevationOverEllipsoid + geoidHandler.getElevationDegree(lat, lon);
-//
-//           // Set elevation over the ellipsoid
-//           tile.setElevation(rasterLatSize - 1 - iLat, jLon, elevationOverEllipsoid);
-//       }
-//   }
-//   band.delete();
-//   band = null;
-//   ds.delete();
-//   ds = null;
-//}
-//
-//private String getRasterFilePath(final double latitude, final double longitude) {
-//
-//   double latDeg = FastMath.toDegrees(latitude);
-//   // Assure that the longitude belongs to [-180, + 180]
-//   double lonDeg = FastMath.toDegrees(MathUtils.normalizeAngle(longitude, 0.0));
-//
-//   // Compute parent dir with longitude value
-//   int parentDirValue = (int) (1 + (lonDeg + 180.) / 5);
-//   String parentDir = String.format("%02d", parentDirValue);
-//
-//   // Compute sub dir with latitude value
-//   int subDirValue = (int) (1 + (60. - latDeg) / 5);
-//   String subDir = String.format("%02d", subDirValue);
-//
-//   String filePath = this.rootDirectory + java.io.File.separator + parentDir + java.io.File.separator + subDir + java.io.File.separator +
-//                     "srtm_" + parentDir + "_" + subDir + ".tif";
-//   return filePath;
-//}
-//
-//private boolean checkRasterDirectory(final String directory) {
-//   
-//   if (directory == null) {
-//
-//       String str = "Directory not defined";
-//       org.hipparchus.exception.DummyLocalizable message = new org.hipparchus.exception.DummyLocalizable(str);
-//       throw new org.orekit.rugged.errors.RuggedException(message);
-//
-//   } else {
-//       try {
-//           java.nio.file.Path dir = java.nio.file.FileSystems.getDefault().getPath(directory);
-//           java.nio.file.DirectoryStream<java.nio.file.Path> stream = java.nio.file.Files.newDirectoryStream(dir);
-//           boolean found = false;
-//           for (java.nio.file.Path path : stream) {
-//               if (!found) {
-//                   java.io.File currentFile = path.toFile();
-//                   if (currentFile.isDirectory()) {
-//                       found = checkRasterDirectory(currentFile.getAbsolutePath());
-//                   } else {
-//                       String filePath = currentFile.getAbsolutePath();
-//                       if (filePath.matches(".*.tif")) {
-//                           found = true;
-//                       }
-//                   }
-//                   if (found) {
-//                       stream.close();
-//                       return true;
-//                   }
-//               }
-//           }
-//           stream.close();
-//
-//           String str = "raster not found  in" + directory;
-//           org.hipparchus.exception.DummyLocalizable message = new org.hipparchus.exception.DummyLocalizable(str);
-//           throw new org.orekit.rugged.errors.RuggedException(message);
-//
-//       } catch (java.io.IOException e) {
-//           String str = "dir not found " + directory;
-//           org.hipparchus.exception.DummyLocalizable message = new org.hipparchus.exception.DummyLocalizable(str);
-//           throw new org.orekit.rugged.errors.RuggedException(message);
-//       }
-//   }
-//}
-//}
 
-- 
GitLab