sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1783887 - in /sis/branches/JDK8/core/sis-referencing/src: main/java/org/apache/sis/referencing/ main/java/org/apache/sis/referencing/factory/ main/java/org/apache/sis/referencing/gazetteer/ test/java/org/apache/sis/referencing/gazetteer/
Date Tue, 21 Feb 2017 13:22:23 GMT
Author: desruisseaux
Date: Tue Feb 21 13:22:23 2017
New Revision: 1783887

URL: http://svn.apache.org/viewvc?rev=1783887&view=rev
Log:
Fix the correction which is applied when the coordinate is in the wrong latitude band.

Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java
    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

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java?rev=1783887&r1=1783886&r2=1783887&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CommonCRS.java
[UTF-8] Tue Feb 21 13:22:23 2017
@@ -986,7 +986,7 @@ public enum CommonCRS {
      */
     @Deprecated
     public ProjectedCRS UTM(final double latitude, final double longitude) {
-        return universal(Math.max(-45, Math.min(45, latitude)), longitude);
+        return universal(Math.signum(latitude), longitude);
     }
 
     /**
@@ -1022,9 +1022,15 @@ public enum CommonCRS {
      *   </li>
      * </ul>
      *
+     * <div class="note"><b>Tip:</b>
+     * for "straight" UTM zone calculation without any special case (neither Norway, Svalbard
or Universal Polar
+     * Stereographic projection), one can replace the {@code latitude} argument by {@code
Math.signum(latitude)}.
+     * For using a specific zone number, one can additionally replace the {@code longitude}
argument by
+     * {@code zone * 6 - 183}.</div>
+     *
      * The map projection uses the following parameters:
      *
-     * <blockquote><table class="sis">
+     * <table class="sis">
      *   <caption>Universal Transverse Mercator (UTM) and Universal Polar Stereographic
(UPS) projection parameters</caption>
      *   <tr>
      *     <th>Parameter name</th>
@@ -1051,7 +1057,7 @@ public enum CommonCRS {
      *     <td>0 (North hemisphere) or 10 000 000 (South hemisphere) metres</td>
      *     <td>2 000 000 metres</td>
      *   </tr>
-     * </table></blockquote>
+     * </table>
      *
      * The coordinate system axes are (Easting, Northing) in metres.
      *

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java?rev=1783887&r1=1783886&r2=1783887&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/CommonAuthorityFactory.java
[UTF-8] Tue Feb 21 13:22:23 2017
@@ -599,6 +599,9 @@ public class CommonAuthorityFactory exte
         /*
          * For the (Universal) Transverse Mercator case (AUTO:42001 and 42002), we delegate
to the CommonCRS
          * enumeration if possible because CommonCRS will itself delegate to the EPSG factory
if possible.
+         * The Math.signum(latitude) instruction is for preventing "AUTO:42001" to handle
the UTM special cases
+         * (Norway and Svalbard) or to switch on the Universal Polar Stereographic projection
for high latitudes,
+         * because the WMS specification does not said that we should.
          */
         final CommonCRS datum = CommonCRS.WGS84;
         final GeographicCRS baseCRS;                // To be set, directly or indirectly,
to WGS84.geographic().
@@ -606,7 +609,7 @@ public class CommonAuthorityFactory exte
         CartesianCS cs;                             // Coordinate system with (E,N) axes
in metres.
         try {
             if (isUTM != null && isUTM) {
-                crs = datum.universal(forceUTM(latitude), longitude);
+                crs = datum.universal(Math.signum(latitude), longitude);
                 if (factor == (isLegacy ? Constants.EPSG_METRE : 1)) {
                     return crs;
                 }
@@ -615,7 +618,7 @@ public class CommonAuthorityFactory exte
             } else {
                 cs = projectedCS;
                 if (cs == null) {
-                    crs = datum.universal(forceUTM(latitude), longitude);
+                    crs = datum.universal(Math.signum(latitude), longitude);
                     projectedCS = cs = crs.getCoordinateSystem();
                     baseCRS = crs.getBaseCRS();
                 } else {
@@ -687,17 +690,6 @@ public class CommonAuthorityFactory exte
     }
 
     /**
-     * Forces the given latitude in the range of UTM projections, excluding Norway and Svalbard
special cases.
-     * This method is used for preventing {@code "AUTO:42001"} to handle the UTM special
cases and to switch
-     * on the Universal Polar Stereographic projection for high latitudes, because the WMS
specification does
-     * not said that we should. However we could remove this method if we consider allowing
UTM special cases
-     * and UPS projections as an Apache SIS extension.
-     */
-    private static double forceUTM(final double latitude) {
-        return Math.max(-45, Math.min(45, latitude));
-    }
-
-    /**
      * Returns the "Computer display" reference system (CRS:1). This is rarely used.
      */
     private synchronized CoordinateReferenceSystem displayCRS() throws FactoryException {

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=1783887&r1=1783886&r2=1783887&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] Tue Feb 21 13:22:23 2017
@@ -343,8 +343,10 @@ public class MilitaryGridReferenceSystem
              */
             double φs = Double.NaN;
             int col = 1, row = 0;
+            boolean hasSquareIdentification = true;
             for (int part = 1; part <= 3; part++) {
                 if (part == 2 && i >= end) {
+                    hasSquareIdentification = false;
                     break;                                      // Allow to stop parsing
only after part 1.
                 }
                 i = nextComponent(reference, base, i, end);
@@ -395,19 +397,22 @@ public class MilitaryGridReferenceSystem
                 i = ni;
             }
             /*
-             * We need to create a UTM projection from (φ,λ) coordinates, not from UTM
zone,
-             * because there is special cases to take in account for Norway and Svalbard.
+             * Create a UTM projection for exactly the zone specified in the MGRS reference,
+             * regardless the Norway and Svalbard special cases. Then project an estimation
+             * of the (φ,λ) coordinate in order to get an estimation of the northing value.
+             * This estimation is needed because the 100 000-metres square identification
is
+             * insufficient; we may need to add some multiple of 2000 kilometres.
              */
             final double λ0 = TransverseMercator.Zoner.UTM.centralMeridian(zone);
-            final ProjectedCRS crs = datum.universal(φs, λ0);
+            final ProjectedCRS crs = datum.universal(Math.signum(φs), λ0);
             final DirectPosition2D pos = new DirectPosition2D(φs, λ0);
             final MathTransform projection = crs.getConversionFromBase().getMathTransform();
-            row += ((int) (projection.transform(pos, pos).getOrdinate(1)
-                    / (GRID_SQUARE_SIZE * GRID_ROW_COUNT))) * GRID_ROW_COUNT;
-
+            final double northing = Math.floor(projection.transform(pos, pos).getOrdinate(1)
+                                    / (GRID_SQUARE_SIZE * GRID_ROW_COUNT))
+                                    * (GRID_SQUARE_SIZE * GRID_ROW_COUNT);
             pos.setCoordinateReferenceSystem(crs);
             pos.x = col * GRID_SQUARE_SIZE;
-            pos.y = row * GRID_SQUARE_SIZE;
+            pos.y = row * GRID_SQUARE_SIZE + northing;
             if (i < end) {
                 /*
                  * If we have not yet reached the end of string, parse the numerical location.
@@ -446,18 +451,29 @@ public class MilitaryGridReferenceSystem
              * meridian (λ₀). But the (x,y) position that we just parsed is probably at
another longitude (λ), in
              * which case its northing value (y) is closer to the pole of its hemisphere.
The slight difference in
              * northing values can cause a change of 100 000-metres grid square. We detect
this case by converting
-             * (x,y) to geographic coordinates (φ,λ) and verifying if the result is in
the expected latitude band.
+             * (x,y) to geographic coordinates (φ,λ) and verifying if the result is in
the expected latitude band:
+             *
+             *  - In North hemisphere, we expect φ >= φs in all cases because φ value
is closest to equator at λ₀.
+             *    So if (φ - φs) is negative, this means that φ is too low and more northing
needs to be added.
+             *
+             *  - In South hemisphere, we expect φ <= φs + LATITUDE_BAND_HEIGHT in all
cases for similar reason
+             *    (the +LATITUDE_BAND_HEIGHT is for converting southernmost value φs into
northernmost value φn).
+             *    So if (φ - φs) > LATITUDE_BAND_HEIGHT, this means that φ is too high
and some northing needs to
+             *    be removed.
+             *
              * We also use this calculation for error detection, by verifying if the given
100 000-metres square
              * identification is consistent with grid zone designation.
              */
-            final MathTransform inverse = projection.inverse();
-            DirectPosition check = inverse.transform(pos, null);
-            final double sign = Math.signum(φs);
-            double error = (φs - check.getOrdinate(0)) / LATITUDE_BAND_HEIGHT;
-            if (error > 0) {
-                if (error < 1) {
-                    pos.y += sign * (GRID_SQUARE_SIZE * GRID_ROW_COUNT);
-                } else {
+            if (hasSquareIdentification) {
+                final MathTransform inverse = projection.inverse();
+                DirectPosition check = inverse.transform(pos, null);
+                double delta = truncateLastLatitudeBand(check.getOrdinate(0)) - φs;
+                if ((φs >= 0) ? (delta < 0) : (delta > LATITUDE_BAND_HEIGHT)) {
+                    pos.y += Math.signum(φs) * (GRID_SQUARE_SIZE * GRID_ROW_COUNT);
+                    check = inverse.transform(pos, check);
+                    delta = truncateLastLatitudeBand(check.getOrdinate(0)) - φs;
+                }
+                if (!(delta >= 0 && delta <= LATITUDE_BAND_HEIGHT)) {
                     throw new GazetteerException("Iconsistent MGRS reference.");    // TODO:
localize
                 }
             }
@@ -551,6 +567,18 @@ public class MilitaryGridReferenceSystem
                 * MathFunctions.pow10(METRE_PRECISION_DIGITS - (end - start));
     }
 
+    /**
+     * If the given latitude is inside the "extended area" of X band, pretend that we have
the maximal
+     * "normal area" latitude value instead. The intend is to hide the additional complexity
introduced
+     * by the fact that the X latitude band is 12° height while all other latitude bands
are 8° height.
+     */
+    static double truncateLastLatitudeBand(double φ) {
+        if (φ > 80 && φ < TransverseMercator.Zoner.NORTH_BOUNDS) {
+            φ = 80;
+        }
+        return φ;
+    }
+
 
 
 

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=1783887&r1=1783886&r2=1783887&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] Tue Feb 21 13:22:23 2017
@@ -166,8 +166,8 @@ public final strictfp class MilitaryGrid
 
         position = coder.decode("33XVM2240708183");
         assertSame("crs", CommonCRS.WGS84.universal(82, 10), position.getCoordinateReferenceSystem());
-//      assertEquals("Easting",   515537, position.getOrdinate(0), STRICT);
-//      assertEquals("Northing", 9104963, position.getOrdinate(1), STRICT);
+        assertEquals("Easting",   422407, position.getOrdinate(0), STRICT);
+        assertEquals("Northing", 9108183, position.getOrdinate(1), STRICT);
     }
 
     /**
@@ -259,6 +259,6 @@ public final strictfp class MilitaryGrid
         position = coder.decode("32T");
         assertEquals("32T", position, coder.decode("32/T"));
         assertEquals("Easting",   100000, position.getOrdinate(0), STRICT);
-//      assertEquals("Northing", 4000000, position.getOrdinate(1), STRICT);
+        assertEquals("Northing", 4000000, position.getOrdinate(1), STRICT);
     }
 }



Mime
View raw message