From 8ea34de04b1a0f4dc4c92159cc4c9c95950e5bf2 Mon Sep 17 00:00:00 2001 From: Luc Maisonobe <luc@orekit.org> Date: Fri, 17 Oct 2014 18:46:16 +0200 Subject: [PATCH] Added a detection of wrong TileUpdater implementations. TileUpdater must not return a tile fow which the specified latitude/longitude are in the last row/column, as these row/columns are considered not covered by this tile but are used only to interpolate points in the preceding row/column. --- .../org/orekit/rugged/api/RuggedMessages.java | 1 + .../org/orekit/rugged/raster/TileUpdater.java | 12 +++++++ .../org/orekit/rugged/raster/TilesCache.java | 11 +++++- .../org/orekit/rugged/RuggedMessages_de.utf8 | 3 ++ .../org/orekit/rugged/RuggedMessages_en.utf8 | 3 ++ .../org/orekit/rugged/RuggedMessages_es.utf8 | 3 ++ .../org/orekit/rugged/RuggedMessages_fr.utf8 | 3 ++ .../org/orekit/rugged/RuggedMessages_gl.utf8 | 3 ++ .../org/orekit/rugged/RuggedMessages_it.utf8 | 3 ++ .../orekit/rugged/api/RuggedMessagesTest.java | 2 +- .../duvenhage/DuvenhageAlgorithmTest.java | 34 ++++++++++++++++++- .../orekit/rugged/raster/TilesCacheTest.java | 2 +- 12 files changed, 76 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/orekit/rugged/api/RuggedMessages.java b/core/src/main/java/org/orekit/rugged/api/RuggedMessages.java index 0f63da90..374fef7c 100644 --- a/core/src/main/java/org/orekit/rugged/api/RuggedMessages.java +++ b/core/src/main/java/org/orekit/rugged/api/RuggedMessages.java @@ -53,6 +53,7 @@ public enum RuggedMessages implements Localizable { INTERNAL_ERROR("internal error, contact maintenance at {0}"), OUT_OF_TILE_INDICES("no data at indices [{0}, {1}], tile only covers from [0, 0] to [{2}, {3}] (inclusive)"), OUT_OF_TILE_ANGLES("no data at latitude {0} and longitude {1}, tile covers only latitudes {2} to {3} and longitudes {4} to {5}"), + WRONG_TILE("the tile retrieved for latitude {0} and longitude {1} does not cover the point neighborhood (probably wrong overlap handling in TileUpdater)"), OUT_OF_TIME_RANGE("date {0} is out of time span [{1}, {2}]"), UNINITIALIZED_CONTEXT("general context has not been initialized"), EMPTY_TILE("tile is empty: {0} ⨉ {1}"), diff --git a/core/src/main/java/org/orekit/rugged/raster/TileUpdater.java b/core/src/main/java/org/orekit/rugged/raster/TileUpdater.java index c283f253..5b65b87d 100644 --- a/core/src/main/java/org/orekit/rugged/raster/TileUpdater.java +++ b/core/src/main/java/org/orekit/rugged/raster/TileUpdater.java @@ -29,6 +29,18 @@ import org.orekit.rugged.api.RuggedException; public interface TileUpdater { /** Set the tile global geometry. + * <p> + * As elevations are interpolated within Digital Elevation Model + * pixels using four pixels at indices (i, j), (i+1, j), (i, j+1) + * (i+1, j+1), the last row and last column of each tile is considered + * to be <em>not</em> covered by this tile (as checked using {@link + * Tile#getLocation(double, double)}) and should therefore be + * in the next tile (Eastwards or Northwards), which should have + * on row/column of <em>overlap</em>. This implies that this method + * must ensure that the latitude and longitude specified here do + * not lie in the last row/column of the returned tile, otherwise + * an error will be triggered by caller. + * <p> * @param latitude latitude that must be covered by the tile * @param longitude longitude that must be covered by the tile * @param tile to update diff --git a/core/src/main/java/org/orekit/rugged/raster/TilesCache.java b/core/src/main/java/org/orekit/rugged/raster/TilesCache.java index 66584fb8..64646dd0 100644 --- a/core/src/main/java/org/orekit/rugged/raster/TilesCache.java +++ b/core/src/main/java/org/orekit/rugged/raster/TilesCache.java @@ -23,7 +23,9 @@ import java.util.Comparator; import java.util.Iterator; import java.util.List; +import org.apache.commons.math3.util.FastMath; import org.orekit.rugged.api.RuggedException; +import org.orekit.rugged.api.RuggedMessages; import org.orekit.rugged.raster.Tile.Location; /** Cache for Digital Elevation Model {@link Tile tiles}. @@ -73,7 +75,14 @@ public class TilesCache<T extends Tile> { */ public T getTile(final double latitude, final double longitude) throws RuggedException { - return getStrip(latitude, longitude).getTile(latitude, longitude); + final T tile = getStrip(latitude, longitude).getTile(latitude, longitude); + if (tile.getLocation(latitude, longitude) != Tile.Location.IN_TILE) { + // this should happen only if user set up an inconsistent TileUpdater + throw new RuggedException(RuggedMessages.WRONG_TILE, + FastMath.toDegrees(latitude), + FastMath.toDegrees(longitude)); + } + return tile; } /** Create a tile covering a ground point. diff --git a/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_de.utf8 b/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_de.utf8 index 8476d28f..a93bf8fa 100644 --- a/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_de.utf8 +++ b/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_de.utf8 @@ -7,6 +7,9 @@ OUT_OF_TILE_INDICES = Keine Angaben im Index, die Ziegel nimmt nur Bezug auf [0, # no data at latitude {0} and longitude {1}, tile covers only latitudes {2} to {3} and longitudes {4} to {5} OUT_OF_TILE_ANGLES = keine Angaben zu Breite {0} und Länge {1}, die Ziegel nimmt nur Bezug auf die Breite {2} bis {3} und Länge {4} bis {5} +# the tile retrieved for latitude {0} and longitude {1} does not cover the point neighborhood (probably wrong overlap handling in TileUpdater) +WRONG_TILE = <MISSING TRANSLATION> + # date {0} is out of time span [{1}, {2}] OUT_OF_TIME_RANGE = Angabe {0} ist außerhalb der Zeitspanne [{1}, {2}] diff --git a/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_en.utf8 b/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_en.utf8 index 118da04a..8bb8983e 100644 --- a/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_en.utf8 +++ b/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_en.utf8 @@ -7,6 +7,9 @@ OUT_OF_TILE_INDICES = no data at indices [{0}, {1}], tile only covers from [0, 0 # no data at latitude {0} and longitude {1}, tile covers only latitudes {2} to {3} and longitudes {4} to {5} OUT_OF_TILE_ANGLES = no data at latitude {0} and longitude {1}, tile covers only latitudes {2} to {3} and longitudes {4} to {5} +# the tile retrieved for latitude {0} and longitude {1} does not cover the point neighborhood (probably wrong overlap handling in TileUpdater) +WRONG_TILE = the tile retrieved for latitude {0} and longitude {1} does not cover the point neighborhood (probably wrong overlap handling in TileUpdater) + # date {0} is out of time span [{1}, {2}] OUT_OF_TIME_RANGE = date {0} is out of time span [{1}, {2}] diff --git a/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_es.utf8 b/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_es.utf8 index c2c88535..88aad615 100644 --- a/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_es.utf8 +++ b/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_es.utf8 @@ -7,6 +7,9 @@ OUT_OF_TILE_INDICES = no hay datos en los Ãndices [{0}, {1}], la faceta sólo c # no data at latitude {0} and longitude {1}, tile covers only latitudes {2} to {3} and longitudes {4} to {5} OUT_OF_TILE_ANGLES = no hay datos para la latitud {0} y la longitud {1}, la faceta sólo cubre las latitudes de {2} a {3} y las longitudes de {4} a {5} +# the tile retrieved for latitude {0} and longitude {1} does not cover the point neighborhood (probably wrong overlap handling in TileUpdater) +WRONG_TILE = <MISSING TRANSLATION> + # date {0} is out of time span [{1}, {2}] OUT_OF_TIME_RANGE = la fecha {0} está fuera del intervalo temporal [{1}, {2}] diff --git a/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_fr.utf8 b/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_fr.utf8 index dbbd3973..56312d3d 100644 --- a/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_fr.utf8 +++ b/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_fr.utf8 @@ -7,6 +7,9 @@ OUT_OF_TILE_INDICES = aucune donnée aux indices [{0}, {1}], la tuile ne couvre # no data at latitude {0} and longitude {1}, tile covers only latitudes {2} to {3} and longitudes {4} to {5} OUT_OF_TILE_ANGLES = aucune donnée à la latitude {0} et à la longitude {1}, la tuile ne couvre que les latitudes de {2} à {3} et les longitudes de {4} à {5} +# the tile retrieved for latitude {0} and longitude {1} does not cover the point neighborhood (probably wrong overlap handling in TileUpdater) +WRONG_TILE = la tuile fournie pourla latitude {0} et à la longitude {1} ne couvre pas le voisinage de ce point (il s''agit probablement d''un problème de gestion des recouvrements dans le TileUpdater) + # date {0} is out of time span [{1}, {2}] OUT_OF_TIME_RANGE = la date {0} est hors de la plage temporelle [{1}, {2}] diff --git a/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_gl.utf8 b/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_gl.utf8 index b697164b..a3dbc6dd 100644 --- a/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_gl.utf8 +++ b/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_gl.utf8 @@ -7,6 +7,9 @@ OUT_OF_TILE_INDICES = non hai datos nos Ãndices [{0}, {1}], a faceta só cubre # no data at latitude {0} and longitude {1}, tile covers only latitudes {2} to {3} and longitudes {4} to {5} OUT_OF_TILE_ANGLES = non hai datos para a latitude {0} e a lonxitude {1}, a faceta só cubre as latitudes de {2} a {3} e as lonxitudes de {4} a {5} +# the tile retrieved for latitude {0} and longitude {1} does not cover the point neighborhood (probably wrong overlap handling in TileUpdater) +WRONG_TILE = <MISSING TRANSLATION> + # date {0} is out of time span [{1}, {2}] OUT_OF_TIME_RANGE = a data {0} está fora do intervalo temporal [{1}, {2}] diff --git a/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_it.utf8 b/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_it.utf8 index 5b453a65..f7e348a4 100644 --- a/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_it.utf8 +++ b/core/src/main/resources/assets/org/orekit/rugged/RuggedMessages_it.utf8 @@ -7,6 +7,9 @@ OUT_OF_TILE_INDICES = nessun dato agli indici [{0}, {1}], il quadrante non copre # no data at latitude {0} and longitude {1}, tile covers only latitudes {2} to {3} and longitudes {4} to {5} OUT_OF_TILE_ANGLES = nessun dato alla latitudine {0} e alla longitudine {1}, il quadrante non copre che le latitudini da {2} a {3} et les longitudes de {4} à {5} +# the tile retrieved for latitude {0} and longitude {1} does not cover the point neighborhood (probably wrong overlap handling in TileUpdater) +WRONG_TILE = <MISSING TRANSLATION> + # date {0} is out of time span [{1}, {2}] OUT_OF_TIME_RANGE = la data {0} è fuori dell''intervallo temporale [{1}, {2}] diff --git a/core/src/test/java/org/orekit/rugged/api/RuggedMessagesTest.java b/core/src/test/java/org/orekit/rugged/api/RuggedMessagesTest.java index 203d053e..8c555280 100644 --- a/core/src/test/java/org/orekit/rugged/api/RuggedMessagesTest.java +++ b/core/src/test/java/org/orekit/rugged/api/RuggedMessagesTest.java @@ -29,7 +29,7 @@ public class RuggedMessagesTest { @Test public void testMessageNumber() { - Assert.assertEquals(14, RuggedMessages.values().length); + Assert.assertEquals(15, RuggedMessages.values().length); } @Test diff --git a/core/src/test/java/org/orekit/rugged/intersection/duvenhage/DuvenhageAlgorithmTest.java b/core/src/test/java/org/orekit/rugged/intersection/duvenhage/DuvenhageAlgorithmTest.java index ce1e1f9c..37fbfc10 100644 --- a/core/src/test/java/org/orekit/rugged/intersection/duvenhage/DuvenhageAlgorithmTest.java +++ b/core/src/test/java/org/orekit/rugged/intersection/duvenhage/DuvenhageAlgorithmTest.java @@ -18,6 +18,7 @@ package org.orekit.rugged.intersection.duvenhage; import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; +import org.apache.commons.math3.util.FastMath; import org.junit.Assert; import org.junit.Test; import org.orekit.bodies.GeodeticPoint; @@ -26,8 +27,8 @@ import org.orekit.rugged.api.RuggedException; import org.orekit.rugged.api.RuggedMessages; import org.orekit.rugged.intersection.AbstractAlgorithmTest; import org.orekit.rugged.intersection.IntersectionAlgorithm; -import org.orekit.rugged.intersection.duvenhage.DuvenhageAlgorithm; import org.orekit.rugged.raster.TileUpdater; +import org.orekit.rugged.raster.UpdatableTile; public class DuvenhageAlgorithmTest extends AbstractAlgorithmTest { @@ -71,4 +72,35 @@ public class DuvenhageAlgorithmTest extends AbstractAlgorithmTest { } } + @Test + public void testInconsistentTileUpdater() throws RuggedException, OrekitException { + final int n = 1201; + final double size = FastMath.toRadians(1.0); + updater = new TileUpdater() { + public void updateTile(double latitude, double longitude, UpdatableTile tile) + throws RuggedException { + double step = size / (n - 1); + // this geometry is incorrect: + // the specified latitude/longitude belong to rows/columns [1, n-1] + // and not [0, n-2]. + tile.setGeometry(size * FastMath.floor(latitude / size) - 0.5 * step, + size * FastMath.floor(longitude / size) - 0.5 * step, + step, step, n, n); + for (int i = 0; i < n; ++i) { + for (int j = 0; j < n; ++j) { + tile.setElevation(i, j, ((i + j) % 2 == 0) ? -7.0 : 224); + } + } + } + }; + final IntersectionAlgorithm algorithm = createAlgorithm(updater, 8); + try { + algorithm.intersection(earth, + new Vector3D(-3010311.9672771087, 5307094.8081077365, 1852867.7919871407), + new Vector3D(0.3953329359154183, -0.8654901360032332, -0.30763402650162286)); + } catch (RuggedException re) { + Assert.assertEquals(RuggedMessages.WRONG_TILE, re.getSpecifier()); + } + } + } diff --git a/core/src/test/java/org/orekit/rugged/raster/TilesCacheTest.java b/core/src/test/java/org/orekit/rugged/raster/TilesCacheTest.java index cad96cd4..0f0ca1a6 100644 --- a/core/src/test/java/org/orekit/rugged/raster/TilesCacheTest.java +++ b/core/src/test/java/org/orekit/rugged/raster/TilesCacheTest.java @@ -104,7 +104,7 @@ public class TilesCacheTest { 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); + SimpleTile tileAtEnd = cache.getTile(0.234375, 0.609375); Assert.assertEquals(1, factory.getCount()); Assert.assertEquals(0.125, tileAtEnd.getMinimumLatitude(), 1.0e-10); Assert.assertEquals(0.5, tileAtEnd.getMinimumLongitude(), 1.0e-10); -- GitLab