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 c56754a04103e49922494583b51f3822b8586711..5c35b14d1a296c21f29accbd8c2b5eefc5f1cad6 100644
--- a/src/main/java/org/orekit/rugged/intersection/duvenhage/MinMaxTreeTile.java
+++ b/src/main/java/org/orekit/rugged/intersection/duvenhage/MinMaxTreeTile.java
@@ -90,7 +90,7 @@ public class MinMaxTreeTile extends SimpleTile {
      * Creates an empty tile.
      * </p>
      */
-    MinMaxTreeTile() {
+    protected MinMaxTreeTile() {
     }
 
     /** {@inheritDoc} */
diff --git a/src/main/java/org/orekit/rugged/raster/SimpleTile.java b/src/main/java/org/orekit/rugged/raster/SimpleTile.java
index 5db49b4e9a39f3976aeb54029f43eb4fef3421f0..ce1376928645894613e96db86b2a3bd19462b06a 100644
--- a/src/main/java/org/orekit/rugged/raster/SimpleTile.java
+++ b/src/main/java/org/orekit/rugged/raster/SimpleTile.java
@@ -268,7 +268,7 @@ public class SimpleTile implements Tile {
     public double interpolateElevation(final double latitude, final double longitude) {
 
         final double doubleLatitudeIndex  = getDoubleLatitudeIndex(latitude);
-        final double doubleLongitudeIndex = getDoubleLontitudeIndex(longitude);
+        final double doubleLongitudeIndex = getDoubleLongitudeIndex(longitude);
         if (doubleLatitudeIndex  < -TOLERANCE || doubleLatitudeIndex  >= (latitudeRows - 1 + TOLERANCE) ||
             doubleLongitudeIndex < -TOLERANCE || doubleLongitudeIndex >= (longitudeColumns - 1 + TOLERANCE)) {
             throw new RuggedException(RuggedMessages.OUT_OF_TILE_ANGLES,
@@ -422,7 +422,7 @@ public class SimpleTile implements Tile {
     /** {@inheritDoc} */
     @Override
     public int getFloorLongitudeIndex(final double longitude) {
-        return (int) FastMath.floor(getDoubleLontitudeIndex(longitude));
+        return (int) FastMath.floor(getDoubleLongitudeIndex(longitude));
     }
 
     /** Get the latitude index of a point.
@@ -437,7 +437,7 @@ public class SimpleTile implements Tile {
      * @param longitude geodetic longitude (rad)
      * @return longitude index (it may lie outside of the tile!)
      */
-    private double getDoubleLontitudeIndex(final double longitude) {
+    private double getDoubleLongitudeIndex(final double longitude) {
         return (longitude - minLongitude) / longitudeStep;
     }
 
diff --git a/src/main/java/org/orekit/rugged/raster/TilesCache.java b/src/main/java/org/orekit/rugged/raster/TilesCache.java
index 6e487987487563aaf6911174a6405686032756ab..d8df9db0276ca01db06e734712947fd36bb50b6f 100644
--- a/src/main/java/org/orekit/rugged/raster/TilesCache.java
+++ b/src/main/java/org/orekit/rugged/raster/TilesCache.java
@@ -18,6 +18,9 @@ package org.orekit.rugged.raster;
 
 import org.hipparchus.util.FastMath;
 import java.lang.reflect.Array;
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.Locale;
 
 import org.orekit.rugged.errors.RuggedException;
 import org.orekit.rugged.errors.RuggedMessages;
@@ -54,8 +57,8 @@ public class TilesCache<T extends Tile> {
     }
 
     /** Get the tile covering a ground point.
-     * @param latitude ground point latitude
-     * @param longitude ground point longitude
+     * @param latitude ground point latitude (rad)
+     * @param longitude ground point longitude (rad)
      * @return tile covering the ground point
      */
     public T getTile(final double latitude, final double longitude) {
@@ -89,6 +92,116 @@ public class TilesCache<T extends Tile> {
         updater.updateTile(latitude, longitude, tile);
         tile.tileUpdateCompleted();
 
+        
+        // Check if the tile HAS INTERPOLATION NEIGHBORS : the (latitude, longitude) is inside the tile
+        // otherwise the (latitude, longitude) is on the edge of the tile.
+        // One must create a zipper tile in case tiles are not overlapping ...
+        
+        tilePrint(tile, "Current tile:");
+
+final DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US);
+final DecimalFormat dfs = new DecimalFormat("#.###",symbols);
+System.out.format("longitude= " + dfs.format(FastMath.toDegrees(longitude)) + " location= " + tile.getLocation(latitude, longitude) + "\n");
+
+        final Tile.Location location = tile.getLocation(latitude, longitude);
+
+// System.out.format("Origin : lat min " + dfs.format(FastMath.toDegrees(tile.getMinimumLatitude())) +
+//        " lat max " + dfs.format(FastMath.toDegrees(tile.getMaximumLatitude())) +
+//        " lon min " + dfs.format(FastMath.toDegrees(tile.getMinimumLongitude())) +
+//        " lon max " + dfs.format(FastMath.toDegrees(tile.getMaximumLongitude())) +
+//        "\n");
+
+
+        // We are on the edge of the tile 
+        if (location != Tile.Location.HAS_INTERPOLATION_NEIGHBORS) {
+
+            // One must create a zipper tile between this tile and the neighbor tile
+            switch (location) {
+            
+            case NORTH: // latitudeIndex > latitudeRows - 2
+                final int latitudeRows = tile.getLatitudeRows();
+                final double latStep = tile.getLatitudeStep();
+
+                // Get the North Tile
+                final double latToGetNorthTile = latitudeRows*latStep + tile.getMinimumLatitude();
+                final T tileNorth = factory.createTile();
+                updater.updateTile(latToGetNorthTile, longitude, tileNorth);
+                tileNorth.tileUpdateCompleted();
+                
+                tilePrint(tileNorth, "North tile:");
+
+
+// System.out.println("North : lat min " + dfs.format(FastMath.toDegrees(tileNorth.getMinimumLatitude())) +
+//                           " lat max " + dfs.format(FastMath.toDegrees(tileNorth.getMaximumLatitude())) +
+//                           " lon min " + dfs.format(FastMath.toDegrees(tileNorth.getMinimumLongitude())) +
+//                           " lon max " + dfs.format(FastMath.toDegrees(tileNorth.getMaximumLongitude())) +
+//                           "\n");
+
+                // Create zipper tile between the current tile and the North tile;
+                // 2 rows belong to the North part of the origin tile
+                // 1 row belongs to the South part of the North tile
+                final Tile tileZipperNorth = new ZipperTile();
+
+                // TODO we suppose here the 2 tiles have same origin and size along longitude
+
+                double zipperLatitudeMin = (latitudeRows - 2)*latStep + tile.getMinimumLatitude();
+                double zipperLatitudeStep = tile.getLatitudeStep();
+                int zipperLatitudeRows = 4 + 5;
+                
+                int zipperLongitudeColumns = tile.getLongitudeColumns();
+                
+                double[][] elevations = new double[zipperLatitudeRows][zipperLongitudeColumns];
+                
+                for (int jLon = 0; jLon < zipperLongitudeColumns; jLon++) {
+                    // Part from the current tile
+                    int latitudeIndex = latitudeRows - 2;
+                    elevations[0][jLon] = tile.getElevationAtIndices(latitudeIndex, jLon);
+                    latitudeIndex = latitudeRows - 1;
+                    elevations[1][jLon] = tile.getElevationAtIndices(latitudeIndex, jLon);
+                    
+                    // Part from the North tile
+                    elevations[2][jLon] = tileNorth.getElevationAtIndices(0, jLon);
+                    elevations[3][jLon] = tileNorth.getElevationAtIndices(1, jLon);
+                    
+                    // + 5 latitude
+                    elevations[4][jLon] = tileNorth.getElevationAtIndices(2, jLon);
+                    elevations[5][jLon] = tileNorth.getElevationAtIndices(3, jLon);
+                    elevations[6][jLon] = tileNorth.getElevationAtIndices(4, jLon);
+                    elevations[7][jLon] = tileNorth.getElevationAtIndices(5, jLon);
+                    elevations[8][jLon] = tileNorth.getElevationAtIndices(6, jLon);
+
+                }
+                tileZipperNorth.setGeometry(zipperLatitudeMin, tile.getMinimumLongitude(), zipperLatitudeStep, tile.getLongitudeStep(), 
+                                            zipperLatitudeRows, zipperLongitudeColumns);
+                
+                // Fill in the tile with the relevant elevations
+                for (int iLat = 0; iLat < zipperLatitudeRows; iLat++) {
+                    for (int jLon = 0; jLon < zipperLongitudeColumns; jLon++) {
+                        tileZipperNorth.setElevation(iLat, jLon, elevations[iLat][jLon]);
+                    }
+                }
+                tileZipperNorth.tileUpdateCompleted();
+
+                tilePrint(tileZipperNorth, "Zipper tile:");
+                
+                // again make some room in the cache, possibly evicting the least recently used one
+                for (int i = tiles.length - 1; i > 0; --i) {
+                    tiles[i] = tiles[i - 1];
+                }
+                tiles[1] = tile;
+                tiles[0] = (T) tileZipperNorth;
+                return (T) tileZipperNorth;
+//break;               
+//                tiles[0] = tile;
+//                return tile;
+
+            default:
+                System.out.println("Location= " + location + " => Case not yet implemented");
+                break;
+            }
+
+        }
+   
         if (tile.getLocation(latitude, longitude) != Tile.Location.HAS_INTERPOLATION_NEIGHBORS) {
             // this should happen only if user set up an inconsistent TileUpdater
             throw new RuggedException(RuggedMessages.TILE_WITHOUT_REQUIRED_NEIGHBORS_SELECTED,
@@ -100,5 +213,24 @@ public class TilesCache<T extends Tile> {
         return tile;
 
     }
+    
+    protected void tilePrint(final Tile tile, String comment) {
+        
+        final DecimalFormatSymbols symbols = new DecimalFormatSymbols(Locale.US);
+        final DecimalFormat dfs = new DecimalFormat("#.###",symbols);
+        final DecimalFormat dfs2 = new DecimalFormat("#.#####",symbols);
+
+        System.out.format(comment + " rows " + tile.getLatitudeRows() + " col " + tile.getLongitudeColumns() + 
+                " lat step " + dfs2.format(FastMath.toDegrees(tile.getLatitudeStep())) + " long step " + dfs2.format(FastMath.toDegrees(tile.getLongitudeStep())) + 
+                "\n" +  
+                "       lat min " + dfs.format(FastMath.toDegrees(tile.getMinimumLatitude())) + " lat max " + dfs.format(FastMath.toDegrees(tile.getMaximumLatitude())) + 
+                "\n" +  
+                "       lon min " + dfs.format(FastMath.toDegrees(tile.getMinimumLongitude())) + " lon max " + dfs.format(FastMath.toDegrees(tile.getMaximumLongitude())) +
+                "\n" +  
+                "       min elevation " + tile.getMinElevation() + " lat index " + tile.getMinElevationLatitudeIndex() + " long index " + tile.getMinElevationLongitudeIndex() +
+                "\n " +
+                "       max elevation " + tile.getMaxElevation() +  " lat index " + tile.getMaxElevationLatitudeIndex() + " long index " + tile.getMaxElevationLongitudeIndex() +
+                "\n");
+    }
 
 }
diff --git a/src/main/java/org/orekit/rugged/raster/ZipperTile.java b/src/main/java/org/orekit/rugged/raster/ZipperTile.java
new file mode 100644
index 0000000000000000000000000000000000000000..15cecd91dd737bd8ef7a62a7ac51ec252356eaf1
--- /dev/null
+++ b/src/main/java/org/orekit/rugged/raster/ZipperTile.java
@@ -0,0 +1,59 @@
+/* Copyright 2013-2019 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.raster;
+
+import org.orekit.rugged.intersection.duvenhage.MinMaxTreeTile;
+
+public class ZipperTile extends MinMaxTreeTile {
+
+
+    public ZipperTile() {
+        
+    }
+
+    /** Create the geometry of the zipper tile from two tiles
+     */
+    public void createGeometry(final double zipperLatitudeMin, final double zipperLatitudeStep, final int zipperLatitudeRows,
+                               final double zipperLongitudeMin, final double zipperLongitudeStep, final int zipperLongitudeColumns,
+                               double[][] zipperElevations) {
+        // Set the tile geometry
+        setGeometry(zipperLatitudeMin, zipperLongitudeMin, zipperLatitudeStep, zipperLongitudeStep, zipperLatitudeRows, zipperLongitudeColumns);
+        
+        // Fill in the tile with the relevant elevations
+        for (int iLat = 0; iLat < zipperLatitudeRows; iLat++) {
+            for (int jLon = 0; jLon < zipperLongitudeColumns; jLon++) {
+                setElevation(iLat, jLon, zipperElevations[iLat][jLon]);
+            }
+        }
+    }
+    
+    /** {@inheritDoc} */
+    @Override
+    public void setGeometry(final double zipperLatitudeMin, final double zipperLongitudeMin,
+                            final double zipperLatitudeStep, final double zipperLongitudeStep,
+                            final int zipperLatitudeRows, final int zipperLongitudeColumns) {
+        // Set the tile geometry
+        super.setGeometry(zipperLatitudeMin, zipperLongitudeMin, zipperLatitudeStep, zipperLongitudeStep, zipperLatitudeRows, zipperLongitudeColumns);
+    }
+    
+    /** {@inheritDoc} */
+    @Override
+    public void setElevation(final int latitudeIndex, final int longitudeIndex, final double elevation) {
+        super.setElevation(latitudeIndex, longitudeIndex, elevation);
+    }
+
+}
diff --git a/src/test/java/org/orekit/rugged/raster/SimpleTileTest.java b/src/test/java/org/orekit/rugged/raster/SimpleTileTest.java
index ceea009d15237ab357a189734d03c1a57eeea58f..53588380c34436d0a1eb84a2446dd0c7d5bca789 100644
--- a/src/test/java/org/orekit/rugged/raster/SimpleTileTest.java
+++ b/src/test/java/org/orekit/rugged/raster/SimpleTileTest.java
@@ -101,6 +101,42 @@ public class SimpleTileTest {
         }
 
     }
+    
+    @Test
+    public void testZipper() {
+
+        SimpleTile tile0 = new SimpleTileFactory().createTile();
+        tile0.setGeometry(1.0, 2.0, 0.1, 0.2, 100, 200);
+        for (int i = 0; i < tile0.getLatitudeRows(); ++i) {
+            for (int j = 0; j < tile0.getLongitudeColumns(); ++j) {
+                tile0.setElevation(i, j, 1000 * i + j);
+            }
+        }
+        tile0.tileUpdateCompleted();
+
+        // Tile North of tile0
+        SimpleTile tileNorth = new SimpleTileFactory().createTile();
+        tileNorth.setGeometry(10.9, 2.0, 0.1, 0.2, 100, 200);
+        for (int i = 0; i < tileNorth.getLatitudeRows(); ++i) {
+            for (int j = 0; j < tileNorth.getLongitudeColumns(); ++j) {
+                tileNorth.setElevation(i, j, 1000 * i + j);
+            }
+        }
+        tileNorth.tileUpdateCompleted();
+
+      
+
+//        Assert.assertEquals(Location.SOUTH_WEST, tile0.getLocation( 0.0,  1.0));
+//        Assert.assertEquals(Location.WEST,       tile0.getLocation( 6.0,  1.0));
+//        Assert.assertEquals(Location.NORTH_WEST, tile0.getLocation(12.0,  1.0));
+//        Assert.assertEquals(Location.SOUTH,      tile0.getLocation( 0.0, 22.0));
+//        Assert.assertEquals(Location.HAS_INTERPOLATION_NEIGHBORS,    tile0.getLocation( 6.0, 22.0));
+//        Assert.assertEquals(Location.NORTH,      tile0.getLocation(12.0, 22.0));
+//        Assert.assertEquals(Location.SOUTH_EAST, tile0.getLocation( 0.0, 43.0));
+//        Assert.assertEquals(Location.EAST,       tile0.getLocation( 6.0, 43.0));
+//        Assert.assertEquals(Location.NORTH_EAST, tile0.getLocation(12.0, 43.0));
+
+    }
 
     @Test
     public void testOutOfBoundsIndices() {
diff --git a/src/test/java/org/orekit/rugged/raster/TilesCacheTest.java b/src/test/java/org/orekit/rugged/raster/TilesCacheTest.java
index 4f3d8ffb670e2882f1222c9e830df8a54b1f4129..62838ebb9f31f77e051af6917553b404d8cb2603 100644
--- a/src/test/java/org/orekit/rugged/raster/TilesCacheTest.java
+++ b/src/test/java/org/orekit/rugged/raster/TilesCacheTest.java
@@ -16,11 +16,26 @@
  */
 package org.orekit.rugged.raster;
 
+import java.io.File;
+import java.net.URISyntaxException;
+
+import org.hipparchus.geometry.euclidean.threed.Vector3D;
 import org.hipparchus.random.RandomGenerator;
 import org.hipparchus.random.Well19937a;
 import org.hipparchus.util.FastMath;
 import org.junit.Assert;
 import org.junit.Test;
+import org.orekit.bodies.GeodeticPoint;
+import org.orekit.data.DataProvidersManager;
+import org.orekit.data.DirectoryCrawler;
+import org.orekit.frames.FramesFactory;
+import org.orekit.rugged.errors.RuggedException;
+import org.orekit.rugged.errors.RuggedMessages;
+import org.orekit.rugged.intersection.IntersectionAlgorithm;
+import org.orekit.rugged.intersection.duvenhage.DuvenhageAlgorithm;
+import org.orekit.rugged.utils.ExtendedEllipsoid;
+import org.orekit.utils.Constants;
+import org.orekit.utils.IERSConventions;
 
 public class TilesCacheTest {
 
@@ -159,4 +174,46 @@ public class TilesCacheTest {
 
     }
 
+    @Test
+    public void testZipperTileCreation() throws URISyntaxException {
+
+        String path = getClass().getClassLoader().getResource("orekit-data").toURI().getPath();
+        DataProvidersManager.getInstance().addProvider(new DirectoryCrawler(new File(path)));
+        ExtendedEllipsoid earth = new ExtendedEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
+                                      Constants.WGS84_EARTH_FLATTENING,
+                                      FramesFactory.getITRF(IERSConventions.IERS_2010, true));
+
+        final int n = 1201;
+        final double size = FastMath.toRadians(1.0);
+        TileUpdater updater = new TileUpdater() {
+            public void updateTile(double latitude, double longitude, UpdatableTile tile) {
+                
+                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 - j*Math.random()) : (224 + i*Math.random()));
+                    }
+                }
+            }
+        };
+        final IntersectionAlgorithm algorithm = new DuvenhageAlgorithm(updater, 8, false);
+        try {
+//            GeodeticPoint gp = algorithm.intersection(earth,
+//                    new Vector3D(-3010311.9672771087, 5307094.8081077365, 1852867.7919871407),
+//                    new Vector3D(-0.3953329359154183, +0.8654901360032332, +0.30763402650162286));
+           GeodeticPoint gp =  algorithm.intersection(earth,
+                    new Vector3D(-3010311.9672771087, 5307094.8081077365, 1852867.7919871407),
+                    new Vector3D(0.3953329359154183, -0.8654901360032332, -0.30763402650162286));
+            System.out.println(gp.toString());
+
+        } catch (RuggedException re) {
+            Assert.assertEquals(RuggedMessages.TILE_WITHOUT_REQUIRED_NEIGHBORS_SELECTED, re.getSpecifier());
+        }
+    }
 }