sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1783778 - in /sis/branches/JDK8/core/sis-referencing/src: main/java/org/apache/sis/referencing/gazetteer/ test/java/org/apache/sis/referencing/gazetteer/ test/java/org/apache/sis/test/suite/
Date Mon, 20 Feb 2017 15:38:45 GMT
Author: desruisseaux
Date: Mon Feb 20 15:38:45 2017
New Revision: 1783778

URL: http://svn.apache.org/viewvc?rev=1783778&view=rev
Log:
Refactor MGRSEncoder as an inner class of MilitaryGridReferenceSystem.

Removed:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MGRSEncoder.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MGRSEncoderTest.java
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystemTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java?rev=1783778&r1=1783777&r2=1783778&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystem.java
[UTF-8] Mon Feb 20 15:38:45 2017
@@ -23,18 +23,26 @@ import org.opengis.util.FactoryException
 import org.opengis.geometry.DirectPosition;
 import org.opengis.referencing.crs.ProjectedCRS;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.OperationMethod;
+import org.opengis.referencing.operation.Projection;
 import org.opengis.referencing.operation.TransformException;
 import org.apache.sis.internal.referencing.provider.TransverseMercator;
+import org.apache.sis.internal.referencing.provider.PolarStereographicA;
 import org.apache.sis.internal.referencing.Resources;
+import org.apache.sis.referencing.CRS;
 import org.apache.sis.referencing.CommonCRS;
+import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.referencing.crs.DefaultProjectedCRS;
+import org.apache.sis.referencing.cs.AxesConvention;
 import org.apache.sis.math.MathFunctions;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.StringBuilders;
+import org.apache.sis.util.Utilities;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.geometry.DirectPosition2D;
 
-import static org.apache.sis.referencing.gazetteer.MGRSEncoder.*;
-
 
 /**
  * The Military Grid Reference System (MGRS).
@@ -57,13 +65,74 @@ import static org.apache.sis.referencing
  */
 public class MilitaryGridReferenceSystem {
     /**
+     * Height of latitude bands, in degrees.
+     * Those bands are labeled from {@code 'C'} to {@code 'X'} inclusive, excluding {@code
'I'} and {@code 'O'}.
+     */
+    static final double LATITUDE_BAND_HEIGHT = 8;
+
+    /**
+     * Special {@link #crsZone} value for the UPS South (Universal Polar Stereographic) projection.
+     */
+    static final int SOUTH_POLE = -1000;
+
+    /**
+     * Special {@link #crsZone} value for the UPS North (Universal Polar Stereographic) projection.
+     */
+    static final int NORTH_POLE = 1000;
+
+    /**
+     * Size of the 100,000-meter squares.
+     */
+    static final double GRID_SQUARE_SIZE = 100_000;
+
+    /**
+     * Number of letters available for grid rows. Those letters are "ABCDEFGHJKLMNPQRSTUV"
(starting at letter
+     * F for zones of even number), repeated in a cycle. Each row is {@value #GRID_SQUARE_SIZE}
metres height.
+     */
+    static final int GRID_ROW_COUNT = 20;
+
+    /**
+     * The number of digits in a one-meter precision when formatting MGRS labels.
+     *
+     * <p><b>Invariant:</b> the following relationship must hold:
+     * {@code GRID_SQUARE_SIZE == Math.pow(10, METRE_PRECISION_DIGITS)}
+     */
+    static final int METRE_PRECISION_DIGITS = 5;
+
+    /**
+     * The first of the two letters ({@code 'I'} and {@code 'O'}) excluded in MGRS notation.
+     * This letter and all following letters shall be shifted by one character. Example:
+     *
+     * {@preformat java
+     *     char band = ...;
+     *     if (band >= EXCLUDE_I) {
+     *         band++;
+     *         if (band >= EXCLUDE_O) band++;
+     *     }
+     * }
+     *
+     * or equivalently:
+     *
+     * {@preformat java
+     *     char band = ...;
+     *     if (band >= EXCLUDE_I && ++band >= EXCLUDE_O) band++;
+     * }
+     */
+    static final char EXCLUDE_I = 'I';
+
+    /**
+     * The second of the two letters ({@code 'I'} and {@code 'O'}) excluded in MGRS notation.
+     */
+    static final char EXCLUDE_O = 'O';
+
+    /**
      * The datum to which to transform the coordinate before formatting the MGRS label.
      * Only the datums enumerated in {@link CommonCRS} are currently supported.
      */
     final CommonCRS datum;
 
     /**
-     * Whether {@link MGRSEncoder} should infer the datum from the given coordinates
+     * Whether {@link Encoder} should infer the datum from the given coordinates
      * instead than using {@link #datum}.
      */
     final boolean avoidDatumChange;
@@ -132,10 +201,10 @@ public class MilitaryGridReferenceSystem
         /**
          * Cached information needed for building a MGRS label from a direct position in
the given CRS.
          */
-        private final Map<CoordinateReferenceSystem,MGRSEncoder> encoders;
+        private final Map<CoordinateReferenceSystem,Encoder> encoders;
 
         /**
-         * Temporary positions used by {@link MGRSEncoder} only. References are kept for
avoiding to
+         * Temporary positions used by {@link Encoder} only. References are kept for avoiding
to
          * recreate those temporary objects for every label to format.
          */
         DirectPosition normalized, geographic;
@@ -234,10 +303,10 @@ public class MilitaryGridReferenceSystem
         public String encode(final DirectPosition position) throws TransformException {
             ArgumentChecks.ensureNonNull("position", position);
             final CoordinateReferenceSystem crs = position.getCoordinateReferenceSystem();
-            MGRSEncoder encoder = encoders.get(crs);
+            Encoder encoder = encoders.get(crs);
             try {
                 if (encoder == null) {
-                    encoder = new MGRSEncoder(avoidDatumChange ? null : datum, crs);
+                    encoder = new Encoder(avoidDatumChange ? null : datum, crs);
                     if (encoders.put(crs, encoder) != null) {
                         throw new ConcurrentModificationException();            // Opportunistic
check.
                     }
@@ -301,7 +370,7 @@ public class MilitaryGridReferenceSystem
                 /*
                  * At this point, 'c' is a valid letter. First, applies a correction for
the fact that 'I' and 'O'
                  * letters were excluded. Next, the conversion to latitude or 100 000 meters
grid indices depends
-                 * on which part we are parsing. The formulas used below are about the same
than in MGRSEncoder,
+                 * on which part we are parsing. The formulas used below are about the same
than in Encoder,
                  * with terms moved on the other side of the equations.
                  */
                 if (c >= EXCLUDE_O) c--;
@@ -415,4 +484,273 @@ public class MilitaryGridReferenceSystem
         }
         throw new GazetteerException(Resources.format(errorKey, part), cause);
     }
+
+
+
+
+    /**
+     * Conversions from direct positions to Military Grid Reference System (MGRS) labels.
+     * Each {@code Encoder} instance is configured for one {@code DirectPosition} CRS.
+     * If a position is given in another CRS, another {@code Encoder} instance must be created.
+     *
+     * <div class="section">Immutability and thread safety</div>
+     * This class is <strong>not</strong> thread-safe. A new instance must be
created for each thread,
+     * or synchronization must be applied by the caller.
+     *
+     * @author  Martin Desruisseaux (Geomatys)
+     * @since   0.8
+     * @version 0.8
+     * @module
+     *
+     * @see <a href="https://en.wikipedia.org/wiki/Military_Grid_Reference_System">Military
Grid Reference System on Wikipedia</a>
+     */
+    static final class Encoder {
+        /**
+         * The datum to which to transform the coordinate before formatting the MGRS label.
+         * Only the datums enumerated in {@link CommonCRS} are currently supported.
+         */
+        private final CommonCRS datum;
+
+        /**
+         * UTM zone of position CRS (negative for South hemisphere), or {@value #NORTH_POLE}
or {@value #SOUTH_POLE}
+         * if the CRS is a Universal Polar Stereographic projection, or 0 if the CRS is not
a recognized projection.
+         * Note that this is not necessarily the same zone than the one to use for formatting
any given coordinate in
+         * that projected CRS, since the {@link #zone(double, char)} method has special rules
for some latitudes.
+         */
+        private final int crsZone;
+
+        /**
+         * Coordinate conversion from the position CRS to a CRS of the same type but with
normalized axes,
+         * or {@code null} if not needed. After conversion, axis directions will be (East,
North) and axis
+         * units will be metres.
+         *
+         * <p>This transform should perform only simple operations like swapping axis
order and unit conversions.
+         * It should not perform more complex operations that would require to go back to
geographic coordinates.</p>
+         */
+        private final MathTransform toNormalized;
+
+        /**
+         * Coordinate conversion or transformation from the <em>normalized</em>
CRS to geographic CRS.
+         * Axis directions are (North, East) as in EPSG geodetic dataset and axis units are
degrees.
+         * This transform is never {@code null}.
+         *
+         * <p>This transform may contain datum change from the position datum to the
target {@link #datum}.</p>
+         */
+        private final MathTransform toGeographic;
+
+        /**
+         * A transform from a position in the CRS given at construction time to a position
in the CRS identified by
+         * {@link #actualZone}. This field is updated only when a given position is not located
in the zone of the
+         * CRS given at construction time.
+         */
+        private MathTransform toActualZone;
+
+        /**
+         * The actual zone where the position to encode is located. Legal values are the
same than {@link #crsZone}.
+         * If non-zero, then this is the zone of the {@link #toActualZone} transform. This
field is updated only when
+         * a given position is not located in the zone of the CRS given at construction time.
+         */
+        private int actualZone;
+
+        /**
+         * Creates a new converter from direct positions to MGRS labels.
+         *
+         * @param  datum  the datum to which to transform the coordinate before formatting
the MGRS label,
+         *                or {@code null} for inferring the datum from the given {@code
crs}.
+         * @param  crs    the coordinate reference system of the coordinates for which to
create MGRS labels.
+         * @throws IllegalArgumentException if the given CRS has no horizontal component
or do not use one of
+         *         the supported datums.
+         */
+        Encoder(CommonCRS datum, CoordinateReferenceSystem crs) throws FactoryException,
TransformException {
+            if (crs == null) {
+                throw new GazetteerException(Errors.format(Errors.Keys.UnspecifiedCRS));
+            }
+            CoordinateReferenceSystem horizontal = CRS.getHorizontalComponent(crs);
+            if (horizontal == null) {
+                horizontal = crs;
+            }
+            if (datum == null) {
+                datum = CommonCRS.forDatum(horizontal);
+            }
+            this.datum = datum;
+            if (horizontal instanceof ProjectedCRS) {
+                ProjectedCRS  projCRS = (ProjectedCRS) horizontal;
+                Projection projection = projCRS.getConversionFromBase();
+                final OperationMethod method = projection.getMethod();
+                if (IdentifiedObjects.isHeuristicMatchForName(method, TransverseMercator.NAME))
{
+                    crsZone = TransverseMercator.Zoner.UTM.zone(projection.getParameterValues());
+                } else if (IdentifiedObjects.isHeuristicMatchForName(method, PolarStereographicA.NAME))
{
+                    crsZone = NORTH_POLE * PolarStereographicA.isUPS(projection.getParameterValues());
+                } else {
+                    crsZone = 0;                                    // Neither UTM or UPS
projection.
+                }
+                if (crsZone != 0) {
+                    /*
+                     * Usually, the projected CRS already has (E,N) axis orientations with
metres units,
+                     * so we let 'toNormalized' to null. In the rarer cases where the CRS
axes do not
+                     * have the expected orientations and units, then we build a normalized
version of
+                     * that CRS and compute the transformation to that CRS.
+                     */
+                    final DefaultProjectedCRS userAxisOrder = DefaultProjectedCRS.castOrCopy(projCRS);
+                    projCRS = userAxisOrder.forConvention(AxesConvention.NORMALIZED);
+                    if (crs != horizontal || projCRS != userAxisOrder) {
+                        toNormalized = CRS.findOperation(crs, projCRS, null).getMathTransform();
+                        projection   = projCRS.getConversionFromBase();
+                        horizontal   = projCRS;
+                        crs          = projCRS;         // Next step in the chain of transformations.
+                    } else {
+                        toNormalized = null;            // ProjectedCRS (UTM or UPS) is already
normalized.
+                    }
+                } else {
+                    toNormalized = null;    // ProjectedCRS is neither UTM or UPS — will
need full reprojection.
+                }
+                /*
+                 * We will also need the transformation from the normalized projected CRS
to latitude and
+                 * longitude (in that order) in degrees. We can get this transform directly
from the
+                 * projected CRS if its base CRS already has the expected axis orientations
and units.
+                 */
+                if (crs == horizontal && Utilities.equalsIgnoreMetadata(projCRS.getBaseCRS(),
datum.geographic())) {
+                    toGeographic = projection.getMathTransform().inverse();
+                    return;
+                }
+            } else {
+                crsZone      = 0;
+                toNormalized = null;
+            }
+            toGeographic = CRS.findOperation(crs, datum.geographic(), null).getMathTransform();
+        }
+
+        /**
+         * Returns the band letter for the given latitude. It is caller responsibility to
ensure that the
+         * given latitude is between {@value #UTM_SOUTH_BOUNDS} and {@value #UTM_NORTH_BOUNDS}
inclusive.
+         * The returned letter will be one of {@code "CDEFGHJKLMNPQRSTUVWX"} (note that I
and O letters
+         * are excluded). All bands are 8° height except the X band which is 12° height.
+         *
+         * @param  φ  the latitude in degrees for which to get the band letter.
+         * @return the band letter for the given latitude.
+         */
+        static char latitudeBand(final double φ) {
+            int band = 'C' + (int) ((φ - TransverseMercator.Zoner.SOUTH_BOUNDS) / LATITUDE_BAND_HEIGHT);
+            if (band >= EXCLUDE_I && ++band >= EXCLUDE_O && ++band
== 'Y') {
+                band = 'X';         // Because the last latitude band ('X') is 12° height
instead of 8°.
+            }
+            assert band >= 'C' && band <= 'X' : band;
+            return (char) band;
+        }
+
+        /**
+         * Encodes the given position into a MGRS label. It is caller responsibility to ensure
that the
+         * position CRS is the same than the CRS specified at this {@code Encoder} creation
time.
+         *
+         * @param  owner      the {@code Coder} which own this {@code Encoder}.
+         * @param  position   the direct position to format as a MGRS label.
+         * @param  separator  the separator to insert between each component of the MGRS
identifier.
+         * @param  digits     number of digits to use for formatting the numerical part of
a MGRS label.
+         * @return the value of {@code buffer.toString()}.
+         */
+        String encode(final MilitaryGridReferenceSystem.Coder owner, DirectPosition position,
+                final String separator, final int digits) throws FactoryException, TransformException
+        {
+            final StringBuilder buffer = owner.buffer;
+            if (toNormalized != null) {
+                owner.normalized = position = toNormalized.transform(position, owner.normalized);
+            }
+            final DirectPosition geographic = toGeographic.transform(position, owner.geographic);
+            owner.geographic = geographic;                      // For reuse in next method
calls.
+            final double φ = geographic.getOrdinate(0);
+            if (φ >= TransverseMercator.Zoner.SOUTH_BOUNDS &&
+                φ <  TransverseMercator.Zoner.NORTH_BOUNDS)
+            {
+                /*
+                 * Universal Transverse Mercator (UTM) case.
+                 */
+                final double λ = geographic.getOrdinate(1);
+                final int zone = TransverseMercator.Zoner.UTM.zone(φ, λ);
+                final int sz   = MathFunctions.isNegative(φ) ? -zone : zone;
+                if (sz == 0) {
+                    // Zero value at this point is the result of NaN of infinite ordinate
value.
+                    throw new GazetteerException(Errors.format(Errors.Keys.NotANumber_1,
"longitude"));
+                }
+                if (sz != crsZone) {
+                    if (sz != actualZone) {
+                        actualZone   = 0;                           // In case an exception
is thrown on the next line.
+                        toActualZone = CRS.findOperation(datum.geographic(), datum.universal(φ,
λ), null).getMathTransform();
+                        actualZone   = sz;
+                    }
+                    owner.normalized = position = toActualZone.transform(geographic, owner.normalized);
+                }
+                buffer.setLength(0);
+                buffer.append(zone).append(separator).append(latitudeBand(φ));
+                if (digits >= 0) {
+                    /*
+                     * Specification said that 100,000-meters columns are lettered from A
through Z (omitting I and O)
+                     * starting at the 180° meridian, proceeding easterly for 18°, and
repeating for each 18° intervals.
+                     * Since a UTM zone is 6° width, a 18° interval is exactly 3 standard
UTM zones. Columns in zone 1
+                     * are A-H, zone 2 are J-R (skipping O), zone 3 are S-Z, then repeating
every 3 zones.
+                     */
+                    final double x = position.getOrdinate(0);
+                    final double y = position.getOrdinate(1);
+                    final double cx = Math.floor(x / GRID_SQUARE_SIZE);
+                    final double cy = Math.floor(y / GRID_SQUARE_SIZE);
+                    int col = (int) cx;
+                    if (col < 1 || col > 8) {
+                        /*
+                         * UTM northing values at the equator range from 166021 to 833979
meters approximatively
+                         * (WGS84 ellipsoid). Consequently 'cx' ranges from approximatively
1.66 to 8.34, so 'c'
+                         * should range from 1 to 8.
+                         */
+                        throw new GazetteerException(Errors.format(Errors.Keys.OutsideDomainOfValidity));
+                    }
+                    switch (zone % 3) {                          // First A-H sequence starts
at zone number 1.
+                        case 1: col += ('A' - 1); break;
+                        case 2: col += ('J' - 1); if (col >= EXCLUDE_O) col++; break;
+                        case 0: col += ('S' - 1); break;
+                    }
+                    /*
+                     * Rows in odd  zones are ABCDEFGHJKLMNPQRSTUV
+                     * Rows in even zones are FGHJKLMNPQRSTUVABCDE
+                     * Those 20 letters are repeated in a cycle.
+                     */
+                    int row = (int) cy;
+                    if ((zone & 1) == 0) {
+                        row += ('F' - 'A');
+                    }
+                    row = 'A' + (row % GRID_ROW_COUNT);
+                    if (row >= EXCLUDE_I && ++row >= EXCLUDE_O) row++;
+                    buffer.append(separator).append((char) col).append((char) row);
+                    /*
+                     * Numerical location at the given precision.
+                     * The specification requires us to truncate the number, not to round
it.
+                     */
+                    if (digits > 0) {
+                        final double precision = MathFunctions.pow10(METRE_PRECISION_DIGITS
- digits);
+                        append(buffer.append(separator), (int) ((x - cx * GRID_SQUARE_SIZE)
/ precision), digits);
+                        append(buffer.append(separator), (int) ((y - cy * GRID_SQUARE_SIZE)
/ precision), digits);
+                    }
+                }
+            } else {
+                /*
+                 * Universal Polar Stereographic (UPS) case.
+                 */
+                return null;    // TODO
+            }
+            return buffer.toString();
+        }
+
+        /**
+         * Appends the given value in the given buffer, padding with zero digits in order
to get
+         * the specified total amount of digits.
+         */
+        private static void append(final StringBuilder buffer, final int value, int digits)
throws TransformException {
+            if (value >= 0) {
+                final int p = buffer.length();
+                digits -= (buffer.append(value).length() - p);
+                if (digits >= 0) {
+                    StringBuilders.repeat(buffer, p, '0', digits);
+                    return;
+                }
+            }
+            throw new TransformException(Errors.format(Errors.Keys.OutsideDomainOfValidity));
+        }
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystemTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystemTest.java?rev=1783778&r1=1783777&r2=1783778&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystemTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MilitaryGridReferenceSystemTest.java
[UTF-8] Mon Feb 20 15:38:45 2017
@@ -19,9 +19,9 @@ package org.apache.sis.referencing.gazet
 import org.opengis.referencing.operation.TransformException;
 import org.opengis.geometry.DirectPosition;
 import org.apache.sis.geometry.DirectPosition2D;
+import org.apache.sis.internal.referencing.provider.TransverseMercator;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.test.DependsOnMethod;
-import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
@@ -36,7 +36,6 @@ import static org.junit.Assert.*;
  * @version 0.8
  * @module
  */
-@DependsOn(MGRSEncoderTest.class)
 public final strictfp class MilitaryGridReferenceSystemTest extends TestCase {
     /**
      * Returns a coder instance to test.
@@ -46,6 +45,47 @@ public final strictfp class MilitaryGrid
     }
 
     /**
+     * Verifies relationship between static fields documented in {@link Encoder}.
+     */
+    @Test
+    public void verifyInvariants() {
+        assertEquals("GRID_SQUARE_SIZE",
+             StrictMath.pow(10, MilitaryGridReferenceSystem.METRE_PRECISION_DIGITS),
+                                MilitaryGridReferenceSystem.GRID_SQUARE_SIZE, STRICT);
+    }
+
+    /**
+     * Tests {@link MilitaryGridReferenceSystem.Encoder#latitudeBand(double)}.
+     */
+    @Test
+    public void testLatitudeBand() {
+        assertEquals("80°S", 'C', MilitaryGridReferenceSystem.Encoder.latitudeBand(-80));
+        assertEquals("45°N", 'T', MilitaryGridReferenceSystem.Encoder.latitudeBand( 45));
+        assertEquals("55°N", 'U', MilitaryGridReferenceSystem.Encoder.latitudeBand( 55));
+        assertEquals("56°N", 'V', MilitaryGridReferenceSystem.Encoder.latitudeBand( 56));
+        assertEquals("63°N", 'V', MilitaryGridReferenceSystem.Encoder.latitudeBand( 63));
+        assertEquals("64°N", 'W', MilitaryGridReferenceSystem.Encoder.latitudeBand( 64));
+        assertEquals("71°N", 'W', MilitaryGridReferenceSystem.Encoder.latitudeBand( 71));
+        assertEquals("72°N", 'X', MilitaryGridReferenceSystem.Encoder.latitudeBand( 72));
+        assertEquals("84°N", 'X', MilitaryGridReferenceSystem.Encoder.latitudeBand( 84));
+    }
+
+    /**
+     * Verifies that {@link Zoner#isNorway(double)} and {@link Zoner#isSvalbard(double)}
+     * are consistent with the latitude bands.
+     */
+    @Test
+    public void verifyZonerConsistency() {
+        for (double φ = TransverseMercator.Zoner.SOUTH_BOUNDS; φ < TransverseMercator.Zoner.NORTH_BOUNDS;
φ++) {
+            final String latitude = String.valueOf(φ);
+            final char band = MilitaryGridReferenceSystem.Encoder.latitudeBand(φ);
+            assertTrue  (latitude, band >= 'C' && band <= 'X');
+            assertEquals(latitude, band == 'V', TransverseMercator.Zoner.isNorway(φ));
+            assertEquals(latitude, band == 'X', TransverseMercator.Zoner.isSvalbard(φ));
+        }
+    }
+
+    /**
      * Tests encoding of various coordinates.
      *
      * @throws TransformException if an error occurred while computing the MGRS label.
@@ -62,14 +102,14 @@ public final strictfp class MilitaryGrid
         position.y = 4539239;
         assertEquals("32TNL8410239239", coder.encode(position));
         /*
-         * 82°N 10°W (UTM zone 29) — should instantiate a new MGRSEncoder.
+         * 82°N 10°W (UTM zone 29) — should instantiate a new MilitaryGridReferenceSystem.Encoder.
          */
         position.setCoordinateReferenceSystem(CommonCRS.WGS84.universal(82, -10));
         position.x =  484463;
         position.y = 9104963;
         assertEquals("29XMM8446304963", coder.encode(position));
         /*
-         * 41°S 10°E (UTM zone 32) — should reuse the MGRSEncoder created in first test.
+         * 41°S 10°E (UTM zone 32) — should reuse the Encoder created in first test.
          */
         position.setCoordinateReferenceSystem(CommonCRS.WGS84.universal(-41, 10));
         position.x =  584102;

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1783778&r1=1783777&r2=1783778&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
[UTF-8] Mon Feb 20 15:38:45 2017
@@ -245,7 +245,6 @@ import org.junit.BeforeClass;
     org.apache.sis.distance.LatLonPointRadiusTest.class,        // Pending refactoring in
a geometry package.
 
     // Referencing by identifiers
-    org.apache.sis.referencing.gazetteer.MGRSEncoderTest.class,
     org.apache.sis.referencing.gazetteer.MilitaryGridReferenceSystemTest.class,
 
     org.apache.sis.test.integration.DatumShiftTest.class,



Mime
View raw message