From 62a4698c3a68854169991d48f45bd3cec522aa22 Mon Sep 17 00:00:00 2001 From: Luc Maisonobe <luc@orekit.org> Date: Wed, 11 Feb 2015 15:53:04 +0100 Subject: [PATCH] Fixed computation of min/max when some cells are Double.NaN. --- .../java/org/orekit/rugged/api/Rugged.java | 7 + .../duvenhage/MinMaxTreeTile.java | 177 +++++------------- .../org/orekit/rugged/raster/SimpleTile.java | 13 +- .../org/orekit/rugged/utils/MaxSelector.java | 74 ++++++++ .../org/orekit/rugged/utils/MinSelector.java | 74 ++++++++ .../org/orekit/rugged/utils/Selector.java | 43 +++++ .../orekit/rugged/errors/DumpManagerTest.java | 5 + .../rugged/errors/DumpReplayerTest.java | 7 +- .../orekit/rugged/raster/SimpleTileTest.java | 3 +- .../resources/replay/replay-direct-loc-01.txt | 38 ++-- 10 files changed, 284 insertions(+), 157 deletions(-) create mode 100644 src/main/java/org/orekit/rugged/utils/MaxSelector.java create mode 100644 src/main/java/org/orekit/rugged/utils/MinSelector.java create mode 100644 src/main/java/org/orekit/rugged/utils/Selector.java diff --git a/src/main/java/org/orekit/rugged/api/Rugged.java b/src/main/java/org/orekit/rugged/api/Rugged.java index 0e23ae86..0f17428c 100644 --- a/src/main/java/org/orekit/rugged/api/Rugged.java +++ b/src/main/java/org/orekit/rugged/api/Rugged.java @@ -174,6 +174,13 @@ public class Rugged { return scToBody.isInRange(date); } + /** Get the observed body ellipsoid. + * @return observed body ellipsoid + */ + public ExtendedEllipsoid getEllipsoid() { + return ellipsoid; + } + /** Direct location of a sensor line. * @param sensorName name of the line sensor * @param lineNumber number of the line to localize on ground diff --git a/src/main/java/org/orekit/rugged/intersection/duvenhage/MinMaxTreeTile.java b/src/main/java/org/orekit/rugged/intersection/duvenhage/MinMaxTreeTile.java index a8fd2e10..2c7bbfb6 100644 --- a/src/main/java/org/orekit/rugged/intersection/duvenhage/MinMaxTreeTile.java +++ b/src/main/java/org/orekit/rugged/intersection/duvenhage/MinMaxTreeTile.java @@ -16,10 +16,12 @@ */ package org.orekit.rugged.intersection.duvenhage; -import org.apache.commons.math3.analysis.BivariateFunction; import org.apache.commons.math3.util.FastMath; import org.orekit.rugged.errors.DumpManager; import org.orekit.rugged.raster.SimpleTile; +import org.orekit.rugged.utils.MaxSelector; +import org.orekit.rugged.utils.MinSelector; +import org.orekit.rugged.utils.Selector; /** Simple implementation of a {@link org.orekit.rugged.raster.Tile} * with a min/max kd tree. @@ -112,41 +114,11 @@ public class MinMaxTreeTile extends SimpleTile { final double[] preprocessed = new double[raw.length]; - // we don't use org.apache.commons.math3.analysis.function.Min - // because we want to ignore NaN values instead of spreading them - final BivariateFunction min = new BivariateFunction() { - /** {@inheritDoc} */ - @Override - public double value(final double x, final double y) { - if (Double.isNaN(x)) { - return y; - } else if (Double.isNaN(y)) { - return x; - } else { - return x <= y ? x : y; - } - } - }; - preprocess(preprocessed, raw, nbRows, nbCols, min); - applyRecursively(minTree, start.length - 1, nbRows, nbCols, min, preprocessed, 0); - - // we don't use org.apache.commons.math3.analysis.function.Max - // because we want to ignore NaN values instead of spreading them - final BivariateFunction max = new BivariateFunction() { - /** {@inheritDoc} */ - @Override - public double value(final double x, final double y) { - if (Double.isNaN(x)) { - return y; - } else if (Double.isNaN(y)) { - return x; - } else { - return x <= y ? y : x; - } - } - }; - preprocess(preprocessed, raw, nbRows, nbCols, max); - applyRecursively(maxTree, start.length - 1, nbRows, nbCols, max, preprocessed, 0); + preprocess(preprocessed, raw, nbRows, nbCols, MinSelector.getInstance()); + applyRecursively(minTree, start.length - 1, nbRows, nbCols, MinSelector.getInstance(), preprocessed, 0); + + preprocess(preprocessed, raw, nbRows, nbCols, MaxSelector.getInstance()); + applyRecursively(maxTree, start.length - 1, nbRows, nbCols, MaxSelector.getInstance(), preprocessed, 0); } @@ -284,77 +256,7 @@ public class MinMaxTreeTile extends SimpleTile { * @return row/column indices of the cell at which min elevation is reached */ public int[] locateMin(final int i, final int j, final int level) { - - final int k = start.length - level; - int rowShift = k / 2; - int colShift = (k + 1) / 2; - int levelI = i >> rowShift; - int levelJ = j >> colShift; - int levelR = 1 + ((getLatitudeRows() - 1) >> rowShift); - int levelC = 1 + ((getLongitudeColumns() - 1) >> colShift); - - // track the cell ancestors from merged tree at specified level up to tree at level 1 - for (int l = level + 1; l < start.length; ++l) { - - if (isColumnMerging(l)) { - - --colShift; - levelC = 1 + ((getLongitudeColumns() - 1) >> colShift); - levelJ = levelJ << 1; - - if (levelJ + 1 < levelC) { - // the cell results from a regular merging of two columns - if (minTree[start[l] + levelI * levelC + levelJ] > - minTree[start[l] + levelI * levelC + levelJ + 1]) { - levelJ++; - } - } - - } else { - - --rowShift; - levelR = 1 + ((getLatitudeRows() - 1) >> rowShift); - levelI = levelI << 1; - - if (levelI + 1 < levelR) { - // the cell results from a regular merging of two rows - if (minTree[start[l] + levelI * levelC + levelJ] > - minTree[start[l] + (levelI + 1) * levelC + levelJ]) { - levelI++; - } - } - - } - - } - - // we are now at first merge level, which always results from a column merge - // or pre-processed data, which themselves result from merging four cells - // used in interpolation - // this imply the ancestor of min/max at (n, m) is one of - // (2n, m), (2n+1, m), (2n+2, m), (2n, m+1), (2n+1, m+1), (2n+2, m+1) - int minI = levelI; - int minJ = 2 * levelJ; - double minElevation = Double.POSITIVE_INFINITY; - for (int n = 2 * levelJ; n < 2 * levelJ + 3; ++n) { - if (n < getLongitudeColumns()) { - for (int m = levelI; m < levelI + 2; ++m) { - if (m < getLatitudeRows()) { - final double elevation = raw[m * getLongitudeColumns() + n]; - if (elevation < minElevation) { - minI = m; - minJ = n; - minElevation = elevation; - } - } - } - } - } - - return new int[] { - minI, minJ - }; - + return locateMinMax(i, j, level, MinSelector.getInstance(), minTree); } /** Locate the cell at which max elevation is reached for a specified level. @@ -371,6 +273,19 @@ public class MinMaxTreeTile extends SimpleTile { * @return row/column indices of the cell at which min elevation is reached */ public int[] locateMax(final int i, final int j, final int level) { + return locateMinMax(i, j, level, MaxSelector.getInstance(), maxTree); + } + + /** Locate the cell at which min/max elevation is reached for a specified level. + * @param i row index of the cell + * @param j column index of the cell + * @param level tree level of the sub-tile considered + * @param selector min/max selector to use + * @param tree min/max tree to use + * @return row/column indices of the cell at which min/max elevation is reached + */ + private int[] locateMinMax(final int i, final int j, final int level, + final Selector selector, final double[] tree) { final int k = start.length - level; int rowShift = k / 2; @@ -391,8 +306,8 @@ public class MinMaxTreeTile extends SimpleTile { if (levelJ + 1 < levelC) { // the cell results from a regular merging of two columns - if (maxTree[start[l] + levelI * levelC + levelJ] < - maxTree[start[l] + levelI * levelC + levelJ + 1]) { + if (selector.selectFirst(tree[start[l] + levelI * levelC + levelJ + 1], + tree[start[l] + levelI * levelC + levelJ])) { levelJ++; } } @@ -405,8 +320,8 @@ public class MinMaxTreeTile extends SimpleTile { if (levelI + 1 < levelR) { // the cell results from a regular merging of two rows - if (maxTree[start[l] + levelI * levelC + levelJ] < - maxTree[start[l] + (levelI + 1) * levelC + levelJ]) { + if (selector.selectFirst(tree[start[l] + (levelI + 1) * levelC + levelJ], + tree[start[l] + levelI * levelC + levelJ])) { levelI++; } } @@ -420,18 +335,18 @@ public class MinMaxTreeTile extends SimpleTile { // used in interpolation // this imply the ancestor of min/max at (n, m) is one of // (2n, m), (2n+1, m), (2n+2, m), (2n, m+1), (2n+1, m+1), (2n+2, m+1) - int maxI = levelI; - int maxJ = 2 * levelJ; - double maxElevation = Double.NEGATIVE_INFINITY; + int selectedI = levelI; + int selectedJ = 2 * levelJ; + double selectedElevation = Double.NaN; for (int n = 2 * levelJ; n < 2 * levelJ + 3; ++n) { if (n < getLongitudeColumns()) { for (int m = levelI; m < levelI + 2; ++m) { if (m < getLatitudeRows()) { final double elevation = raw[m * getLongitudeColumns() + n]; - if (elevation > maxElevation) { - maxI = m; - maxJ = n; - maxElevation = elevation; + if (selector.selectFirst(elevation, selectedElevation)) { + selectedI = m; + selectedJ = n; + selectedElevation = elevation; } } } @@ -439,7 +354,7 @@ public class MinMaxTreeTile extends SimpleTile { } return new int[] { - maxI, maxJ + selectedI, selectedJ }; } @@ -638,11 +553,11 @@ public class MinMaxTreeTile extends SimpleTile { * @param elevations raw elevations te preprocess * @param nbRows number of rows * @param nbCols number of columns - * @param f function to apply + * @param selector selector to use */ private void preprocess(final double[] preprocessed, final double[] elevations, final int nbRows, final int nbCols, - final BivariateFunction f) { + final Selector selector) { int k = 0; @@ -650,20 +565,20 @@ public class MinMaxTreeTile extends SimpleTile { // regular elements with both a column at right and a row below for (int j = 0; j < nbCols - 1; ++j) { - preprocessed[k] = f.value(f.value(elevations[k], elevations[k + 1]), - f.value(elevations[k + nbCols], elevations[k + nbCols + 1])); + preprocessed[k] = selector.select(selector.select(elevations[k], elevations[k + 1]), + selector.select(elevations[k + nbCols], elevations[k + nbCols + 1])); k++; } // last column elements, lacking a right column - preprocessed[k] = f.value(elevations[k], elevations[k + nbCols]); + preprocessed[k] = selector.select(elevations[k], elevations[k + nbCols]); k++; } // last row elements, lacking a below row for (int j = 0; j < nbCols - 1; ++j) { - preprocessed[k] = f.value(elevations[k], elevations[k + 1]); + preprocessed[k] = selector.select(elevations[k], elevations[k + 1]); k++; } @@ -677,13 +592,13 @@ public class MinMaxTreeTile extends SimpleTile { * @param level current level * @param levelRows number of rows at current level * @param levelColumns number of columns at current level - * @param f function to apply + * @param selector to apply * @param base base array from which function arguments are drawn * @param first index of the first element to consider in base array */ private void applyRecursively(final double[] tree, final int level, final int levelRows, final int levelColumns, - final BivariateFunction f, + final Selector selector, final double[] base, final int first) { if (isColumnMerging(level + 1)) { @@ -698,7 +613,7 @@ public class MinMaxTreeTile extends SimpleTile { // regular pairs for (int j = 0; j < jEnd; ++j) { - tree[iTree++] = f.value(base[iBase], base[iBase + 1]); + tree[iTree++] = selector.select(base[iBase], base[iBase + 1]); iBase += 2; } @@ -711,7 +626,7 @@ public class MinMaxTreeTile extends SimpleTile { } if (level > 0) { - applyRecursively(tree, level - 1, levelRows, nextColumns, f, tree, start[level]); + applyRecursively(tree, level - 1, levelRows, nextColumns, selector, tree, start[level]); } } else { @@ -727,7 +642,7 @@ public class MinMaxTreeTile extends SimpleTile { for (int i = 0; i < iEnd; ++i) { for (int j = 0; j < levelColumns; ++j) { - tree[iTree++] = f.value(base[iBase], base[iBase + levelColumns]); + tree[iTree++] = selector.select(base[iBase], base[iBase + levelColumns]); iBase++; } iBase += levelColumns; @@ -740,7 +655,7 @@ public class MinMaxTreeTile extends SimpleTile { } if (level > 0) { - applyRecursively(tree, level - 1, nextRows, levelColumns, f, tree, start[level]); + applyRecursively(tree, level - 1, nextRows, levelColumns, selector, tree, start[level]); } } diff --git a/src/main/java/org/orekit/rugged/raster/SimpleTile.java b/src/main/java/org/orekit/rugged/raster/SimpleTile.java index 2fe4d842..5cc3c0a1 100644 --- a/src/main/java/org/orekit/rugged/raster/SimpleTile.java +++ b/src/main/java/org/orekit/rugged/raster/SimpleTile.java @@ -16,6 +16,8 @@ */ package org.orekit.rugged.raster; +import java.util.Arrays; + import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.apache.commons.math3.util.FastMath; import org.apache.commons.math3.util.Precision; @@ -23,6 +25,8 @@ import org.orekit.bodies.GeodeticPoint; import org.orekit.rugged.errors.DumpManager; import org.orekit.rugged.errors.RuggedException; import org.orekit.rugged.errors.RuggedMessages; +import org.orekit.rugged.utils.MaxSelector; +import org.orekit.rugged.utils.MinSelector; import org.orekit.rugged.utils.NormalizedGeodeticPoint; @@ -105,6 +109,7 @@ public class SimpleTile implements Tile { throw new RuggedException(RuggedMessages.EMPTY_TILE, newLatitudeRows, newLongitudeColumns); } this.elevations = new double[newLatitudeRows * newLongitudeColumns]; + Arrays.fill(elevations, Double.NaN); } @@ -224,20 +229,20 @@ public class SimpleTile implements Tile { /** {@inheritDoc} */ @Override - public void setElevation(final int latitudeIndex, final int longitudeIndex, - final double elevation) throws RuggedException { + public void setElevation(final int latitudeIndex, final int longitudeIndex, final double elevation) + throws RuggedException { if (latitudeIndex < 0 || latitudeIndex > (latitudeRows - 1) || longitudeIndex < 0 || longitudeIndex > (longitudeColumns - 1)) { throw new RuggedException(RuggedMessages.OUT_OF_TILE_INDICES, latitudeIndex, longitudeIndex, latitudeRows - 1, longitudeColumns - 1); } - if (elevation < minElevation) { + if (MinSelector.getInstance().selectFirst(elevation, minElevation)) { minElevation = elevation; minElevationLatitudeIndex = latitudeIndex; minElevationLongitudeIndex = longitudeIndex; } - if (elevation > maxElevation) { + if (MaxSelector.getInstance().selectFirst(elevation, maxElevation)) { maxElevation = elevation; maxElevationLatitudeIndex = latitudeIndex; maxElevationLongitudeIndex = longitudeIndex; diff --git a/src/main/java/org/orekit/rugged/utils/MaxSelector.java b/src/main/java/org/orekit/rugged/utils/MaxSelector.java new file mode 100644 index 00000000..44c706b2 --- /dev/null +++ b/src/main/java/org/orekit/rugged/utils/MaxSelector.java @@ -0,0 +1,74 @@ +/* Copyright 2013-2015 CS Systèmes d'Information + * Licensed to CS Systèmes d'Information (CS) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * CS licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.orekit.rugged.utils; + +/** Selector for max value. + * <p> + * This selector considers {@code Double.NaN} values correspond + * to non-initialized data that should be ignored rather than + * selected. + * </p> + * @see MinSelector + * @author Luc Maisonobe + */ +public class MaxSelector extends Selector { + + /** Private constructor for singleton. + */ + private MaxSelector() { + } + + /** Get the unique instance. + * @return unique instance of the min selector. + */ + public static MaxSelector getInstance() { + return LazyHolder.INSTANCE; + } + + /** Check if first value should be selected. + * @param v1 first value + * @param v2 second value + * @return true if v1 is higher than v2, or if v2 is {@code Double.NaN} + */ + @Override + public boolean selectFirst(final double v1, final double v2) { + return v1 > v2 || Double.isNaN(v2); + } + + /** Holder for the min selector singleton. + * <p> + * We use the Initialization On Demand Holder Idiom to store + * the singletons, as it is both thread-safe, efficient (no + * synchronization) and works with all versions of java. + * </p> + */ + private static class LazyHolder { + + /** Unique instance. */ + private static final MaxSelector INSTANCE = new MaxSelector(); + + /** Private constructor. + * <p>This class is a utility class, it should neither have a public + * nor a default constructor. This private constructor prevents + * the compiler from generating one automatically.</p> + */ + private LazyHolder() { + } + + } + +} diff --git a/src/main/java/org/orekit/rugged/utils/MinSelector.java b/src/main/java/org/orekit/rugged/utils/MinSelector.java new file mode 100644 index 00000000..7a32ee80 --- /dev/null +++ b/src/main/java/org/orekit/rugged/utils/MinSelector.java @@ -0,0 +1,74 @@ +/* Copyright 2013-2015 CS Systèmes d'Information + * Licensed to CS Systèmes d'Information (CS) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * CS licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.orekit.rugged.utils; + +/** Selector for min value. + * <p> + * This selector considers {@code Double.NaN} values correspond + * to non-initialized data that should be ignored rather than + * selected. + * </p> + * @see MaxSelector + * @author Luc Maisonobe + */ +public class MinSelector extends Selector { + + /** Private constructor for singleton. + */ + private MinSelector() { + } + + /** Get the unique instance. + * @return unique instance of the min selector. + */ + public static MinSelector getInstance() { + return LazyHolder.INSTANCE; + } + + /** Check if first value should be selected. + * @param v1 first value + * @param v2 second value + * @return true if v1 is lower than v2, or if v2 is {@code Double.NaN} + */ + @Override + public boolean selectFirst(final double v1, final double v2) { + return v1 < v2 || Double.isNaN(v2); + } + + /** Holder for the min selector singleton. + * <p> + * We use the Initialization On Demand Holder Idiom to store + * the singletons, as it is both thread-safe, efficient (no + * synchronization) and works with all versions of java. + * </p> + */ + private static class LazyHolder { + + /** Unique instance. */ + private static final MinSelector INSTANCE = new MinSelector(); + + /** Private constructor. + * <p>This class is a utility class, it should neither have a public + * nor a default constructor. This private constructor prevents + * the compiler from generating one automatically.</p> + */ + private LazyHolder() { + } + + } + +} diff --git a/src/main/java/org/orekit/rugged/utils/Selector.java b/src/main/java/org/orekit/rugged/utils/Selector.java new file mode 100644 index 00000000..060a8801 --- /dev/null +++ b/src/main/java/org/orekit/rugged/utils/Selector.java @@ -0,0 +1,43 @@ +/* Copyright 2013-2015 CS Systèmes d'Information + * Licensed to CS Systèmes d'Information (CS) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * CS licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.orekit.rugged.utils; + + +/** Class for selecting one value among two. + * @see MinSelector + * @see MaxSelector + * @author Luc Maisonobe + */ +public abstract class Selector { + + /** Check if first value should be selected. + * @param v1 first value + * @param v2 second value + * @return true if v1 should be selected + */ + public abstract boolean selectFirst(double v1, double v2); + + /** Select a value. + * @param v1 first value + * @param v2 second value + * @return selected value + */ + public double select(final double v1, final double v2) { + return selectFirst(v1, v2) ? v1 : v2; + } + +} diff --git a/src/test/java/org/orekit/rugged/errors/DumpManagerTest.java b/src/test/java/org/orekit/rugged/errors/DumpManagerTest.java index f073cbe3..77eda7bd 100644 --- a/src/test/java/org/orekit/rugged/errors/DumpManagerTest.java +++ b/src/test/java/org/orekit/rugged/errors/DumpManagerTest.java @@ -21,6 +21,7 @@ import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; +import java.io.PrintStream; import java.net.URISyntaxException; import org.apache.commons.math3.geometry.euclidean.threed.Rotation; @@ -77,6 +78,8 @@ public class DumpManagerTest { int countDirectLoc = 0; int countDirectLocResult = 0; BufferedReader br = new BufferedReader(new FileReader(dump)); + PrintStream out = new PrintStream("/home/luc/sources/eclipse/rugged/src/test/resources/replay/replay-direct-loc-02.txt", + "UTF-8"); for (String line = br.readLine(); line != null; line = br.readLine()) { String trimmed = line.trim(); if (trimmed.length() > 0 && !trimmed.startsWith("#")){ @@ -100,8 +103,10 @@ public class DumpManagerTest { Assert.fail(line); } } + out.println(line); } br.close(); + out.close(); Assert.assertEquals(1, countAlgorithm); Assert.assertEquals(1, countEllipsoid); Assert.assertEquals(1, countSpan); diff --git a/src/test/java/org/orekit/rugged/errors/DumpReplayerTest.java b/src/test/java/org/orekit/rugged/errors/DumpReplayerTest.java index 2ab2bf16..c628d180 100644 --- a/src/test/java/org/orekit/rugged/errors/DumpReplayerTest.java +++ b/src/test/java/org/orekit/rugged/errors/DumpReplayerTest.java @@ -21,6 +21,7 @@ import java.io.File; import java.io.IOException; import java.net.URISyntaxException; +import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; import org.junit.Assert; import org.junit.Test; import org.orekit.bodies.GeodeticPoint; @@ -47,9 +48,9 @@ public class DumpReplayerTest { for (final DumpReplayer.Result result : results) { GeodeticPoint expectedGP = (GeodeticPoint) result.getExpected(); GeodeticPoint replayedGP = (GeodeticPoint) result.getReplayed(); - Assert.assertEquals(expectedGP.getLatitude(), replayedGP.getLatitude(), 1.0e-12); - Assert.assertEquals(expectedGP.getLongitude(), replayedGP.getLongitude(), 1.0e-12); - Assert.assertEquals(expectedGP.getAltitude(), replayedGP.getAltitude(), 1.0e-6); + double distance = Vector3D.distance(rugged.getEllipsoid().transform(expectedGP), + rugged.getEllipsoid().transform(replayedGP)); + Assert.assertEquals(0.0, distance, 3.0e-9); } } diff --git a/src/test/java/org/orekit/rugged/raster/SimpleTileTest.java b/src/test/java/org/orekit/rugged/raster/SimpleTileTest.java index 0e2ba0a6..3e33de62 100644 --- a/src/test/java/org/orekit/rugged/raster/SimpleTileTest.java +++ b/src/test/java/org/orekit/rugged/raster/SimpleTileTest.java @@ -173,7 +173,8 @@ public class SimpleTileTest { tile.setElevation(21, 15, 95.0); tile.tileUpdateCompleted(); Assert.assertEquals(150.5, tile.interpolateElevation(20.0, 14.5), 1.0e-10); - Assert.assertEquals(128.5, tile.interpolateElevation(21.0, 14.5), 1.0e-10); + Assert.assertEquals(128.5, tile.interpolateElevation(FastMath.nextDown(21.0), 14.5), 1.0e-10); + Assert.assertTrue(Double.isNaN(tile.interpolateElevation(FastMath.nextUp(21.0), 14.5))); Assert.assertEquals(146.1, tile.interpolateElevation(20.2, 14.5), 1.0e-10); } diff --git a/src/test/resources/replay/replay-direct-loc-01.txt b/src/test/resources/replay/replay-direct-loc-01.txt index 610b0274..605137c0 100644 --- a/src/test/resources/replay/replay-direct-loc-01.txt +++ b/src/test/resources/replay/replay-direct-loc-01.txt @@ -1,8 +1,8 @@ -# Rugged library dump file, created on 2015-02-10T16:00:15Z +# Rugged library dump file, created on 2015-02-11T14:08:32Z # all units are SI units (m, m/s, rad ...) direct location: date 2012-01-01T12:30:00.00000000000000Z position 1.500000000000000e+00 0.000000000000000e+00 -2.000000000000000e-01 los 0.000000000000000e+00 -7.547095802227720e-01 6.560590289905073e-01 lightTime true aberration true span: minDate 2012-01-01T12:29:59.85000000000000Z maxDate 2012-01-01T12:30:00.15000000000000Z tStep 1.000000000000000e-03 tolerance 5.000000000000000e+00 inertialFrame EME2000 -transform: index 150 body r -8.085963389171905e-01 -3.465415132416125e-04 4.896468952533137e-04 -5.883634938068593e-01 Ω -8.740475534355122e-08 1.215132763920864e-09 -7.292109805268457e-05 ΩDot -1.642299174832679e-16 8.973031065665686e-17 1.983408395824453e-19 spacecraft p 1.384771423708159e+04 3.157872644483112e+03 -7.179504513218164e+06 v -3.193269831348565e+01 -8.025700179158079e+00 8.276060585645734e+00 a -9.306388141791047e-01 -8.320023410534990e+00 1.352798021525103e-03 r -6.828948932066574e-01 4.142451147005848e-01 -3.878489669799004e-01 4.600312256701621e-01 Ω -1.009835959093257e-03 1.982938126604663e-04 1.645927204535755e-04 ΩDot -3.647403055483546e-07 2.008714378022283e-07 -1.257148591486377e-06 +transform: index 150 body r -8.085963389171905e-01 -3.465415132416124e-04 4.896468952533136e-04 -5.883634938068593e-01 Ω -8.740475534355121e-08 1.215132763920863e-09 -7.292109805268457e-05 ΩDot -1.642299174832473e-16 8.973031065833714e-17 1.983408395826415e-19 spacecraft p 1.384771423708159e+04 3.157872644483112e+03 -7.179504513218164e+06 v -3.193269831348565e+01 -8.025700179158079e+00 8.276060585645734e+00 a -9.306388141791047e-01 -8.320023410534990e+00 1.352798021525103e-03 r -6.828948932066574e-01 4.142451147005848e-01 -3.878489669799004e-01 4.600312256701621e-01 Ω -1.009835959093257e-03 1.982938126604663e-04 1.645927204535755e-04 ΩDot -3.647403055483546e-07 2.008714378022283e-07 -1.257148591486377e-06 ellipsoid: ae 6.378137000000000e+06 f 3.352810664747481e-03 frame ITRF_CIO_CONV_2010_SIMPLE_EOP algorithm: DUVENHAGE DEM tile: t0 latMin -4.014257279586958e-01 latStep 6.817692390602850e-05 latRows 257 lonMin 2.495820830351891e+00 lonStep 6.817692390602850e-05 lonCols 257 @@ -40,16 +40,26 @@ DEM cell: t0 latIndex 98 lonIndex 49 elevation -2.653137720265925e+01 DEM cell: t0 latIndex 97 lonIndex 48 elevation -9.460844691182658e+01 DEM cell: t0 latIndex 98 lonIndex 48 elevation -6.303622859747302e+01 direct location result: latitude -3.947611273580563e-01 longitude 2.499133846389992e+00 elevation -4.295871413137783e+01 +direct location: date 2012-01-01T12:30:00.00000000000000Z position 1.500000000000000e+00 0.000000000000000e+00 -2.000000000000000e-01 los 0.000000000000000e+00 -7.595223858294946e-01 6.504811645419663e-01 lightTime true aberration true DEM cell: t0 latIndex 91 lonIndex 0 elevation -4.644285910379659e+02 DEM cell: t0 latIndex 92 lonIndex 0 elevation -6.361521230433466e+02 DEM cell: t0 latIndex 91 lonIndex 1 elevation -6.695324221432916e+02 DEM cell: t0 latIndex 92 lonIndex 1 elevation -6.941696826528058e+02 -DEM cell: t0 latIndex 91 lonIndex 2 elevation -7.590003401646543e+02 -DEM cell: t0 latIndex 90 lonIndex 3 elevation -8.207436833089408e+02 +DEM cell: t0 latIndex 96 lonIndex 12 elevation -6.229043689225860e+02 +DEM cell: t0 latIndex 97 lonIndex 12 elevation -6.074403513292080e+02 +DEM cell: t0 latIndex 96 lonIndex 13 elevation -6.849894309179065e+02 +DEM cell: t0 latIndex 97 lonIndex 13 elevation -6.129357249231432e+02 DEM cell: t0 latIndex 90 lonIndex 4 elevation -8.534523757445398e+02 -DEM cell: t0 latIndex 90 lonIndex 2 elevation -7.924361301694835e+02 +DEM cell: t0 latIndex 91 lonIndex 4 elevation -8.996784383751103e+02 +DEM cell: t0 latIndex 90 lonIndex 5 elevation -9.026655203899021e+02 +DEM cell: t0 latIndex 91 lonIndex 5 elevation -9.279387777828925e+02 +DEM cell: t0 latIndex 92 lonIndex 2 elevation -7.517293327072680e+02 +DEM cell: t0 latIndex 93 lonIndex 2 elevation -7.766413818620708e+02 +DEM cell: t0 latIndex 92 lonIndex 3 elevation -8.594398740278656e+02 +DEM cell: t0 latIndex 93 lonIndex 3 elevation -8.590835217917245e+02 DEM cell: t0 latIndex 90 lonIndex 1 elevation -7.251222469503653e+02 -direct location: date 2012-01-01T12:30:00.00000000000000Z position 1.500000000000000e+00 0.000000000000000e+00 -2.000000000000000e-01 los 0.000000000000000e+00 -7.595223858294946e-01 6.504811645419663e-01 lightTime true aberration true +DEM cell: t0 latIndex 90 lonIndex 2 elevation -7.924361301694835e+02 +DEM cell: t0 latIndex 91 lonIndex 2 elevation -7.590003401646543e+02 DEM cell: t0 latIndex 90 lonIndex 0 elevation -5.786400093316511e+02 direct location result: latitude -3.952555711362365e-01 longitude 2.495847653590435e+00 elevation -5.905034290161145e+02 direct location: date 2012-01-01T12:30:00.00000000000000Z position 1.500000000000000e+00 0.000000000000000e+00 -2.000000000000000e-01 los 0.000000000000000e+00 -7.596364750290255e-01 6.503479267326657e-01 lightTime true aberration true @@ -60,23 +70,15 @@ DEM cell: t1 latIndex 90 lonIndex 255 elevation -6.028136533065612e+02 DEM cell: t1 latIndex 90 lonIndex 256 elevation -5.786400093316511e+02 DEM cell: t1 latIndex 91 lonIndex 255 elevation -6.221990476940956e+02 DEM cell: t1 latIndex 91 lonIndex 256 elevation -4.644285910379659e+02 -DEM cell: t1 latIndex 88 lonIndex 252 elevation 0.000000000000000e+00 -DEM cell: t1 latIndex 89 lonIndex 252 elevation -4.877794667497003e+02 -DEM cell: t1 latIndex 88 lonIndex 253 elevation 0.000000000000000e+00 -DEM cell: t1 latIndex 89 lonIndex 253 elevation -5.757446064041551e+02 -DEM cell: t1 latIndex 91 lonIndex 252 elevation 0.000000000000000e+00 -DEM cell: t1 latIndex 92 lonIndex 252 elevation 0.000000000000000e+00 -DEM cell: t1 latIndex 91 lonIndex 253 elevation -6.152228016740617e+02 -DEM cell: t1 latIndex 92 lonIndex 253 elevation 0.000000000000000e+00 DEM cell: t1 latIndex 92 lonIndex 256 elevation -6.361521230433466e+02 DEM cell: t1 latIndex 91 lonIndex 257 elevation -6.361521230433466e+02 DEM cell: t1 latIndex 92 lonIndex 257 elevation -5.119072938899205e+02 direct location result: latitude -3.952672865845636e-01 longitude 2.495769458919830e+00 elevation -5.923807760050810e+02 direct location: date 2012-01-01T12:30:00.00000000000000Z position 1.500000000000000e+00 0.000000000000000e+00 -2.000000000000000e-01 los 0.000000000000000e+00 -7.597505408555608e-01 6.502146689130315e-01 lightTime true aberration true -DEM cell: t1 latIndex 88 lonIndex 248 elevation 0.000000000000000e+00 -DEM cell: t1 latIndex 89 lonIndex 248 elevation -2.769462712597335e+02 -DEM cell: t1 latIndex 88 lonIndex 249 elevation 0.000000000000000e+00 -DEM cell: t1 latIndex 89 lonIndex 249 elevation -3.314207112316006e+02 +DEM cell: t1 latIndex 92 lonIndex 248 elevation -1.470524675650724e+02 +DEM cell: t1 latIndex 93 lonIndex 248 elevation -1.448837787295385e+02 +DEM cell: t1 latIndex 92 lonIndex 249 elevation -2.503632800423777e+02 +DEM cell: t1 latIndex 93 lonIndex 249 elevation -2.077565123004881e+02 DEM cell: t1 latIndex 90 lonIndex 254 elevation -5.859504161342276e+02 DEM cell: t1 latIndex 91 lonIndex 254 elevation -6.458840770174961e+02 direct location result: latitude -3.952790935038382e-01 longitude 2.495690638626864e+00 elevation -5.963149908542051e+02 -- GitLab