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 7681e2c76693fd6ed9e8cf823ac50a879ffcbbc6..1c00d16713300b579fdcf48e1ab092f9b91a697d 100644
--- a/src/main/java/org/orekit/rugged/intersection/duvenhage/MinMaxTreeTile.java
+++ b/src/main/java/org/orekit/rugged/intersection/duvenhage/MinMaxTreeTile.java
@@ -75,6 +75,9 @@ import org.orekit.rugged.raster.SimpleTile;
  */
 public class MinMaxTreeTile extends SimpleTile {
 
+    /** Raw elevations. */
+    private double[] raw;
+
     /** Min kd-tree. */
     private double[] minTree;
 
@@ -96,6 +99,8 @@ public class MinMaxTreeTile extends SimpleTile {
     @Override
     protected void processUpdatedElevation(final double[] elevations) {
 
+        raw = elevations;
+
         final int nbRows = getLatitudeRows();
         final int nbCols = getLongitudeColumns();
 
@@ -107,12 +112,12 @@ public class MinMaxTreeTile extends SimpleTile {
         // compute min/max trees
         if (start.length > 0) {
 
-            final double[] preprocessed = new double[elevations.length];
+            final double[] preprocessed = new double[raw.length];
 
-            preprocess(preprocessed, elevations, nbRows, nbCols, new Min());
+            preprocess(preprocessed, raw, nbRows, nbCols, new Min());
             applyRecursively(minTree, start.length - 1, nbRows, nbCols, new Min(), preprocessed, 0);
 
-            preprocess(preprocessed, elevations, nbRows, nbCols, new Max());
+            preprocess(preprocessed, raw, nbRows, nbCols, new Max());
             applyRecursively(maxTree, start.length - 1, nbRows, nbCols, new Max(), preprocessed, 0);
 
         }
@@ -130,10 +135,32 @@ public class MinMaxTreeTile extends SimpleTile {
     }
 
     /** Get the minimum elevation at some level tree.
+     * <p>
+     * Note that the min elevation is <em>not</em> computed
+     * only at cell center, but considering that it is interpolated
+     * considering also Eastwards and Northwards neighbors, and extends
+     * up to the center of these neighbors. As an example, lets consider
+     * four neighboring cells in some Digital Elevation Model:
+     * <table border="0" cellpadding="5" bgcolor="#f5f5dc">
+     * <tr><th bgcolor="#c9d5c9">j+1</th><td>11</td><td>10</td></tr>
+     * <tr><th bgcolor="#c9d5c9">j</th><td>12</td><td>11</td></tr>
+     * <tr  bgcolor="#c9d5c9"><th>j/i</th><th>i</th><th>i+1</th></tr>
+     * </table>
+     * When we interpolate elevation at a point located slightly South-West
+     * to the center of the (i+1, j+1) cell, we use all four cells in the
+     * interpolation, and we will get a result very close to 10 if we start
+     * close to (i+1, j+1) cell center. As the min value for this interpolation
+     * is stored at (i, j) indices, this implies that {@code getMinElevation(i,
+     * j, l)} must return 10 if l is chosen such that the sub-tile at
+     * tree level l includes cell (i,j) but not cell (i+1, j+1). In other words,
+     * interpolation implies sub-tile boundaries are overshoot by one column to
+     * the East and one row to the North when computing min.
+     * </p>
      * @param i row index of the cell
      * @param j column index of the cell
      * @param level tree level
-     * @return minimum elevation
+     * @return minimum value that can be reached when interpolating elevation
+     * in the sub-tile
      * @see #getLevels()
      * @see #getMaxElevation(int, int, int)
      * @see #getMergeLevel(int, int, int, int)
@@ -149,10 +176,9 @@ public class MinMaxTreeTile extends SimpleTile {
         final int levelC   = 1 + ((getLongitudeColumns() - 1) >> colShift);
 
         if (DumpManager.isActive()) {
-            // the following call is performed only for its side-effect
-            // of dumping the ancestor elevation, during the final
-            // call to getElevationAtIndices
-            findAncestor(i, j, level, true);
+            final int[] ancestor = findAncestor(i, j, level, true);
+            DumpManager.dumpTileCell(this, ancestor[0], ancestor[1],
+                                     raw[ancestor[0] * getLongitudeColumns() + ancestor[1]]);
         }
 
         return minTree[start[level] + levelI * levelC + levelJ];
@@ -160,10 +186,32 @@ public class MinMaxTreeTile extends SimpleTile {
     }
 
     /** Get the maximum elevation at some level tree.
+     * <p>
+     * Note that the max elevation is <em>not</em> computed
+     * only at cell center, but considering that it is interpolated
+     * considering also Eastwards and Northwards neighbors, and extends
+     * up to the center of these neighbors. As an example, lets consider
+     * four neighboring cells in some Digital Elevation Model:
+     * <table border="0" cellpadding="5" bgcolor="#f5f5dc">
+     * <tr><th bgcolor="#c9d5c9">j+1</th><td>11</td><td>12</td></tr>
+     * <tr><th bgcolor="#c9d5c9">j</th><td>10</td><td>11</td></tr>
+     * <tr  bgcolor="#c9d5c9"><th>j/i</th><th>i</th><th>i+1</th></tr>
+     * </table>
+     * When we interpolate elevation at a point located slightly South-West
+     * to the center of the (i+1, j+1) cell, we use all four cells in the
+     * interpolation, and we will get a result very close to 12 if we start
+     * close to (i+1, j+1) cell center. As the max value for this interpolation
+     * is stored at (i, j) indices, this implies that {@code getMaxElevation(i,
+     * j, l)} must return 12 if l is chosen such that the sub-tile at
+     * tree level l includes cell (i,j) but not cell (i+1, j+1). In other words,
+     * interpolation implies sub-tile boundaries are overshoot by one column to
+     * the East and one row to the North when computing max.
+     * </p>
      * @param i row index of the cell
      * @param j column index of the cell
      * @param level tree level
-     * @return maximum elevation
+     * @return maximum value that can be reached when interpolating elevation
+     * in the sub-tile
      * @see #getLevels()
      * @see #getMinElevation(int, int, int)
      * @see #getMergeLevel(int, int, int, int)
@@ -179,10 +227,9 @@ public class MinMaxTreeTile extends SimpleTile {
         final int levelC   = 1 + ((getLongitudeColumns() - 1) >> colShift);
 
         if (DumpManager.isActive()) {
-            // the following call is performed only for its side-effect
-            // of dumping the ancestor elevation, during the final
-            // call to getElevationAtIndices
-            findAncestor(i, j, level, false);
+            final int[] ancestor = findAncestor(i, j, level, false);
+            DumpManager.dumpTileCell(this, ancestor[0], ancestor[1],
+                                     raw[ancestor[0] * getLongitudeColumns() + ancestor[1]]);
         }
 
         return maxTree[start[level] + levelI * levelC + levelJ];
@@ -223,12 +270,12 @@ public class MinMaxTreeTile extends SimpleTile {
                 if (levelJ + 1 < levelC) {
                     // the cell results from a regular merging of two columns
                     if (isMin) {
-                        if (minTree[start[l] + levelI * levelC + levelJ] <=
+                        if (minTree[start[l] + levelI * levelC + levelJ] >
                             minTree[start[l] + levelI * levelC + levelJ + 1]) {
                             levelJ++;
                         }
                     } else {
-                        if (maxTree[start[l] + levelI * levelC + levelJ] >=
+                        if (maxTree[start[l] + levelI * levelC + levelJ] <
                             maxTree[start[l] + levelI * levelC + levelJ + 1]) {
                             levelJ++;
                         }
@@ -244,12 +291,12 @@ public class MinMaxTreeTile extends SimpleTile {
                 if (levelI + 1 < levelR) {
                     // the cell results from a regular merging of two rows
                     if (isMin) {
-                        if (minTree[start[l] + levelI       * levelC + levelJ] <=
+                        if (minTree[start[l] + levelI       * levelC + levelJ] >
                             minTree[start[l] + (levelI + 1) * levelC + levelJ]) {
                             levelI++;
                         }
                     } else {
-                        if (maxTree[start[l] + levelI       * levelC + levelJ] >=
+                        if (maxTree[start[l] + levelI       * levelC + levelJ] <
                             maxTree[start[l] + (levelI + 1) * levelC + levelJ]) {
                             levelI++;
                         }
@@ -263,24 +310,54 @@ public class MinMaxTreeTile extends SimpleTile {
         // we are now at first merge level, which always results from a column merge of raw data
         levelJ = levelJ << 1;
         levelC = getLongitudeColumns();
+        final int[] interpolationBase;
         if (levelJ + 1 < levelC) {
             // the cell results from a regular merging of two columns
-            if (isMin) {
-                if (getElevationAtIndices(levelI, levelJ) <=
-                    getElevationAtIndices(levelI, levelJ + 1)) {
-                    levelJ++;
-                }
-            } else {
-                if (getElevationAtIndices(levelI, levelJ) >=
-                    getElevationAtIndices(levelI, levelJ + 1)) {
-                    levelJ++;
-                }
-            }
+            interpolationBase = selectExtreme(new int[] {
+                levelI, levelJ
+            }, new int[] {
+                levelI, levelJ + 1
+            }, isMin);
+        } else {
+            // the cell is on last column
+            interpolationBase = new int[] {
+                levelI, levelJ
+            };
+        }
+
+        // as min/max are computed taking interpolation into account,
+        // we need to check 3 neighbors too (or fewer if on last row/column)
+        final int[] south = selectExtreme(interpolationBase,
+                                          new int[] {
+                                              interpolationBase[0]    , interpolationBase[1] + 1
+                                          }, isMin);
+        final int[] north = selectExtreme(new int[] {
+            interpolationBase[0] + 1, interpolationBase[1] + 1
+        }, new int[] {
+            interpolationBase[0] + 1, interpolationBase[1] + 1
+        }, isMin);
+
+        return selectExtreme(south, north, isMin);
+
+    }
+
+    /** Select an extreme cell.
+     * @param x1 indices of first cell
+     * @param x2 indices of second cell (may be out of tile ...)
+     * @param isMin if true, the min ancestor cell is desired, otherwise the max ancestor
+     * cell is desired
+     * @return row/column indices of the min/max cell
+     */
+    private int[] selectExtreme(final int[] x1, final int[] x2, final boolean isMin) {
+
+        if (x2[0] >= getLatitudeRows() || x2[1] >= getLongitudeColumns()) {
+            // the second cell is out of tile
+            return x1;
         }
 
-        return new int[] {
-            levelI, levelJ
-        };
+        final double  e1 = raw[x1[0] * getLongitudeColumns() + x1[1]];
+        final double  e2 = raw[x2[0] * getLongitudeColumns() + x2[1]];
+        return (isMin ^ (e1 > e2)) ? x1 : x2;
 
     }
 
diff --git a/src/test/java/org/orekit/rugged/intersection/duvenhage/MinMaxTreeTileTest.java b/src/test/java/org/orekit/rugged/intersection/duvenhage/MinMaxTreeTileTest.java
index 84549d1b3dda444c74949a73ecbf8b96743df142..7964b7fd190cacc1aeb5fb18f61321cecbe099b7 100644
--- a/src/test/java/org/orekit/rugged/intersection/duvenhage/MinMaxTreeTileTest.java
+++ b/src/test/java/org/orekit/rugged/intersection/duvenhage/MinMaxTreeTileTest.java
@@ -135,14 +135,16 @@ public class MinMaxTreeTileTest {
     @Test
     public void testAncestor() throws RuggedException {
         RandomGenerator random = new Well1024a(0xca9883209c6e740cl);
-        for (int nbRows = 1; nbRows < 25; nbRows++) {
-            for (int nbColumns = 1; nbColumns < 25; nbColumns++) {
+        for (int nbRows = 3; nbRows < 4; nbRows++) {
+            for (int nbColumns = 3; nbColumns < 4; nbColumns++) {
 
                 MinMaxTreeTile tile = new MinMaxTreeTileFactory().createTile();
                 tile.setGeometry(1.0, 2.0, 0.1, 0.2, nbRows, nbColumns);
                 for (int i = 0; i < nbRows; ++i) {
                     for (int j = 0; j < nbColumns; ++j) {
-                        tile.setElevation(i, j, 1000.0 * random.nextDouble());
+                        final double e  = 1000.0 * random.nextDouble();
+                        tile.setElevation(i, j, e);
+                        System.out.println(i + " " + j + " " + e);
                     }
                 }
                 tile.tileUpdateCompleted();
@@ -151,6 +153,9 @@ public class MinMaxTreeTileTest {
                     for (int j = 0; j < tile.getLongitudeColumns(); ++j) {
                         for (int l = 0; l < tile.getLevels(); ++l) {
                             int[] minAncestor = tile.findAncestor(i, j, l, true);
+                            System.out.println(i + " " + j + " " + l + " -> min = " + minAncestor[0] + " " + minAncestor[1]);
+                            System.out.println(tile.getMinElevation(i, j, l) + " / " +
+                                               tile.getElevationAtIndices(minAncestor[0], minAncestor[1]));
                             Assert.assertEquals(tile.getMinElevation(i, j, l),
                                                 tile.getElevationAtIndices(minAncestor[0], minAncestor[1]),
                                                 1.0e-10);
@@ -165,6 +170,21 @@ public class MinMaxTreeTileTest {
         }
     }
 
+    @Test
+    public void testIssue189() throws RuggedException {
+        MinMaxTreeTile tile = new MinMaxTreeTileFactory().createTile();
+        tile.setGeometry(1.0, 2.0, 0.1, 0.2, 2, 2);
+        tile.setElevation(0, 0, 1.0);
+        tile.setElevation(0, 1, 2.0);
+        tile.setElevation(1, 0, 3.0);
+        tile.setElevation(1, 1, 4.0);
+        tile.tileUpdateCompleted();
+        Assert.assertEquals(1.0, tile.getMinElevation(0, 0, 0), 1.0e-10);
+        Assert.assertEquals(3.0, tile.getMinElevation(1, 0, 0), 1.0e-10);
+        Assert.assertEquals(4.0, tile.getMaxElevation(0, 0, 0), 1.0e-10);
+        Assert.assertEquals(4.0, tile.getMaxElevation(1, 0, 0), 1.0e-10);
+    }
+
     @Test
     public void testMergeLarge() throws RuggedException {
         MinMaxTreeTile tile = createTile(1201, 1201);