From ad2149830988e33bee424ef3eb4577e2abcff72b Mon Sep 17 00:00:00 2001
From: Luc Maisonobe <luc@orekit.org>
Date: Mon, 31 Mar 2014 16:34:04 +0200
Subject: [PATCH] Reorganized source tree.

---
 .gitignore                                    |   6 +-
 .../orekit/rugged/geotiff/AngulerUnits.java   |  80 +++++-
 .../orekit/rugged/geotiff/AsterMessages.java  | 152 +++++++++++
 .../rugged/geotiff/AsterTileUpdater.java      | 258 ++++++++++++++++++
 .../org/orekit/rugged/geotiff/GeoTiffDEM.java | 207 --------------
 .../org/orekit/rugged/AsterMessages_en.utf8   |  23 ++
 .../org/orekit/rugged/AsterMessages_fr.utf8   |  23 ++
 .../rugged/geotiff/AsterMessagesTest.java     | 104 +++++++
 .../rugged/geotiff/AsterTileUpdaterTest.java  | 117 ++++++++
 .../orekit/rugged/geotiff/GeoTiffDEMTest.java |  64 -----
 .../rugged/geotiff/ASTER-files-warning.txt    |  19 ++
 11 files changed, 771 insertions(+), 282 deletions(-)
 create mode 100644 geotiff/src/main/java/org/orekit/rugged/geotiff/AsterMessages.java
 create mode 100644 geotiff/src/main/java/org/orekit/rugged/geotiff/AsterTileUpdater.java
 delete mode 100644 geotiff/src/main/java/org/orekit/rugged/geotiff/GeoTiffDEM.java
 create mode 100644 geotiff/src/main/resources/assets/org/orekit/rugged/AsterMessages_en.utf8
 create mode 100644 geotiff/src/main/resources/assets/org/orekit/rugged/AsterMessages_fr.utf8
 create mode 100644 geotiff/src/test/java/org/orekit/rugged/geotiff/AsterMessagesTest.java
 create mode 100644 geotiff/src/test/java/org/orekit/rugged/geotiff/AsterTileUpdaterTest.java
 delete mode 100644 geotiff/src/test/java/org/orekit/rugged/geotiff/GeoTiffDEMTest.java
 create mode 100644 geotiff/src/test/resources/org/orekit/rugged/geotiff/ASTER-files-warning.txt

diff --git a/.gitignore b/.gitignore
index 4ec3c9ac..7dcecb87 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,6 @@ bin
 .project
 .settings
 target
-rugged-api/target
-rugged-core/target
-rugged-geotiff/target
+geotiff/target
+geotiff/src/test/resources/org/orekit/rugged/geotiff/ASTGTM2_*.zip
+
diff --git a/geotiff/src/main/java/org/orekit/rugged/geotiff/AngulerUnits.java b/geotiff/src/main/java/org/orekit/rugged/geotiff/AngulerUnits.java
index a642125a..cca133b0 100644
--- a/geotiff/src/main/java/org/orekit/rugged/geotiff/AngulerUnits.java
+++ b/geotiff/src/main/java/org/orekit/rugged/geotiff/AngulerUnits.java
@@ -16,6 +16,8 @@
  */
 package org.orekit.rugged.geotiff;
 
+import org.apache.commons.math3.util.FastMath;
+
 /** Enumerate for angular units.
  * @see <a href="http://www.remotesensing.org/geotiff/spec/geotiff6.html#6.3.1.4">GeoTIFF specification, section 6.3.1.4</a>
  * @author Luc Maisonobe
@@ -23,14 +25,70 @@ package org.orekit.rugged.geotiff;
 enum AngulerUnits {
 
     // CHECKSTYLE: stop JavadocVariable check
-    RADIAN(9101),
-    DEGREE(9102),
-    ARC_MINUTE(9103),
-    ARC_SECOND(9104),
-    GRAD(9105),
-    GON(9106),
-    DMS(9107),
-    DMS_HEMISPHERE(9108);
+    RADIAN(9101) {
+        /** {@inheritDoc} */
+        @Override
+        public double toRadians(final double raw) {
+            return raw;
+        }
+    },
+
+    DEGREE(9102) {
+        /** {@inheritDoc} */
+        @Override
+        public double toRadians(final double raw) {
+            return FastMath.toRadians(raw);
+        }
+    },
+
+    ARC_MINUTE(9103) {
+        /** {@inheritDoc} */
+        @Override
+        public double toRadians(final double raw) {
+            return FastMath.toRadians(raw / 60.0);
+        }
+    },
+
+    ARC_SECOND(9104) {
+        /** {@inheritDoc} */
+        @Override
+        public double toRadians(final double raw) {
+            return FastMath.toRadians(raw / 3600.0);
+        }
+    },
+
+    GRAD(9105) {
+        /** {@inheritDoc} */
+        @Override
+        public double toRadians(final double raw) {
+            return FastMath.PI * raw / 200.0;
+        }
+    },
+
+    GON(9106) {
+        /** {@inheritDoc} */
+        @Override
+        public double toRadians(final double raw) {
+            return GRAD.toRadians(raw);
+        }
+    },
+
+    DMS(9107) {
+        /** {@inheritDoc} */
+        @Override
+        public double toRadians(final double raw) {
+            throw new UnsupportedOperationException();
+        }
+    },
+
+    DMS_HEMISPHERE(9108) {
+        /** {@inheritDoc} */
+        @Override
+        public double toRadians(final double raw) {
+            throw new UnsupportedOperationException();
+        }
+    };
+
     // CHECKSTYLE: resume JavadocVariable check
 
     /** Units ID. */
@@ -43,6 +101,12 @@ enum AngulerUnits {
         this.id = id;
     }
 
+    /** Convert an angle to radians.
+     * @param raw angle, in instance units
+     * @return angle in radians
+     */
+    public abstract double toRadians(final double raw);
+
     /** Get the units corresponding to an id.
      * @param id type id
      * @return the units corresponding to the id
diff --git a/geotiff/src/main/java/org/orekit/rugged/geotiff/AsterMessages.java b/geotiff/src/main/java/org/orekit/rugged/geotiff/AsterMessages.java
new file mode 100644
index 00000000..f7f547ad
--- /dev/null
+++ b/geotiff/src/main/java/org/orekit/rugged/geotiff/AsterMessages.java
@@ -0,0 +1,152 @@
+/* Copyright 2002-2014 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.geotiff;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.PropertyResourceBundle;
+import java.util.ResourceBundle;
+
+import org.apache.commons.math3.exception.util.Localizable;
+
+/**
+ * Enumeration for localized messages formats.
+ * <p>
+ * The constants in this enumeration represent the available
+ * formats as localized strings. These formats are intended to be
+ * localized using simple properties files, using the constant
+ * name as the key and the property value as the message format.
+ * The source English format is provided in the constants themselves
+ * to serve both as a reminder for developers to understand the parameters
+ * needed by each format, as a basis for translators to create
+ * localized properties files, and as a default format if some
+ * translation is missing.
+ * </p>
+ * <p>
+ * This class is heavily based on Orekit {@link org.orekit.errors.OrekitMessages},
+ * which is distributed under the terms of the Apache License V2.
+ * </p>
+ */
+public enum AsterMessages implements Localizable {
+
+    // CHECKSTYLE: stop JavadocVariable check
+
+    NO_DEM_DATA_FOR_POINT("no Digital Elevation Model data for point {0}, {1}"),
+    ERROR_PARSING_FILE("error parsing file {0}: {1}"),
+    MISSING_PIXEL_SCALE("missing pixel scale GeoTIFF tag in file {0}"),
+    MISSING_TIE_POINT("missing tie point GeoTIFF tag in file {0}"),
+    UNSUPPORTED_GEOTIFF_VERSION("unsupported GeoTIFF version {0}/{1}.{2} in file {3} (expected {4}/{5}.{6})"),
+    UNABLE_TO_RETRIEVE_VALUE_FOR_KEY("unable to retrieve value for key {0} in file {1}"),
+    UNEXPECTED_GEOKEY("unexpected GeoTIFF key {0} in file {1}"),
+    UNEXPECTED_GEOKEY_VALUE("GeoTIFF key {0} in file {1} has unexpected value {2} (expected {3})");
+
+    // CHECKSTYLE: resume JavadocVariable check
+
+    /** Base name of the resource bundle in classpath. */
+    private static final String RESOURCE_BASE_NAME = "assets/org/orekit/rugged/AsterMessages";
+
+    /** Source English format. */
+    private final String sourceFormat;
+
+    /** Simple constructor.
+     * @param sourceFormat source English format to use when no
+     * localized version is available
+     */
+    private AsterMessages(final String sourceFormat) {
+        this.sourceFormat = sourceFormat;
+    }
+
+    /** {@inheritDoc} */
+    public String getSourceString() {
+        return sourceFormat;
+    }
+
+    /** {@inheritDoc} */
+    public String getLocalizedString(final Locale locale) {
+        try {
+            final ResourceBundle bundle =
+                    ResourceBundle.getBundle(RESOURCE_BASE_NAME, locale, new UTF8Control());
+            if (bundle.getLocale().getLanguage().equals(locale.getLanguage())) {
+                final String translated = bundle.getString(name());
+                if ((translated != null) &&
+                    (translated.length() > 0) &&
+                    (!translated.toLowerCase().contains("missing translation"))) {
+                    // the value of the resource is the translated format
+                    return translated;
+                }
+            }
+
+        } catch (MissingResourceException mre) {
+            // do nothing here
+        }
+
+        // either the locale is not supported or the resource is not translated or
+        // it is unknown: don't translate and fall back to using the source format
+        return sourceFormat;
+
+    }
+
+    /** Control class loading properties in UTF-8 encoding.
+     * <p>
+     * This class has been very slightly adapted from BalusC answer to question: <a
+     * href="http://stackoverflow.com/questions/4659929/how-to-use-utf-8-in-resource-properties-with-resourcebundle">
+     * How to use UTF-8 in resource properties with ResourceBundle</a>.
+     * </p>
+     */
+    public static class UTF8Control extends ResourceBundle.Control {
+
+        /** {@inheritDoc} */
+        @Override
+        public ResourceBundle newBundle(final String baseName, final Locale locale, final String format,
+                                        final ClassLoader loader, final boolean reload)
+            throws IllegalAccessException, InstantiationException, IOException {
+            // The below is a copy of the default implementation.
+            final String bundleName = toBundleName(baseName, locale);
+            final String resourceName = toResourceName(bundleName, "utf8");
+            ResourceBundle bundle = null;
+            InputStream stream = null;
+            if (reload) {
+                final URL url = loader.getResource(resourceName);
+                if (url != null) {
+                    final URLConnection connection = url.openConnection();
+                    if (connection != null) {
+                        connection.setUseCaches(false);
+                        stream = connection.getInputStream();
+                    }
+                }
+            } else {
+                stream = loader.getResourceAsStream(resourceName);
+            }
+            if (stream != null) {
+                try {
+                    // Only this line is changed to make it to read properties files as UTF-8.
+                    bundle = new PropertyResourceBundle(new InputStreamReader(stream, "UTF-8"));
+                } finally {
+                    stream.close();
+                }
+            }
+            return bundle;
+        }
+
+    }
+
+}
diff --git a/geotiff/src/main/java/org/orekit/rugged/geotiff/AsterTileUpdater.java b/geotiff/src/main/java/org/orekit/rugged/geotiff/AsterTileUpdater.java
new file mode 100644
index 00000000..9be8ec6e
--- /dev/null
+++ b/geotiff/src/main/java/org/orekit/rugged/geotiff/AsterTileUpdater.java
@@ -0,0 +1,258 @@
+/* Copyright 2013-2014 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.geotiff;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteOrder;
+import java.util.Enumeration;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.apache.commons.imaging.FormatCompliance;
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.common.bytesource.ByteSource;
+import org.apache.commons.imaging.common.bytesource.ByteSourceInputStream;
+import org.apache.commons.imaging.formats.tiff.TiffContents;
+import org.apache.commons.imaging.formats.tiff.TiffDirectory;
+import org.apache.commons.imaging.formats.tiff.TiffField;
+import org.apache.commons.imaging.formats.tiff.TiffReader;
+import org.apache.commons.imaging.formats.tiff.constants.GeoTiffTagConstants;
+import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
+import org.apache.commons.math3.util.FastMath;
+import org.orekit.rugged.api.RuggedException;
+import org.orekit.rugged.api.TileUpdater;
+import org.orekit.rugged.api.UpdatableTile;
+
+/** Digital Elevation Model Updater using Aster data.
+ * @author Luc Maisonobe
+ */
+public class AsterTileUpdater implements TileUpdater {
+
+    /** Directory for Aster data. */
+    private final File directory;
+
+    /** Simple constructor.
+     * @param directory directory holding Aster data.
+     */
+    public AsterTileUpdater(final File directory) {
+        this.directory = directory;
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public void updateTile(final double latitude, final double longitude,
+                           final UpdatableTile tile)
+        throws RuggedException {
+
+        final String name = fileName(latitude, longitude);
+
+        try {
+
+            // build the file name
+            final File file = new File(directory, name);
+            if (!file.exists()) {
+                throw new RuggedException(AsterMessages.NO_DEM_DATA_FOR_POINT,
+                                          FastMath.toDegrees(latitude), FastMath.toDegrees(longitude));
+            }
+
+            final ZipFile zipFile = new ZipFile(file);
+            for (final Enumeration<? extends ZipEntry> e = zipFile.entries(); e.hasMoreElements();) {
+                final ZipEntry entry = e.nextElement();
+                if ((!entry.isDirectory()) && entry.getName().endsWith("_dem.tif")) {
+                    load(zipFile.getInputStream(entry), file.getAbsolutePath(), tile);
+                }
+            }
+            zipFile.close();
+
+        } catch (IOException ioe) {
+            final RuggedException re =
+                    new RuggedException(AsterMessages.ERROR_PARSING_FILE, name, ioe.getLocalizedMessage());
+            re.initCause(ioe);
+            throw re;
+        }
+
+    }
+
+    /** Build the file name covering a point.
+     * @param latitude point latitude
+     * @param longitude point longitude
+     * @return file name
+     */
+    private String fileName(final double latitude, final double longitude) {
+        final int latCode = (int) FastMath.floor(FastMath.toDegrees(latitude));
+        final int lonCode = (int) FastMath.floor(FastMath.toDegrees(longitude));
+        if (latCode < 0) {
+            if (lonCode < 0) {
+                return String.format("ASTGTM2_S%2dW%3d.zip", -latCode, -lonCode);
+            } else {
+                return String.format("ASTGTM2_S%2dE%3d.zip", -latCode,  lonCode);
+            }
+        } else {
+            if (lonCode < 0) {
+                return String.format("ASTGTM2_N%2dW%3d.zip",  latCode, -lonCode);
+            } else {
+                return String.format("ASTGTM2_N%2dE%3d.zip",  latCode,  lonCode);
+            }
+        }
+    }
+
+    /** Load a Digital Elevation Model.
+     * @param stream stream containing the Digital Elevation Model
+     * @param fileName name of the file
+     * @param tile tile to update
+     * @exception IOException if file cannot be loaded
+     * @exception RuggedException if ASTER data cannot be extracted
+     */
+    private void load(final InputStream stream, final String fileName, final UpdatableTile tile)
+        throws RuggedException, IOException {
+
+        try {
+
+            // read TIFF
+            final TiffReader reader = new TiffReader(true);
+            final ByteSource source = new ByteSourceInputStream(stream, fileName);
+            final TiffContents contents = reader.readContents(source, null, FormatCompliance.getDefault());
+
+            // extract GeoTiff data
+            final TiffField scalesField = contents.findField(GeoTiffTagConstants.EXIF_TAG_MODEL_PIXEL_SCALE_TAG);
+            if (scalesField == null) {
+                throw new RuggedException(AsterMessages.MISSING_PIXEL_SCALE, fileName);
+            }
+            final double[] pixelsScales = scalesField.getDoubleArrayValue();
+
+            final TiffField tieField = contents.findField(GeoTiffTagConstants.EXIF_TAG_MODEL_TIEPOINT_TAG);
+            if (tieField == null) {
+                throw new RuggedException(AsterMessages.MISSING_TIE_POINT, fileName);
+            }
+            final double[] tiePoint = tieField.getDoubleArrayValue();
+
+            final int    latitudeRows     = contents.findField(TiffTagConstants.TIFF_TAG_IMAGE_LENGTH).getIntValue();
+            final int    longitudeColumns = contents.findField(TiffTagConstants.TIFF_TAG_IMAGE_WIDTH).getIntValue();
+
+            final int[] geoKeyDirectory   = contents.findField(GeoTiffTagConstants.EXIF_TAG_GEO_KEY_DIRECTORY_TAG).getIntArrayValue();
+            final int keyDirectoryVersion = geoKeyDirectory[0];
+            final int keyRevision         = geoKeyDirectory[1];
+            final int minorRevision       = geoKeyDirectory[2];
+            final int numberOfKeys        = geoKeyDirectory[3];
+            if (keyDirectoryVersion != 1 || keyRevision != 1 || minorRevision != 0) {
+                throw new RuggedException(AsterMessages.UNSUPPORTED_GEOTIFF_VERSION,
+                                          keyDirectoryVersion, keyRevision, minorRevision, fileName,
+                                          1, 1, 0);
+            }
+
+            AngulerUnits angulerUnits = AngulerUnits.DEGREE;
+            for (int i = 0; i < numberOfKeys; ++i) {
+                final GeoKey geoKey   = GeoKey.getKey(geoKeyDirectory[4 * i + 4]);
+                final int location    = geoKeyDirectory[4 * i + 5];
+                final int count       = geoKeyDirectory[4 * i + 6];
+                final int valueOffset = geoKeyDirectory[4 * i + 7];
+                switch(geoKey) {
+                case GT_MODEL_TYPE: {
+                    final ModelType modelType = ModelType.getType(getShort(geoKey, location, count, valueOffset, fileName));
+                    if (modelType != ModelType.GEOGRAPHIC) {
+                        throw new RuggedException(AsterMessages.UNEXPECTED_GEOKEY_VALUE,
+                                                  geoKey, fileName, modelType, ModelType.GEOCENTRIC);
+                    }
+                    break;
+                }
+                case GT_RASTER_TYPE: {
+                    final RasterType rasterType = RasterType.getType(getShort(geoKey, location, count, valueOffset, fileName));
+                    if (rasterType != RasterType.RASTER_PIXEL_IS_AREA) {
+                        throw new RuggedException(AsterMessages.UNEXPECTED_GEOKEY_VALUE,
+                                                  geoKey, fileName, rasterType, RasterType.RASTER_PIXEL_IS_AREA);
+                    }
+                    break;
+                }
+                case GEOGRAPHIC_TYPE: {
+                    final GeographicCoordinateSystemType csType =
+                            GeographicCoordinateSystemType.getType(getShort(geoKey, location, count, valueOffset, fileName));
+                    if (csType != GeographicCoordinateSystemType.GCS_WGS_84) {
+                        throw new RuggedException(AsterMessages.UNEXPECTED_GEOKEY_VALUE,
+                                                  geoKey, fileName, csType, GeographicCoordinateSystemType.GCS_WGS_84);
+                    }
+                    break;
+                }
+                case GEOG_LINEAR_UNITS: {
+                    final LinearUnits linearUnits =
+                            LinearUnits.getUnits(getShort(geoKey, location, count, valueOffset, fileName));
+                    if (linearUnits != LinearUnits.METER) {
+                        throw new RuggedException(AsterMessages.UNEXPECTED_GEOKEY_VALUE,
+                                                  geoKey, fileName, linearUnits, LinearUnits.METER);
+                    }
+                    break;
+                }
+                case GEOG_ANGULAR_UNITS: {
+                    angulerUnits = AngulerUnits.getUnits(getShort(geoKey, location, count, valueOffset, fileName));
+                    break;
+                }
+                default:
+                    throw new RuggedException(AsterMessages.UNEXPECTED_GEOKEY, geoKey, fileName);
+                }
+            }
+
+            // set up geometry
+            final double latitudeStep  = angulerUnits.toRadians(pixelsScales[1]);
+            final double longitudeStep = angulerUnits.toRadians(pixelsScales[0]);
+            final double minLatitude   = angulerUnits.toRadians(tiePoint[4]) - (latitudeRows - 1) * latitudeStep;
+            final double minLongitude  = angulerUnits.toRadians(tiePoint[3]);
+            tile.setGeometry(minLatitude, minLongitude, latitudeStep, longitudeStep,
+                             latitudeRows, longitudeColumns);
+
+            // read the raster data
+            final int msb = reader.getByteOrder() == ByteOrder.BIG_ENDIAN ? 0 : 1;
+            final int lsb = reader.getByteOrder() == ByteOrder.BIG_ENDIAN ? 1 : 0;
+            int i = 0;
+            for (final TiffDirectory tiffDirectory : contents.directories) {
+                for (final TiffDirectory.ImageDataElement element : tiffDirectory.getTiffRawImageDataElements()) {
+                    final byte[] bytes = source.getBlock(element.offset, element.length);
+                    for (int longitudeIndex = 0; longitudeIndex < longitudeColumns; ++longitudeIndex) {
+                        final int elevation = (bytes[2 * longitudeIndex + msb] << 8) |
+                                bytes[2 * longitudeIndex + 1 + lsb];
+                        tile.setElevation(latitudeRows - 1 - i, longitudeIndex, elevation);
+                    }
+                    i++;
+                }
+            }
+
+        } catch (ImageReadException ire) {
+            throw new RuggedException(AsterMessages.ERROR_PARSING_FILE,
+                                      fileName, ire.getLocalizedMessage());
+        }
+
+    }
+
+    /** Get a short from the geo key directory.
+     * @param key being parsed
+     * @param location location of the short
+     * @param count number of elements
+     * @param valueOffset offset of the value
+     * @param fileName name of the file
+     * @return short value
+     * @exception RuggedException if value cannot be retrieved
+     */
+    private int getShort(final GeoKey key, final int location, final int count, final int valueOffset,
+                         final String fileName)
+        throws RuggedException {
+        if (location != 0 && count != 1) {
+            throw new RuggedException(AsterMessages.UNABLE_TO_RETRIEVE_VALUE_FOR_KEY, key, fileName);
+        }
+        return valueOffset;
+    }
+
+}
diff --git a/geotiff/src/main/java/org/orekit/rugged/geotiff/GeoTiffDEM.java b/geotiff/src/main/java/org/orekit/rugged/geotiff/GeoTiffDEM.java
deleted file mode 100644
index dbc6233f..00000000
--- a/geotiff/src/main/java/org/orekit/rugged/geotiff/GeoTiffDEM.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/* Copyright 2013-2014 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.geotiff;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-import org.apache.commons.imaging.FormatCompliance;
-import org.apache.commons.imaging.ImageReadException;
-import org.apache.commons.imaging.common.bytesource.ByteSource;
-import org.apache.commons.imaging.common.bytesource.ByteSourceInputStream;
-import org.apache.commons.imaging.formats.tiff.TiffContents;
-import org.apache.commons.imaging.formats.tiff.TiffField;
-import org.apache.commons.imaging.formats.tiff.TiffReader;
-import org.apache.commons.imaging.formats.tiff.constants.GeoTiffTagConstants;
-
-/** Loader for GeoTiff Digital Elevation Model similar to ASTER files.
- * @author Luc Maisonobe
- */
-public class GeoTiffDEM {
-
-    /** Pixels scales. */
-    private double[] pixelsScales;
-
-    /** Tie point. */
-    private double[] tiePoint;
-
-    /** Model type. */
-    private ModelType modelType;
-
-    /** Raster type. */
-    private RasterType rasterType;
-
-    /** Geographic type. */
-    private GeographicCoordinateSystemType csType;
-
-    /** Linear units. */
-    private LinearUnits linearUnits;
-
-    /** Angular units. */
-    private AngulerUnits angulerUnits;
-
-    /** Load a Digital Elevation Model.
-     * @param file file containing the Digital Elevation Model
-     * @exception IOException if file cannot be loaded
-     * @exception ImageReadException if TIFF data cannot be extracted
-     */
-    public GeoTiffDEM(final File file) throws IOException, ImageReadException {
-        InputStream stream = null;
-        try {
-            stream = new FileInputStream(file);
-            load(stream, file.getName());
-        } finally {
-            if (stream != null) {
-                stream.close();
-            }
-        }
-    }
-
-    /** Load a Digital Elevation Model.
-     * @param stream stream containing the Digital Elevation Model
-     * @param fileName name of the file
-     * @exception IOException if file cannot be loaded
-     * @exception ImageReadException if TIFF data cannot be extracted
-     */
-    public GeoTiffDEM(final InputStream stream, final String fileName)
-        throws IOException, ImageReadException {
-        load(stream, fileName);
-    }
-
-    /** Load a Digital Elevation Model.
-     * @param stream stream containing the Digital Elevation Model
-     * @param fileName name of the file
-     * @exception IOException if file cannot be loaded
-     * @exception ImageReadException if TIFF data cannot be extracted
-     */
-    private void load(final InputStream stream, final String fileName)
-        throws IOException, ImageReadException {
-
-        // read TIFF
-        final TiffReader reader = new TiffReader(true);
-        final ByteSource source = new ByteSourceInputStream(stream, fileName);
-        final TiffContents content = reader.readContents(source, null, FormatCompliance.getDefault());
-
-        // extract GeoTiff data
-        pixelsScales = content.findField(GeoTiffTagConstants.EXIF_TAG_MODEL_PIXEL_SCALE_TAG).getDoubleArrayValue();
-        tiePoint     = content.findField(GeoTiffTagConstants.EXIF_TAG_MODEL_TIEPOINT_TAG).getDoubleArrayValue();
-
-        final TiffField geoAsciiParams  = content.findField(GeoTiffTagConstants.EXIF_TAG_GEO_ASCII_PARAMS_TAG);
-        final TiffField geoDoubleParams = content.findField(GeoTiffTagConstants.EXIF_TAG_GEO_DOUBLE_PARAMS_TAG);
-        final int[] geoKeyDirectory     = content.findField(GeoTiffTagConstants.EXIF_TAG_GEO_KEY_DIRECTORY_TAG).getIntArrayValue();
-        final int keyDirectoryVersion = geoKeyDirectory[0];
-        final int keyRevision         = geoKeyDirectory[1];
-        final int minorRevision       = geoKeyDirectory[2];
-        final int numberOfKeys        = geoKeyDirectory[3];
-        for (int i = 0; i < numberOfKeys; ++i) {
-            final GeoKey geoKey   = GeoKey.getKey(geoKeyDirectory[4 * i + 4]);
-            final int location    = geoKeyDirectory[4 * i + 5];
-            final int count       = geoKeyDirectory[4 * i + 6];
-            final int valueOffset = geoKeyDirectory[4 * i + 7];
-            switch(geoKey) {
-            case GT_MODEL_TYPE:
-                modelType = ModelType.getType(getShort(geoKey, location, count, valueOffset));
-                break;
-            case GT_RASTER_TYPE:
-                rasterType = RasterType.getType(getShort(geoKey, location, count, valueOffset));
-                break;
-            case GEOGRAPHIC_TYPE:
-                csType = GeographicCoordinateSystemType.getType(getShort(geoKey, location, count, valueOffset));
-                break;
-            case GEOG_LINEAR_UNITS:
-                linearUnits = LinearUnits.getUnits(getShort(geoKey, location, count, valueOffset));
-                break;
-            case GEOG_ANGULAR_UNITS:
-                angulerUnits = AngulerUnits.getUnits(getShort(geoKey, location, count, valueOffset));
-                break;
-            default:
-                // TODO: support the other geo keys
-                throw new ImageReadException(geoKey + " unsupported for now");
-            }
-        }
-
-    }
-
-    /** Get a short from the geo key directory.
-     * @param key being parsed
-     * @param location location of the short
-     * @param count number of elements
-     * @param valueOffset offset of the value
-     * @return short value
-     * @exception ImageReadException if value cannot be retrieved
-     */
-    private int getShort(final GeoKey key, final int location, final int count, final int valueOffset)
-        throws ImageReadException {
-        if (location != 0 && count != 1) {
-            throw new ImageReadException("cannot retrieve value for " + key);
-        }
-        return valueOffset;
-    }
-
-    /** Get the pixels scales.
-     * @return pixels scales
-     */
-    public double[] getPixelScales() {
-        return pixelsScales.clone();
-    }
-
-    /** Get the tie point.
-     * @return tie point
-     */
-    public double[] getTiePoint() {
-        return tiePoint.clone();
-    }
-
-    /** Get the model type.
-     * @return model type
-     */
-    public ModelType getModelType() {
-        return modelType;
-    }
-
-    /** Get the raster type.
-     * @return raster type
-     */
-    public RasterType getRasterType() {
-        return rasterType;
-    }
-
-    /** Get the geographic coordinate system type.
-     * @return geographic coordinate system type
-     */
-    public GeographicCoordinateSystemType getCSType() {
-        return csType;
-    }
-
-    /** Get the linear units.
-     * @return linear units
-     */
-    public LinearUnits getLinearUnits() {
-        return linearUnits;
-    }
-
-    /** Get the angular units.
-     * @return angular units
-     */
-    public AngulerUnits getAngularUnits() {
-        return angulerUnits;
-    }
-
-
-}
diff --git a/geotiff/src/main/resources/assets/org/orekit/rugged/AsterMessages_en.utf8 b/geotiff/src/main/resources/assets/org/orekit/rugged/AsterMessages_en.utf8
new file mode 100644
index 00000000..94d1e8bd
--- /dev/null
+++ b/geotiff/src/main/resources/assets/org/orekit/rugged/AsterMessages_en.utf8
@@ -0,0 +1,23 @@
+# no Digital Elevation Model data for point {0}, {1}
+NO_DEM_DATA_FOR_POINT = no Digital Elevation Model data for point {0}, {1}
+
+# error parsing file {0}: {1}
+ERROR_PARSING_FILE = error parsing file {0}: {1}
+
+# missing pixel scale GeoTIFF tag in file {0}
+MISSING_PIXEL_SCALE = missing pixel scale GeoTIFF tag in file {0}
+
+# missing tie point GeoTIFF tag in file {0}
+MISSING_TIE_POINT = missing tie point GeoTIFF tag in file {0}
+
+# unsupported GeoTIFF version {0}/{1}.{2} in file {3} (expected {4}/{5}.{6})
+UNSUPPORTED_GEOTIFF_VERSION = unsupported GeoTIFF version {0}/{1}.{2} in file {3} (expected {4}/{5}.{6})
+
+# unable to retrieve value for key {0} in file {1}
+UNABLE_TO_RETRIEVE_VALUE_FOR_KEY = unable to retrieve value for key {0} in file {1}
+
+# unexpected GeoTIFF key {0} in file {1}
+UNEXPECTED_GEOKEY = unexpected GeoTIFF key {0} in file {1}
+
+# GeoTIFF key {0} in file {1} has unexpected value {2} (expected {3})
+UNEXPECTED_GEOKEY_VALUE = GeoTIFF key {0} in file {1} has unexpected value {2} (expected {3})
diff --git a/geotiff/src/main/resources/assets/org/orekit/rugged/AsterMessages_fr.utf8 b/geotiff/src/main/resources/assets/org/orekit/rugged/AsterMessages_fr.utf8
new file mode 100644
index 00000000..c5b4ec13
--- /dev/null
+++ b/geotiff/src/main/resources/assets/org/orekit/rugged/AsterMessages_fr.utf8
@@ -0,0 +1,23 @@
+# no Digital Elevation Model data for point {0}, {1}
+NO_DEM_DATA_FOR_POINT = pas de données de Modèle Numérique de Terrain pour le point {0}, {1}
+
+# error parsing file {0}: {1}
+ERROR_PARSING_FILE = erreur lors de l''analyse du fichier {0} : {1}
+
+# missing pixel scale GeoTIFF tag in file {0}
+MISSING_PIXEL_SCALE = méta-donnée « pixel scale » GeoTIFF manquante dans le fichier {0}
+
+# missing tie point GeoTIFF tag in file {0}
+MISSING_TIE_POINT = méta-donnée « tie point » GeoTIFF manquante dans le fichier {0}
+
+# unsupported GeoTIFF version {0}/{1}.{2} in file {3} (expected {4}/{5}.{6})
+UNSUPPORTED_GEOTIFF_VERSION = version GeoTIFF {0}/{1}.{2} du fichier {3} non prise en compte (version attendue : {4}/{5}.{6})
+
+# unable to retrieve value for key {0} in file {1}
+UNABLE_TO_RETRIEVE_VALUE_FOR_KEY = impossible de récupérer la valeur pour le clef {0} dans le fichier {1}
+
+# unexpected GeoTIFF key {0} in file {1}
+UNEXPECTED_GEOKEY = clef GeoTIFF {0} inattendue dans le fichier {1}
+
+# GeoTIFF key {0} in file {1} has unexpected value {2} (expected {3})
+UNEXPECTED_GEOKEY_VALUE = la clef GeoTIFF {0} du fichier {1} a la valeur inattendue {2} (valeur attendue : {3})
diff --git a/geotiff/src/test/java/org/orekit/rugged/geotiff/AsterMessagesTest.java b/geotiff/src/test/java/org/orekit/rugged/geotiff/AsterMessagesTest.java
new file mode 100644
index 00000000..ba19843f
--- /dev/null
+++ b/geotiff/src/test/java/org/orekit/rugged/geotiff/AsterMessagesTest.java
@@ -0,0 +1,104 @@
+/* Copyright 2002-2014 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.geotiff;
+
+
+import java.text.MessageFormat;
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class AsterMessagesTest {
+
+    @Test
+    public void testMessageNumber() {
+        Assert.assertEquals(8, AsterMessages.values().length);
+    }
+
+    @Test
+    public void testAllKeysPresentInPropertiesFiles() {
+        for (final String language : new String[] { "en", "fr" } ) {
+            ResourceBundle bundle =
+                ResourceBundle.getBundle("assets/org/orekit/rugged/AsterMessages",
+                                         new Locale(language), new AsterMessages.UTF8Control());
+            for (AsterMessages message : AsterMessages.values()) {
+                final String messageKey = message.toString();
+                boolean keyPresent = false;
+                for (final Enumeration<String> keys = bundle.getKeys(); keys.hasMoreElements();) {
+                    keyPresent |= messageKey.equals(keys.nextElement());
+                }
+                Assert.assertTrue("missing key \"" + message.name() + "\" for language " + language,
+                                  keyPresent);
+            }
+            Assert.assertEquals(language, bundle.getLocale().getLanguage());
+        }
+
+    }
+
+    @Test
+    public void testAllPropertiesCorrespondToKeys() {
+        for (final String language : new String[] { "en", "fr" } ) {
+            ResourceBundle bundle =
+                ResourceBundle.getBundle("assets/org/orekit/rugged/AsterMessages",
+                                         new Locale(language), new AsterMessages.UTF8Control());
+            for (final Enumeration<String> keys = bundle.getKeys(); keys.hasMoreElements();) {
+                final String propertyKey = keys.nextElement();
+                try {
+                    Assert.assertNotNull(AsterMessages.valueOf(propertyKey));
+                } catch (IllegalArgumentException iae) {
+                    Assert.fail("unknown key \"" + propertyKey + "\" in language " + language);
+                }
+            }
+            Assert.assertEquals(language, bundle.getLocale().getLanguage());
+        }
+
+    }
+
+    @Test
+    public void testNoMissingFrenchTranslation() {
+        for (AsterMessages message : AsterMessages.values()) {
+            String translated = message.getLocalizedString(Locale.FRENCH);
+            Assert.assertFalse(message.name(), translated.toLowerCase().contains("missing translation"));
+        }
+    }
+
+    @Test
+    public void testNoOpEnglishTranslation() {
+        for (AsterMessages message : AsterMessages.values()) {
+            String translated = message.getLocalizedString(Locale.ENGLISH);
+            Assert.assertEquals(message.getSourceString(), translated);
+        }
+    }
+
+    @Test
+    public void testVariablePartsConsistency() {
+        for (final String language : new String[] { "en", "fr" } ) {
+            Locale locale = new Locale(language);
+            for (AsterMessages message : AsterMessages.values()) {
+                MessageFormat source     = new MessageFormat(message.getSourceString());
+                MessageFormat translated = new MessageFormat(message.getLocalizedString(locale));
+                Assert.assertEquals(message.name() + " (" + language + ")",
+                                    source.getFormatsByArgumentIndex().length,
+                                    translated.getFormatsByArgumentIndex().length);
+            }
+        }
+    }
+
+}
diff --git a/geotiff/src/test/java/org/orekit/rugged/geotiff/AsterTileUpdaterTest.java b/geotiff/src/test/java/org/orekit/rugged/geotiff/AsterTileUpdaterTest.java
new file mode 100644
index 00000000..01906392
--- /dev/null
+++ b/geotiff/src/test/java/org/orekit/rugged/geotiff/AsterTileUpdaterTest.java
@@ -0,0 +1,117 @@
+/* Copyright 2013-2014 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.geotiff;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.math3.util.FastMath;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.orekit.rugged.api.RuggedException;
+import org.orekit.rugged.core.raster.SimpleTile;
+import org.orekit.rugged.core.raster.SimpleTileFactory;
+import org.orekit.rugged.core.raster.TileFactory;
+
+
+public class AsterTileUpdaterTest {
+
+    @Test
+    public void testAster() throws RuggedException {
+
+        File folder = warningFile.getParentFile();
+        List<int[]> corners = getCorners(folder);
+        if (corners.isEmpty()) {
+            // no ASTER data available in the test resources
+            // warn user, but don't allow the test to fail
+            displayWarning();
+        } else {
+
+            TileFactory<SimpleTile> factory = new SimpleTileFactory();
+            AsterTileUpdater updater = new AsterTileUpdater(folder);
+            for (int[] corner : corners) {
+
+                SimpleTile tile = factory.createTile();
+                updater.updateTile(FastMath.toRadians(corner[0] + 0.2),
+                                   FastMath.toRadians(corner[1] + 0.7),
+                                   tile);
+                tile.tileUpdateCompleted();
+
+                Assert.assertEquals(corner[0] + 1.0 / 7200.0, FastMath.toDegrees(tile.getMinimumLatitude()),  1.0e-10);
+                Assert.assertEquals(corner[1] - 1.0 / 7200.0, FastMath.toDegrees(tile.getMinimumLongitude()), 1.0e-10);
+                Assert.assertEquals(1.0 / 3600.0, FastMath.toDegrees(tile.getLatitudeStep()), 1.0e-10);
+                Assert.assertEquals(1.0 / 3600.0, FastMath.toDegrees(tile.getLongitudeStep()), 1.0e-10);
+                Assert.assertTrue(tile.getMinElevation() <  9000.0);
+                Assert.assertTrue(tile.getMaxElevation() > -1000.0);
+
+            }
+
+        }
+
+    }
+
+    @Before
+    public void setUp() {
+        try {
+            String warningResource = "org/orekit/rugged/geotiff/ASTER-files-warning.txt";
+            URL url = AsterTileUpdaterTest.class.getClassLoader().getResource(warningResource);
+            warningFile = new File(url.toURI().getPath());
+        } catch (URISyntaxException urise) {
+            Assert.fail(urise.getLocalizedMessage());
+        }
+    }
+
+    private List<int[]> getCorners(File folder) {
+        Pattern patter = Pattern.compile("ASTGTM2_([NS]\\d\\d)([EW]\\d\\d\\d)\\.zip$");
+        List<int[]> asterCorners = new ArrayList<int[]>();
+        for (final File file : folder.listFiles()) {
+            Matcher matcher = patter.matcher(file.getName());
+            if (matcher.matches()) {
+                int latCode = (matcher.group(1).startsWith("N") ? 1 : -1) * Integer.parseInt(matcher.group(1).substring(1));
+                int lonCode = (matcher.group(2).startsWith("E") ? 1 : -1) * Integer.parseInt(matcher.group(2).substring(1));
+                asterCorners.add(new int[] { latCode, lonCode });
+            }
+        }
+        return asterCorners;
+    }
+
+    private void displayWarning() {
+        try {
+            System.err.println("######  " + warningFile.getAbsolutePath() + "  ######");
+            BufferedReader reader = new BufferedReader(new FileReader(warningFile));
+            for (String line = reader.readLine(); line != null; line = reader.readLine()) {
+                System.err.println(line);
+            }
+            reader.close();
+            System.err.println("######  " + warningFile.getAbsolutePath() + "  ######");
+        } catch (IOException ioe) {
+            Assert.fail(ioe.getLocalizedMessage());
+        }
+    }
+
+    private File warningFile;
+
+}
diff --git a/geotiff/src/test/java/org/orekit/rugged/geotiff/GeoTiffDEMTest.java b/geotiff/src/test/java/org/orekit/rugged/geotiff/GeoTiffDEMTest.java
deleted file mode 100644
index 3d90ac92..00000000
--- a/geotiff/src/test/java/org/orekit/rugged/geotiff/GeoTiffDEMTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Copyright 2013-2014 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.geotiff;
-
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.util.Enumeration;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-import org.apache.commons.imaging.ImageReadException;
-import org.junit.Assert;
-import org.junit.Test;
-import org.orekit.rugged.geotiff.AngulerUnits;
-import org.orekit.rugged.geotiff.GeoTiffDEM;
-import org.orekit.rugged.geotiff.GeographicCoordinateSystemType;
-import org.orekit.rugged.geotiff.LinearUnits;
-import org.orekit.rugged.geotiff.ModelType;
-import org.orekit.rugged.geotiff.RasterType;
-
-
-public class GeoTiffDEMTest {
-
-    @Test
-    public void testAster() throws URISyntaxException, IOException, ImageReadException {
-        String zipFile = "org/orekit/rugged/geotiff/ASTGTM2_S21E165.zip";
-        String zipPath = GeoTiffDEMTest.class.getClassLoader().getResource(zipFile).toURI().getPath();
-        ZipFile zip = new ZipFile(zipPath);
-        for (Enumeration<? extends ZipEntry> e = zip.entries(); e.hasMoreElements();) {
-            ZipEntry entry = e.nextElement();
-            if ((!entry.isDirectory()) && entry.getName().endsWith("_dem.tif")) {
-                GeoTiffDEM geoTiffDEM = new GeoTiffDEM(zip.getInputStream(entry), entry.getName());
-                Assert.assertEquals(ModelType.GEOGRAPHIC,                      geoTiffDEM.getModelType());
-                Assert.assertEquals(RasterType.RASTER_PIXEL_IS_AREA,           geoTiffDEM.getRasterType());
-                Assert.assertEquals(GeographicCoordinateSystemType.GCS_WGS_84, geoTiffDEM.getCSType());
-                Assert.assertEquals(LinearUnits.METER,                         geoTiffDEM.getLinearUnits());
-                Assert.assertEquals(AngulerUnits.DEGREE,                       geoTiffDEM.getAngularUnits());
-                Assert.assertEquals(6, geoTiffDEM.getTiePoint().length);
-                Assert.assertEquals(  0.0,               geoTiffDEM.getTiePoint()[0], 1.0e-10);
-                Assert.assertEquals(  0.0,               geoTiffDEM.getTiePoint()[1], 1.0e-10);
-                Assert.assertEquals(  0.0,               geoTiffDEM.getTiePoint()[2], 1.0e-10);
-                Assert.assertEquals(164.9998611111111,   geoTiffDEM.getTiePoint()[3], 1.0e-10);
-                Assert.assertEquals(-19.999861111111112, geoTiffDEM.getTiePoint()[4], 1.0e-10);
-                Assert.assertEquals(  0.0,               geoTiffDEM.getTiePoint()[5], 1.0e-10);
-            }
-        }
-        zip.close();
-    }
-
-}
diff --git a/geotiff/src/test/resources/org/orekit/rugged/geotiff/ASTER-files-warning.txt b/geotiff/src/test/resources/org/orekit/rugged/geotiff/ASTER-files-warning.txt
new file mode 100644
index 00000000..f8081b05
--- /dev/null
+++ b/geotiff/src/test/resources/org/orekit/rugged/geotiff/ASTER-files-warning.txt
@@ -0,0 +1,19 @@
+For test purposes, some ASTER files should be put in the same folder as this file.
+
+ASTER stands for Advanced Spaceborne Thermal Emission and Reflection Radiometer
+and is a joint effort of the Ministry of Economy, Trade, and Industry (METI) of
+Japan and the United States National Aeronautics and Space Administration (NASA).
+More information on how to get the files is available here:
+
+  http://asterweb.jpl.nasa.gov/gdem.asp
+
+The Rugged library cannot distribute such test files, so the distributed folder
+contains only this warning text file and no real ASTER files. If the folder still does
+not contain any ASTER files at tests run time, the content of this file is displayed
+as a warning but the tests won't fail.
+
+If users want to really perform tests, they have to retrieve ASTER files by themselves
+and copy them in the folder. Then the files will automatically been picked up and used
+for the tests. The files must have a name of the form ASTGTM2_v##h###.zip, where v
+stands for either N or S, h stands for either E or W and # stands for digits. The zip
+files themselves are used for the tests, users should not extract the _dem.tif files.
-- 
GitLab