Author: desruisseaux
Date: Fri Feb 17 08:50:39 2017
New Revision: 1783350

URL: http://svn.apache.org/viewvc?rev=1783350&view=rev
Log:
Initial implementation of a CommonCRS.universal(φ,λ) method in replacement of 
CommonCRS.UTM(φ,λ) for handling the UPS cases.
https://issues.apache.org/jira/browse/SIS-353

Modified:
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PolarStereographicA.java
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/TransverseMercator.java
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
    
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/EPSGFactoryFallback.java
    
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/StandardDefinitions.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/MGRSEncoder.java
    
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/TransformTestCase.java
    
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/TransverseMercatorTest.java
    
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java
    
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/StandardDefinitionsTest.java
    
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java
    
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MGRSEncoderTest.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/referencing/operation/CoordinateOperationFinderTest.java
    
sis/branches/JDK8/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatReader.java

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java?rev=1783350&r1=1783349&r2=1783350&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/GeodeticObjectBuilder.java
 [UTF-8] Fri Feb 17 08:50:39 2017
@@ -45,6 +45,7 @@ import org.apache.sis.util.ArgumentCheck
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.referencing.provider.TransverseMercator;
+import org.apache.sis.internal.referencing.provider.PolarStereographicA;
 import org.apache.sis.measure.Latitude;
 import org.apache.sis.referencing.Builder;
 import org.apache.sis.referencing.CommonCRS;
@@ -230,18 +231,22 @@ public class GeodeticObjectBuilder exten
      *
      * <blockquote><table class="sis">
      *   <caption>Transverse Mercator parameters</caption>
-     *   <tr><th>Parameter name</th>                 <th>Value</th></tr>
+     *   <tr><th>Parameter name</th>                 <th>Parameter 
value</th></tr>
      *   <tr><td>Latitude of natural origin</td>     <td>Given latitude, 
snapped to 0° in the UTM case</td></tr>
      *   <tr><td>Longitude of natural origin</td>    <td>Given longitude, 
optionally snapped to a UTM zone</td></tr>
-     *   <tr><td>Scale factor at natural origin</td> <td>0.9996</td></tr>
-     *   <tr><td>False easting</td>                  <td>500000 
metres</td></tr>
+     *   <tr><td>Scale factor at natural origin</td> <td>0.9996 in UTM 
case</td></tr>
+     *   <tr><td>False easting</td>                  <td>500000 metres in UTM 
case</td></tr>
      *   <tr><td>False northing</td>                 <td>0 (North hemisphere) 
or 10000000 (South hemisphere) metres</td></tr>
      * </table></blockquote>
      *
      * Note that calculation of UTM zone contains special cases for Norway and 
Svalbard.
      * If not desired, those exceptions can be avoided by making sure that the 
given latitude is below 56°N.
      *
-     * @param  isUTM      if {@code true}, the given central meridian will be 
snapped to the central meridian of a UTM zone.
+     * <p>If the given {@code zoner} is {@link TransverseMercator.Zoner#ANY 
ANY}, then this method will use the given
+     * latitude and longitude verbatim (without snapping them to a zone) but 
will still use the UTM scale factor,
+     * false easting and false northing.
+     *
+     * @param  zoner      whether to use UTM or MTM zones, or {@code ANY} for 
using arbitrary central meridian.
      * @param  latitude   the latitude in the center of the desired projection.
      * @param  longitude  the longitude in the center of the desired 
projection.
      * @return {@code this}, for method calls chaining.
@@ -249,13 +254,45 @@ public class GeodeticObjectBuilder exten
      *
      * @see CommonCRS#UTM(double, double)
      */
-    public GeodeticObjectBuilder setTransverseMercator(boolean isUTM, double 
latitude, double longitude)
+    public GeodeticObjectBuilder 
setTransverseMercator(TransverseMercator.Zoner zoner, double latitude, double 
longitude)
             throws FactoryException
     {
         ArgumentChecks.ensureBetween("latitude",   Latitude.MIN_VALUE,     
Latitude.MAX_VALUE,     latitude);
         ArgumentChecks.ensureBetween("longitude", -Formulas.LONGITUDE_MAX, 
Formulas.LONGITUDE_MAX, longitude);
         setConversionMethod(TransverseMercator.NAME);
-        
setConversionName(TransverseMercator.Zoner.UTM.setParameters(parameters, isUTM, 
latitude, longitude));
+        setConversionName(zoner.setParameters(parameters, latitude, 
longitude));
+        return this;
+    }
+
+    /**
+     * Sets the operation method, parameters and conversion name for a Polar 
Stereographic projection.
+     * This convenience method delegates to the following methods:
+     *
+     * <ul>
+     *   <li>{@link #setConversionName(String)} with a name like 
<cite>"Universal Polar Stereographic North"</cite>,
+     *       depending on the argument given to this method.</li>
+     *   <li>{@link #setConversionMethod(String)} with the name of the Polar 
Stereographic (variant A) projection method.</li>
+     *   <li>{@link #setParameter(String, double, Unit)} for each of the 
parameters enumerated below:</li>
+     * </ul>
+     *
+     * <blockquote><table class="sis">
+     *   <caption>Universal Polar Stereographic parameters</caption>
+     *   <tr><th>Parameter name</th>                 <th>Parameter 
value</th></tr>
+     *   <tr><td>Latitude of natural origin</td>     <td>90°N or 90°S</td></tr>
+     *   <tr><td>Longitude of natural origin</td>    <td>0°</td></tr>
+     *   <tr><td>Scale factor at natural origin</td> <td>0.994</td></tr>
+     *   <tr><td>False easting</td>                  <td>2000000 
metres</td></tr>
+     *   <tr><td>False northing</td>                 <td>2000000 
metres</td></tr>
+     * </table></blockquote>
+     *
+     * @param  north  {@code true} for North pole, or {@code false} for South 
pole.
+     * @return {@code this}, for method calls chaining.
+     * @throws FactoryException if the operation method for the Polar 
Stereographic (variant A)
+     *         projection can not be obtained.
+     */
+    public GeodeticObjectBuilder setPolarStereographic(final boolean north) 
throws FactoryException {
+        setConversionMethod(PolarStereographicA.NAME);
+        setConversionName(PolarStereographicA.setParameters(parameters, 
north));
         return this;
     }
 

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PolarStereographicA.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PolarStereographicA.java?rev=1783350&r1=1783349&r2=1783350&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PolarStereographicA.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PolarStereographicA.java
 [UTF-8] Fri Feb 17 08:50:39 2017
@@ -110,6 +110,36 @@ public final class PolarStereographicA e
     }
 
     /**
+     * Sets the parameter values for a Universal Polar Stereographic projection
+     * and returns a suggested conversion name.
+     *
+     * <blockquote><table class="sis">
+     *   <caption>Universal Polar Stereographic parameters</caption>
+     *   <tr><th>Parameter name</th>                 <th>Value</th></tr>
+     *   <tr><td>Latitude of natural origin</td>     <td>90°N or 90°S</td></tr>
+     *   <tr><td>Longitude of natural origin</td>    <td>0°</td></tr>
+     *   <tr><td>Scale factor at natural origin</td> <td>0.994</td></tr>
+     *   <tr><td>False easting</td>                  <td>2000000 
metres</td></tr>
+     *   <tr><td>False northing</td>                 <td>2000000 
metres</td></tr>
+     * </table></blockquote>
+     *
+     * @param  group  the parameters for which to set the values.
+     * @param  north  {@code true} for North pole, or {@code false} for South 
pole.
+     * @return a name like <cite>"Universal Polar Stereographic North"</cite>,
+     *         depending on the arguments given to this method.
+     *
+     * @since 0.8
+     */
+    public static String setParameters(final ParameterValueGroup group, final 
boolean north) {
+        group.parameter(Constants.LATITUDE_OF_ORIGIN).setValue(north ? 
Latitude.MAX_VALUE : Latitude.MIN_VALUE, Units.DEGREE);
+        group.parameter(Constants.CENTRAL_MERIDIAN)  .setValue(0,       
Units.DEGREE);
+        group.parameter(Constants.SCALE_FACTOR)      .setValue(0.994,   
Units.UNITY);
+        group.parameter(Constants.FALSE_EASTING)     .setValue(2000000, 
Units.METRE);
+        group.parameter(Constants.FALSE_NORTHING)    .setValue(2000000, 
Units.METRE);
+        return "Universal Polar Stereographic " + (north ? "North" : "South");
+    }
+
+    /**
      * If the given parameter values are those of a Universal Polar 
Stereographic projection,
      * returns -1 for South pole or +1 for North pole. Otherwise returns 0. It 
is caller's
      * responsibility to verify that the operation method is {@value #NAME}.

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/TransverseMercator.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/TransverseMercator.java?rev=1783350&r1=1783349&r2=1783350&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/TransverseMercator.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/TransverseMercator.java
 [UTF-8] Fri Feb 17 08:50:39 2017
@@ -141,8 +141,8 @@ public final class TransverseMercator ex
      */
     public static enum Zoner {
         /**
-         * Computes zones for the Universal Transverse Mercator (UTM) 
projections.
-         * This computation includes special cases for Norway and Svalbard.
+         * Universal Transverse Mercator (UTM) projection zones.
+         * The zone computation includes special cases for Norway and Svalbard.
          *
          * <blockquote><table class="sis">
          *   <caption>Universal Transverse Mercator parameters</caption>
@@ -174,7 +174,7 @@ public final class TransverseMercator ex
         },
 
         /**
-         * Computes zones for the Modified Transverse Mercator (MTM) 
projections.
+         * Modified Transverse Mercator (MTM) projection zones.
          * This projection is used in Canada only.
          *
          * <blockquote><table class="sis">
@@ -187,7 +187,17 @@ public final class TransverseMercator ex
          *   <tr><td>False northing</td>                 <td>0 metres</td></tr>
          * </table></blockquote>
          */
-        MTM(-51.5, -3, 0.9999, 304800, Double.NaN);
+        MTM(-51.5, -3, 0.9999, 304800, Double.NaN),
+
+        /**
+         * Like UTM, but allows <cite>latitude of origin</cite> and 
<cite>central meridian</cite> to be anywhere.
+         * The given central meridian is not snapped to the UTM zone center 
and no special case is applied for
+         * Norway or Svalbard.
+         *
+         * <p>This zoner matches the behavior of {@code AUTO(2):42002} 
authority code specified in the
+         * OGC <cite>Web Map Service</cite> (WMS) specification.</p>
+         */
+        ANY(Longitude.MIN_VALUE, 6, 0.9996, 500000, 10000000);
 
         /**
          * Longitude of the beginning of zone 1. This is the westmost 
longitude if {@link #width} is positive,
@@ -244,26 +254,28 @@ public final class TransverseMercator ex
          * </table></blockquote>
          *
          * @param  group      the parameters for which to set the values.
-         * @param  zoned      {@code true} for snapping the given 
latitude/longitude to a zone.
          * @param  latitude   the latitude in the center of the desired 
projection.
          * @param  longitude  the longitude in the center of the desired 
projection.
          * @return a name like <cite>"Transverse Mercator"</cite> or 
<cite>"UTM zone 10N"</cite>,
          *         depending on the arguments given to this method.
          */
-        public final String setParameters(final ParameterValueGroup group,
-                final boolean zoned, double latitude, double longitude)
-        {
+        public final String setParameters(final ParameterValueGroup group, 
double latitude, double longitude) {
             final boolean isSouth = MathFunctions.isNegative(latitude);
             int zone = zone(latitude, longitude);
-            if (zoned) {
-                latitude = 0;
+            String name;
+            if (this == ANY) {
+                name = "UTM";
+                if (latitude != 0 || longitude != centralMeridian(zone)) {
+                    name = NAME;
+                    zone = 0;
+                }
+            } else {
+                name      = name();
+                latitude  = 0;
                 longitude = centralMeridian(zone);
-            } else if (longitude != centralMeridian(zone)) {
-                zone = 0;
             }
-            String name = NAME;
             if (zone != 0) {
-                name = name() + " zone " + zone + (isSouth ? 'S' : 'N');
+                name = name + " zone " + zone + (isSouth ? 'S' : 'N');
             }
             group.parameter(Constants.LATITUDE_OF_ORIGIN).setValue(latitude,  
Units.DEGREE);
             group.parameter(Constants.CENTRAL_MERIDIAN)  .setValue(longitude, 
Units.DEGREE);
@@ -350,5 +362,15 @@ public final class TransverseMercator ex
         public static boolean isSvalbard(final double φ) {
             return (φ >= 72) && (φ < 84);
         }
+
+        /**
+         * Southernmost bound of the first latitude band ({@code 'C'}), 
inclusive.
+         */
+        public static final double SOUTH_BOUNDS = -80;
+
+        /**
+         * Northernmost bound of the last latitude band ({@code 'X'}), 
exclusive.
+         */
+        public static final double NORTH_BOUNDS = 84;
     }
 }

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java?rev=1783350&r1=1783349&r2=1783350&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/CRS.java
 [UTF-8] Fri Feb 17 08:50:39 2017
@@ -145,23 +145,29 @@ public final class CRS extends Static {
      *
      * <blockquote><table class="sis">
      *   <caption>Minimal set of supported authority codes</caption>
-     *   <tr><th>Code</th>      <th>Enum</th>                            
<th>CRS Type</th>      <th>Description</th></tr>
-     *   <tr><td>CRS:27</td>    <td>{@link CommonCRS#NAD27  NAD27}</td>  
<td>Geographic</td>    <td>Like EPSG:4267 except for (<var>longitude</var>, 
<var>latitude</var>) axis order</td></tr>
-     *   <tr><td>CRS:83</td>    <td>{@link CommonCRS#NAD83  NAD83}</td>  
<td>Geographic</td>    <td>Like EPSG:4269 except for (<var>longitude</var>, 
<var>latitude</var>) axis order</td></tr>
-     *   <tr><td>CRS:84</td>    <td>{@link CommonCRS#WGS84  WGS84}</td>  
<td>Geographic</td>    <td>Like EPSG:4326 except for (<var>longitude</var>, 
<var>latitude</var>) axis order</td></tr>
-     *   <tr><td>EPSG:4047</td> <td>{@link CommonCRS#SPHERE SPHERE}</td> 
<td>Geographic</td>    <td>GRS 1980 Authalic Sphere</td></tr>
-     *   <tr><td>EPSG:4230</td> <td>{@link CommonCRS#ED50   ED50}</td>   
<td>Geographic</td>    <td>European Datum 1950</td></tr>
-     *   <tr><td>EPSG:4258</td> <td>{@link CommonCRS#ETRS89 ETRS89}</td> 
<td>Geographic</td>    <td>European Terrestrial Reference Frame 1989</td></tr>
-     *   <tr><td>EPSG:4267</td> <td>{@link CommonCRS#NAD27  NAD27}</td>  
<td>Geographic</td>    <td>North American Datum 1927</td></tr>
-     *   <tr><td>EPSG:4269</td> <td>{@link CommonCRS#NAD83  NAD83}</td>  
<td>Geographic</td>    <td>North American Datum 1983</td></tr>
-     *   <tr><td>EPSG:4322</td> <td>{@link CommonCRS#WGS72  WGS72}</td>  
<td>Geographic</td>    <td>World Geodetic System 1972</td></tr>
-     *   <tr><td>EPSG:4326</td> <td>{@link CommonCRS#WGS84  WGS84}</td>  
<td>Geographic</td>    <td>World Geodetic System 1984</td></tr>
-     *   <tr><td>EPSG:4936</td> <td>{@link CommonCRS#ETRS89 ETRS89}</td> 
<td>Geocentric</td>    <td>European Terrestrial Reference Frame 1989</td></tr>
-     *   <tr><td>EPSG:4937</td> <td>{@link CommonCRS#ETRS89 ETRS89}</td> 
<td>Geographic 3D</td> <td>European Terrestrial Reference Frame 1989</td></tr>
-     *   <tr><td>EPSG:4978</td> <td>{@link CommonCRS#WGS84  WGS84}</td>  
<td>Geocentric</td>    <td>World Geodetic System 1984</td></tr>
-     *   <tr><td>EPSG:4979</td> <td>{@link CommonCRS#WGS84  WGS84}</td>  
<td>Geographic 3D</td> <td>World Geodetic System 1984</td></tr>
-     *   <tr><td>EPSG:4984</td> <td>{@link CommonCRS#WGS72  WGS72}</td>  
<td>Geocentric</td>    <td>World Geodetic System 1972</td></tr>
-     *   <tr><td>EPSG:4985</td> <td>{@link CommonCRS#WGS72  WGS72}</td>  
<td>Geographic 3D</td> <td>World Geodetic System 1972</td></tr>
+     *   <tr><th>Code</th>      <th>Enum</th>                            
<th>CRS Type</th>        <th>Description</th></tr>
+     *   <tr><td>CRS:27</td>    <td>{@link CommonCRS#NAD27  NAD27}</td>  
<td>Geographic</td>      <td>Like EPSG:4267 except for (<var>longitude</var>, 
<var>latitude</var>) axis order</td></tr>
+     *   <tr><td>CRS:83</td>    <td>{@link CommonCRS#NAD83  NAD83}</td>  
<td>Geographic</td>      <td>Like EPSG:4269 except for (<var>longitude</var>, 
<var>latitude</var>) axis order</td></tr>
+     *   <tr><td>CRS:84</td>    <td>{@link CommonCRS#WGS84  WGS84}</td>  
<td>Geographic</td>      <td>Like EPSG:4326 except for (<var>longitude</var>, 
<var>latitude</var>) axis order</td></tr>
+     *   <tr><td>EPSG:4047</td> <td>{@link CommonCRS#SPHERE SPHERE}</td> 
<td>Geographic</td>      <td>GRS 1980 Authalic Sphere</td></tr>
+     *   <tr><td>EPSG:4230</td> <td>{@link CommonCRS#ED50   ED50}</td>   
<td>Geographic</td>      <td>European Datum 1950</td></tr>
+     *   <tr><td>EPSG:4258</td> <td>{@link CommonCRS#ETRS89 ETRS89}</td> 
<td>Geographic</td>      <td>European Terrestrial Reference Frame 1989</td></tr>
+     *   <tr><td>EPSG:4267</td> <td>{@link CommonCRS#NAD27  NAD27}</td>  
<td>Geographic</td>      <td>North American Datum 1927</td></tr>
+     *   <tr><td>EPSG:4269</td> <td>{@link CommonCRS#NAD83  NAD83}</td>  
<td>Geographic</td>      <td>North American Datum 1983</td></tr>
+     *   <tr><td>EPSG:4322</td> <td>{@link CommonCRS#WGS72  WGS72}</td>  
<td>Geographic</td>      <td>World Geodetic System 1972</td></tr>
+     *   <tr><td>EPSG:4326</td> <td>{@link CommonCRS#WGS84  WGS84}</td>  
<td>Geographic</td>      <td>World Geodetic System 1984</td></tr>
+     *   <tr><td>EPSG:4936</td> <td>{@link CommonCRS#ETRS89 ETRS89}</td> 
<td>Geocentric</td>      <td>European Terrestrial Reference Frame 1989</td></tr>
+     *   <tr><td>EPSG:4937</td> <td>{@link CommonCRS#ETRS89 ETRS89}</td> 
<td>Geographic 3D</td>   <td>European Terrestrial Reference Frame 1989</td></tr>
+     *   <tr><td>EPSG:4978</td> <td>{@link CommonCRS#WGS84  WGS84}</td>  
<td>Geocentric</td>      <td>World Geodetic System 1984</td></tr>
+     *   <tr><td>EPSG:4979</td> <td>{@link CommonCRS#WGS84  WGS84}</td>  
<td>Geographic 3D</td>   <td>World Geodetic System 1984</td></tr>
+     *   <tr><td>EPSG:4984</td> <td>{@link CommonCRS#WGS72  WGS72}</td>  
<td>Geocentric</td>      <td>World Geodetic System 1972</td></tr>
+     *   <tr><td>EPSG:4985</td> <td>{@link CommonCRS#WGS72  WGS72}</td>  
<td>Geographic 3D</td>   <td>World Geodetic System 1972</td></tr>
+     *   <tr><td>EPSG:5041</td> <td>{@link CommonCRS#WGS84  WGS84}</td>  
<td>Projected</td>       <td>WGS 84 / UPS North (E,N)</td></tr>
+     *   <tr><td>EPSG:5042</td> <td>{@link CommonCRS#WGS84  WGS84}</td>  
<td>Projected</td>       <td>WGS 84 / UPS South (E,N)</td></tr>
+     *   <tr><td>EPSG:322##</td><td>{@link CommonCRS#WGS72  WGS72}</td>  
<td>Projected</td>       <td>WGS 72 / UTM zone ##N</td></tr>
+     *   <tr><td>EPSG:323##</td><td>{@link CommonCRS#WGS72  WGS72}</td>  
<td>Projected</td>       <td>WGS 72 / UTM zone ##S</td></tr>
+     *   <tr><td>EPSG:326##</td><td>{@link CommonCRS#WGS84  WGS84}</td>  
<td>Projected</td>       <td>WGS 84 / UTM zone ##N</td></tr>
+     *   <tr><td>EPSG:327##</td><td>{@link CommonCRS#WGS84  WGS84}</td>  
<td>Projected</td>       <td>WGS 84 / UTM zone ##S</td></tr>
      *   <tr><td>EPSG:5715</td> <td>{@link CommonCRS.Vertical#DEPTH 
DEPTH}</td> <td>Vertical</td> <td>Mean Sea Level depth</td></tr>
      *   <tr><td>EPSG:5714</td> <td>{@link CommonCRS.Vertical#MEAN_SEA_LEVEL 
MEAN_SEA_LEVEL}</td> <td>Vertical</td> <td>Mean Sea Level height</td></tr>
      * </table></blockquote>

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=1783350&r1=1783349&r2=1783350&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] Fri Feb 17 08:50:39 2017
@@ -19,7 +19,6 @@ package org.apache.sis.referencing;
 import java.util.Map;
 import java.util.Date;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.logging.Level;
 import java.util.logging.LogRecord;
 import javax.measure.Unit;
@@ -150,8 +149,8 @@ public enum CommonCRS {
      *   <tr><th>UTM zones:</th>               <td>1 to 60 in North and South 
hemispheres</td></tr>
      * </table></blockquote>
      */
-    WGS84((short) 4326, (short) 4979, (short) 4978, (short) 6326, (short) 
7030,     // Geodetic info
-          (short) 32600, (short) 32700, (byte) 1, (byte) 60),                  
     // UTM info
+    WGS84((short) 4326, (short) 4979, (short) 4978, (short) 6326, (short) 
7030,             // Geodetic info
+          (short) 5041, (short) 5042, (short) 32600, (short) 32700, (byte) 1, 
(byte) 60),   // UPS and UTM info
 
     /**
      * World Geodetic System 1972.
@@ -168,8 +167,8 @@ public enum CommonCRS {
      *   <tr><th>UTM zones:</th>               <td>1 to 60 in North and South 
hemispheres</td></tr>
      * </table></blockquote>
      */
-    WGS72((short) 4322, (short) 4985, (short) 4984, (short) 6322, (short) 
7043,     // Geodetic info
-          (short) 32200, (short) 32300, (byte) 1, (byte) 60),                  
     // UTM info
+    WGS72((short) 4322, (short) 4985, (short) 4984, (short) 6322, (short) 
7043,             // Geodetic info
+          (short) 0, (short) 0, (short) 32200, (short) 32300, (byte) 1, (byte) 
60),         // UPS and UTM info
 
     /**
      * North American Datum 1983.
@@ -194,8 +193,8 @@ public enum CommonCRS {
      * The <cite>Web Map Server</cite> {@code "CRS:83"} authority code uses 
the NAD83 datum,
      * while the {@code "IGNF:MILLER"} authority code uses the GRS80 
datum.</div>
      */
-    NAD83((short) 4269, (short) 0, (short) 0, (short) 6269, (short) 7019,      
     // Geodetic info
-          (short) 26900, (short) 0, (byte) 1, (byte) 23),                      
     // UTM info
+    NAD83((short) 4269, (short) 0, (short) 0, (short) 6269, (short) 7019,      
             // Geodetic info
+          (short) 0, (short) 0, (short) 26900, (short) 0, (byte) 1, (byte) 
23),             // UPS and UTM info
 
     /**
      * North American Datum 1927.
@@ -212,8 +211,8 @@ public enum CommonCRS {
      *   <tr><th>UTM zones:</th>               <td>1 to 22 in the North 
hemisphere</td></tr>
      * </table></blockquote>
      */
-    NAD27((short) 4267, (short) 0, (short) 0, (short) 6267, (short) 7008,      
     // Geodetic info
-          (short) 26700, (short) 0, (byte) 1, (byte) 22),                      
     // UTM info
+    NAD27((short) 4267, (short) 0, (short) 0, (short) 6267, (short) 7008,      
             // Geodetic info
+          (short) 0, (short) 0, (short) 26700, (short) 0, (byte) 1, (byte) 
22),             // UPS and UTM info
 
     /**
      * European Terrestrial Reference System 1989.
@@ -237,8 +236,8 @@ public enum CommonCRS {
      * The <cite>Web Map Server</cite> {@code "CRS:83"} authority code uses 
the NAD83 datum,
      * while the {@code "IGNF:MILLER"} authority code uses the GRS80 
datum.</div>
      */
-    ETRS89((short) 4258, (short) 4937, (short) 4936, (short) 6258, (short) 
7019,    // Geodetic info
-           (short) 25800, (short) 0, (byte) 28, (byte) 37),                    
     // UTM info
+    ETRS89((short) 4258, (short) 4937, (short) 4936, (short) 6258, (short) 
7019,            // Geodetic info
+           (short) 0, (short) 0, (short) 25800, (short) 0, (byte) 28, (byte) 
37),           // UPS and UTM info
 
     /**
      * European Datum 1950.
@@ -255,8 +254,8 @@ public enum CommonCRS {
      *   <tr><th>UTM zones:</th>               <td>28 to 38 in the North 
hemisphere</td></tr>
      * </table></blockquote>
      */
-    ED50((short) 4230, (short) 0, (short) 0, (short) 6230, (short) 7022,       
     // Geodetic info
-           (short) 23000, (short) 0, (byte) 28, (byte) 38),                    
     // UTM info
+    ED50((short) 4230, (short) 0, (short) 0, (short) 6230, (short) 7022,       
             // Geodetic info
+         (short) 0, (short) 0, (short) 23000, (short) 0, (byte) 28, (byte) 
38),             // UPS and UTM info
 
     /**
      * Unspecified datum based upon the GRS 1980 Authalic Sphere. Spheres use 
a simpler algorithm for
@@ -274,8 +273,8 @@ public enum CommonCRS {
      *
      * @see 
org.apache.sis.referencing.datum.DefaultEllipsoid#getAuthalicRadius()
      */
-    SPHERE((short) 4047, (short) 0, (short) 0, (short) 6047, (short) 7048,     
     // Geodetic info
-           (short) 0, (short) 0, (byte) 0, (byte) 0);                          
     // UTM info
+    SPHERE((short) 4047, (short) 0, (short) 0, (short) 6047, (short) 7048,     
             // Geodetic info
+           (short) 0, (short) 0, (short) 0, (short) 0, (byte) 0, (byte) 0);    
             // UPS and UTM info
 
     /**
      * The enum for the default CRS.
@@ -317,6 +316,11 @@ public enum CommonCRS {
     final short ellipsoid;
 
     /**
+     * EPSG codes of Universal Polar Stereographic projections, North and 
South cases.
+     */
+    final short northUPS, southUPS;
+
+    /**
      * EPSG codes of pseudo "UTM zone zero" (North case and South case), or 0 
if none.
      */
     final short northUTM, southUTM;
@@ -362,12 +366,21 @@ public enum CommonCRS {
     private transient volatile GeocentricCRS cachedSpherical;
 
     /**
-     * The Universal Transverse Mercator projections, created when first 
needed.
-     * All accesses to this map shall be synchronized on {@code cachedUTM}.
+     * The Universal Transverse Mercator (UTM) or Universal Polar 
Stereographic (UPS) projections,
+     * created when first needed. The UPS projections are arbitrarily given 
zone numbers
+     * {@value #POLAR} and -{@value #POLAR} for North and South poles 
respectively.
      *
-     * @see #UTM(double, double)
+     * <p>All accesses to this map shall be synchronized on {@code 
cachedProjections}.</p>
+     *
+     * @see #universal(double, double)
+     */
+    private final Map<Integer,ProjectedCRS> cachedProjections;
+
+    /**
+     * The special zone number used as key in {@link #cachedProjections} for 
polar stereographic projections.
+     * Must be outside the range of UTM zone numbers.
      */
-    private final Map<Integer,ProjectedCRS> cachedUTM;
+    private static final int POLAR = 90;
 
     /**
      * Creates a new constant for the given EPSG or SIS codes.
@@ -379,18 +392,20 @@ public enum CommonCRS {
      * @param ellipsoid   the EPSG code for the ellipsoid.
      */
     private CommonCRS(final short geographic, final short geo3D, final short 
geocentric, final short datum, final short ellipsoid,
-            final short northUTM, final short southUTM, final byte firstZone, 
final byte lastZone)
+            final short northUPS, final short southUPS, final short northUTM, 
final short southUTM, final byte firstZone, final byte lastZone)
     {
         this.geographic = geographic;
         this.geocentric = geocentric;
         this.geo3D      = geo3D;
         this.datum      = datum;
         this.ellipsoid  = ellipsoid;
+        this.northUPS   = northUPS;
+        this.southUPS   = southUPS;
         this.northUTM   = northUTM;
         this.southUTM   = southUTM;
         this.firstZone  = firstZone;
         this.lastZone   = lastZone;
-        cachedUTM = new HashMap<>();
+        cachedProjections = new HashMap<>();
     }
 
     /**
@@ -410,14 +425,14 @@ public enum CommonCRS {
     /**
      * Invoked by when the cache needs to be cleared after a classpath change.
      */
-    @SuppressWarnings("NestedSynchronizedStatement")    // Safe because 
cachedUTM never call any method of 'this'.
+    @SuppressWarnings("NestedSynchronizedStatement")    // Safe because 
cachedProjections never call any method of 'this'.
     synchronized void clear() {
         cached           = null;
         cachedGeo3D      = null;
         cachedNormalized = null;
         cachedGeocentric = null;
-        synchronized (cachedUTM) {
-            cachedUTM.clear();
+        synchronized (cachedProjections) {
+            cachedProjections.clear();
         }
     }
 
@@ -959,25 +974,50 @@ public enum CommonCRS {
     /**
      * Returns a Universal Transverse Mercator (UTM) projection for the zone 
containing the given point.
      * There is a total of 120 UTM zones, with 60 zones in the North 
hemisphere and 60 zones in the South hemisphere.
+     *
+     * @param  latitude  a latitude in the desired UTM projection zone.
+     * @param  longitude a longitude in the desired UTM projection zone.
+     * @return a Universal Transverse Mercator projection for the zone 
containing the given point.
+     *
+     * @since 0.7
+     *
+     * @deprecated Generalized by {@link #universal(double, double)},
+     *             which can also return a UPS projection when appropriate.
+     */
+    @Deprecated
+    public ProjectedCRS UTM(final double latitude, final double longitude) {
+        return universal(Math.max(-45, Math.min(45, latitude)), longitude);
+    }
+
+    /**
+     * Returns a Universal Transverse Mercator (UTM) or a Universal Polar 
Stereographic (UPS) projection
+     * for the zone containing the given point.
+     * There is a total of 120 UTM zones, with 60 zones in the North 
hemisphere and 60 zones in the South hemisphere.
      * The projection zone is determined from the arguments as below:
      *
      * <ul class="verbose">
-     *   <li>The sign of the <var>latitude</var> argument determines the 
hemisphere:
-     *       North for positive latitudes (including positive zero) or
-     *       South for negative latitudes (including negative zero).
-     *       The latitude magnitude is ignored, except for the special cases 
documented below
-     *       and for ensuring that the latitude is inside the [-90 … 90]° 
range.</li>
-     *   <li>The value of the <var>longitude</var> argument determines the 
6°-width zone,
-     *       numbered from 1 for the zone starting at 180°W up to 60 for the 
zone finishing at 180°E.
-     *       Longitudes outside the [-180 … 180]° range will be rolled as 
needed before to compute the zone.</li>
-     *   <li>Calculation of UTM zone involves two special cases (if those 
special cases are not desired,
-     *       they can be avoided by making sure that the given latitude is 
below 56°N):
-     *     <ul>
-     *       <li>Between 56°N and 64°N, zone 32 is widened to 9° (at the 
expense of zone 31)
-     *           to accommodate southwest Norway.</li>
-     *       <li>Between 72°N and 84°N, zones 33 and 35 are widened to 12° to 
accommodate Svalbard.
-     *           To compensate for these 12° wide zones, zones 31 and 37 are 
widened to 9° and
-     *           zones 32, 34, and 36 are eliminated.</li>
+     *   <li>If the <var>latitude</var> argument is less than 80°S or equal or 
greater than 84°N,
+     *       then a <cite>Universal Polar Stereographic</cite> projection is 
created.</li>
+     *   <li>Otherwise a <cite>Universal Transverse Mercator</cite> projection 
is created as below:
+     *     <ul class="verbose">
+     *       <li>The sign of the <var>latitude</var> argument determines the 
hemisphere:
+     *           North for positive latitudes (including positive zero) or
+     *           South for negative latitudes (including negative zero).
+     *           The latitude magnitude is ignored, except for the special 
cases documented below
+     *           and for ensuring that the latitude is inside the [-90 … 90]° 
range.</li>
+     *       <li>The value of the <var>longitude</var> argument determines the 
6°-width zone,
+     *           numbered from 1 for the zone starting at 180°W up to 60 for 
the zone finishing at 180°E.
+     *           Longitudes outside the [-180 … 180]° range will be rolled as 
needed before to compute the zone.</li>
+     *       <li>Calculation of UTM zone involves two special cases (if those 
special cases are not desired,
+     *           they can be avoided by making sure that the given latitude is 
below 56°N):
+     *         <ul>
+     *           <li>Between 56°N and 64°N, zone 32 is widened to 9° (at the 
expense of zone 31)
+     *               to accommodate southwest Norway.</li>
+     *           <li>Between 72°N and 84°N, zones 33 and 35 are widened to 12° 
to accommodate Svalbard.
+     *               To compensate for these 12° wide zones, zones 31 and 37 
are widened to 9° and
+     *               zones 32, 34, and 36 are eliminated.</li>
+     *         </ul>
+     *       </li>
      *     </ul>
      *   </li>
      * </ul>
@@ -985,13 +1025,32 @@ public enum CommonCRS {
      * The map projection uses the following parameters:
      *
      * <blockquote><table class="sis">
-     *   <caption>Universal Transverse Mercator (UTM) parameters</caption>
-     *   <tr><th>Parameter name</th>                 <th>UTM parameter 
value</th></tr>
-     *   <tr><td>Latitude of natural origin</td>     <td>0°</td></tr>
-     *   <tr><td>Longitude of natural origin</td>    <td>Central meridian of 
the UTM zone containing the given longitude</td></tr>
-     *   <tr><td>Scale factor at natural origin</td> <td>0.9996</td></tr>
-     *   <tr><td>False easting</td>                  <td>500 000 
metres</td></tr>
-     *   <tr><td>False northing</td>                 <td>0 (North hemisphere) 
or 10 000 000 (South hemisphere) metres</td></tr>
+     *   <caption>Universal Transverse Mercator (UTM) and Universal Polar 
Stereographic (UPS) projection parameters</caption>
+     *   <tr>
+     *     <th>Parameter name</th>
+     *     <th>UTM parameter value</th>
+     *     <th>UPS parameter value</th>
+     *   </tr><tr>
+     *     <td>Latitude of natural origin</td>
+     *     <td>0°</td>
+     *     <td>90°N or 90°S depending on the sign of given latitude</td>
+     *   </tr><tr>
+     *     <td>Longitude of natural origin</td>
+     *     <td>Central meridian of the UTM zone containing the given 
longitude</td>
+     *     <td>0°</td>
+     *   </tr><tr>
+     *     <td>Scale factor at natural origin</td>
+     *     <td>0.9996</td>
+     *     <td>0.994</td>
+     *   </tr><tr>
+     *     <td>False easting</td>
+     *     <td>500 000 metres</td>
+     *     <td>2 000 000 metres</td>
+     *   </tr><tr>
+     *     <td>False northing</td>
+     *     <td>0 (North hemisphere) or 10 000 000 (South hemisphere) 
metres</td>
+     *     <td>2 000 000 metres</td>
+     *   </tr>
      * </table></blockquote>
      *
      * The coordinate system axes are (Easting, Northing) in metres.
@@ -1001,59 +1060,83 @@ public enum CommonCRS {
      * This order is for consistency with the non-normalized {@linkplain 
#geographic() geographic} CRS
      * of all items in this {@code CommonCRS} enumeration.</div>
      *
-     * @param  latitude  a latitude in the desired UTM projection zone.
-     * @param  longitude a longitude in the desired UTM projection zone.
-     * @return a Universal Transverse Mercator projection for the zone 
containing the given point.
+     * @param  latitude  a latitude in the desired UTM or UPS projection zone.
+     * @param  longitude a longitude in the desired UTM or UPS projection zone.
+     * @return a Universal Transverse Mercator or Polar Stereographic 
projection for the zone containing the given point.
      *
-     * @since 0.7
+     * @since 0.8
      */
-    public ProjectedCRS UTM(final double latitude, final double longitude) {
+    public ProjectedCRS universal(final double latitude, final double 
longitude) {
         ArgumentChecks.ensureBetween("latitude",   Latitude.MIN_VALUE,     
Latitude.MAX_VALUE,     latitude);
         ArgumentChecks.ensureBetween("longitude", -Formulas.LONGITUDE_MAX, 
Formulas.LONGITUDE_MAX, longitude);
         final boolean isSouth = MathFunctions.isNegative(latitude);
-        final int zone = TransverseMercator.Zoner.UTM.zone(latitude, 
longitude);
+        final boolean isUTM   = latitude >= 
TransverseMercator.Zoner.SOUTH_BOUNDS
+                             && latitude <  
TransverseMercator.Zoner.NORTH_BOUNDS;
+        final int zone = isUTM ? TransverseMercator.Zoner.UTM.zone(latitude, 
longitude) : POLAR;
         final Integer key = isSouth ? -zone : zone;
         ProjectedCRS crs;
-        synchronized (cachedUTM) {
-            crs = cachedUTM.get(key);
+        synchronized (cachedProjections) {
+            crs = cachedProjections.get(key);
         }
         if (crs == null) {
+            /*
+             * Requested CRS has not been previously created, or the cache has 
been cleared.
+             * Before to create the CRS explicitely, try to get it from the 
EPSG database.
+             * Using the EPSG geodetic dataset when possible gives us more 
information,
+             * like the aliases and area of validity.
+             */
             int code = 0;
-            if (zone >= firstZone && zone <= lastZone) {
+            if (!isUTM) {
+                code = Short.toUnsignedInt(isSouth ? southUPS : northUPS);
+            } else if (zone >= firstZone && zone <= lastZone) {
                 code = Short.toUnsignedInt(isSouth ? southUTM : northUTM);
-                if (code != 0) {
-                    code += zone;
-                    final GeodeticAuthorityFactory factory = factory();
-                    if (factory != null) try {
-                        return 
factory.createProjectedCRS(String.valueOf(code));
-                    } catch (FactoryException e) {
-                        failure(this, "UTM", e, code);
-                    }
+            }
+            if (code != 0) {
+                if (isUTM) code += zone;
+                final GeodeticAuthorityFactory factory = factory();
+                if (factory != null) try {
+                    return factory.createProjectedCRS(String.valueOf(code));
+                } catch (FactoryException e) {
+                    failure(this, "universal", e, code);
                 }
             }
             /*
-             * All constants defined in this enumeration use the same 
coordinate system, EPSG:4400.
-             * We will arbitrarily create this CS only for a frequently 
created CRS, and share that
-             * CS instance for all other constants.
+             * At this point we couldn't use the EPSG dataset; we have to 
create the CRS ourselves.
+             * All constants defined in this enumeration use the same 
coordinate system (EPSG:4400)
+             * except for the polar regions. We will arbitrarily create the CS 
only for a frequently
+             * used datum, then share that CS instance for all other constants.
              */
             CartesianCS cs = null;
-            synchronized (DEFAULT.cachedUTM) {
-                final Iterator<ProjectedCRS> it = 
DEFAULT.cachedUTM.values().iterator();
-                if (it.hasNext()) {
-                    cs = it.next().getCoordinateSystem();
+            if (isUTM) {
+                synchronized (DEFAULT.cachedProjections) {
+                    for (final Map.Entry<Integer,ProjectedCRS> entry : 
DEFAULT.cachedProjections.entrySet()) {
+                        if (Math.abs(entry.getKey()) != POLAR) {
+                            cs = entry.getValue().getCoordinateSystem();
+                            break;
+                        }
+                    }
                 }
             }
+            /*
+             * If we didn't found a Coordinate System for EPSG:4400, or if the 
CS that we needed was
+             * for another EPSG code (polar cases), delegate to the WGS84 
datum or create the CS now.
+             *
+             *   EPSG:4400 — Cartesian 2D CS. Axes: easting, northing (E,N). 
Orientations: east, north. UoM: m.
+             *   EPSG:1026 — Cartesian 2D CS for UPS north. Axes: E,N. 
Orientations: E along 90°E meridian, N along 180°E meridian. UoM: m.
+             *   EPSG:1027 — Cartesian 2D CS for UPS south. Axes: E,N. 
Orientations: E along 90°E, N along 0°E meridians. UoM: m.
+             */
             if (cs == null) {
                 if (this != DEFAULT) {
-                    cs = DEFAULT.UTM(latitude, 
longitude).getCoordinateSystem();
+                    cs = DEFAULT.universal(latitude, 
longitude).getCoordinateSystem();
                 } else {
-                    cs = (CartesianCS) 
StandardDefinitions.createCoordinateSystem(Constants.EPSG_PROJECTED_CS);
+                    cs = (CartesianCS) 
StandardDefinitions.createCoordinateSystem(
+                            isUTM ? Constants.EPSG_PROJECTED_CS : isSouth ? 
(short) 1027 : (short) 1026);
                 }
             }
-            crs = StandardDefinitions.createUTM(code, geographic(), latitude, 
longitude, cs);
+            crs = StandardDefinitions.createUniversal(code, geographic(), 
isUTM, latitude, longitude, cs);
             final ProjectedCRS other;
-            synchronized (cachedUTM) {
-                other = cachedUTM.putIfAbsent(key, crs);
+            synchronized (cachedProjections) {
+                other = cachedProjections.putIfAbsent(key, crs);
             }
             if (other != null) {
                 return other;

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/EPSGFactoryFallback.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/EPSGFactoryFallback.java?rev=1783350&r1=1783349&r2=1783350&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/EPSGFactoryFallback.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/EPSGFactoryFallback.java
 [UTF-8] Fri Feb 17 08:50:39 2017
@@ -45,6 +45,7 @@ import org.apache.sis.util.resources.Voc
 import org.apache.sis.util.iso.DefaultNameSpace;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.Debug;
+import org.apache.sis.measure.Latitude;
 
 
 /**
@@ -138,10 +139,14 @@ final class EPSGFactoryFallback extends
                 add(codes, crs.geographic);
                 add(codes, crs.geo3D);
             }
-            if (projected && (crs.northUTM != 0 || crs.southUTM != 0)) {
-                for (int zone = crs.firstZone; zone <= crs.lastZone; zone++) {
-                    if (crs.northUTM != 0) 
codes.add(Integer.toString(crs.northUTM + zone));
-                    if (crs.southUTM != 0) 
codes.add(Integer.toString(crs.southUTM + zone));
+            if (projected) {
+                add(codes, crs.northUPS);
+                add(codes, crs.southUPS);
+                if (crs.northUTM != 0 || crs.southUTM != 0) {
+                    for (int zone = crs.firstZone; zone <= crs.lastZone; 
zone++) {
+                        if (crs.northUTM != 0) 
codes.add(Integer.toString(crs.northUTM + zone));
+                        if (crs.southUTM != 0) 
codes.add(Integer.toString(crs.southUTM + zone));
+                    }
                 }
             }
         }
@@ -246,13 +251,19 @@ final class EPSGFactoryFallback extends
                     final double latitude;
                     int zone;
                     if (crs.northUTM != 0 && (zone = n - crs.northUTM) >= 
crs.firstZone && zone <= crs.lastZone) {
-                        latitude = +1;
+                        latitude = +1;          // Any north latitude below 
56°N (because of Norway exception) is okay
                     } else if (crs.southUTM != 0 && (zone = n - crs.southUTM) 
>= crs.firstZone && zone <= crs.lastZone) {
-                        latitude = -1;
+                        latitude = -1;          // Any south latitude above 
80°S (because of UPS south case) is okay.
+                    } else if (n == crs.northUPS) {
+                        latitude = Latitude.MAX_VALUE;
+                        zone     = 30;                  // Any random UTM zone 
is okay.
+                    } else if (n == crs.southUPS) {
+                        latitude = Latitude.MIN_VALUE;
+                        zone     = 30;                  // Any random UTM zone 
is okay.
                     } else {
                         continue;
                     }
-                    return crs.UTM(latitude, 
TransverseMercator.Zoner.UTM.centralMeridian(zone));
+                    return crs.universal(latitude, 
TransverseMercator.Zoner.UTM.centralMeridian(zone));
                 }
             }
             if ((kind & (DATUM | CRS)) != 0) {

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/StandardDefinitions.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/StandardDefinitions.java?rev=1783350&r1=1783349&r2=1783350&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/StandardDefinitions.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/StandardDefinitions.java
 [UTF-8] Fri Feb 17 08:50:39 2017
@@ -41,12 +41,14 @@ import org.opengis.util.NoSuchIdentifier
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.metadata.AxisNames;
 import org.apache.sis.internal.referencing.provider.TransverseMercator;
+import org.apache.sis.internal.referencing.provider.PolarStereographicA;
 import org.apache.sis.metadata.iso.extent.Extents;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.referencing.datum.DefaultEllipsoid;
 import org.apache.sis.referencing.datum.DefaultPrimeMeridian;
 import org.apache.sis.referencing.datum.DefaultGeodeticDatum;
 import org.apache.sis.referencing.datum.DefaultVerticalDatum;
+import org.apache.sis.referencing.cs.CoordinateSystems;
 import org.apache.sis.referencing.cs.DefaultVerticalCS;
 import org.apache.sis.referencing.cs.DefaultCartesianCS;
 import org.apache.sis.referencing.cs.DefaultSphericalCS;
@@ -126,29 +128,31 @@ final class StandardDefinitions {
     }
 
     /**
-     * Returns the operation method for Transverse Mercator projection using 
the SIS factory implementation.
-     * This method restricts the factory to SIS implementation instead than 
arbitrary factory in order to meet
-     * the contract saying that {@link CommonCRS} methods should never fail.
+     * Creates a Universal Transverse Mercator (UTM) or a Universal Polar 
Stereographic (UPS) projected CRS
+     * using the Apache SIS factory implementation. This method restricts the 
factory to SIS implementation
+     * instead than arbitrary factory in order to meet the contract saying 
that {@link CommonCRS} methods
+     * should never fail.
      *
      * @param code       the EPSG code, or 0 if none.
      * @param baseCRS    the geographic CRS on which the projected CRS is 
based.
-     * @param latitude   a latitude in the zone of the desired projection, to 
be snapped to 0°.
+     * @param isUTM      {@code true} for UTM or {@code false} for UPS. Note: 
redundant with the given latitude.
+     * @param latitude   a latitude in the zone of the desired projection, to 
be snapped to 0°, 90°S or 90°N.
      * @param longitude  a longitude in the zone of the desired projection, to 
be snapped to UTM central meridian.
      * @param derivedCS  the projected coordinate system.
      */
-    static ProjectedCRS createUTM(final int code, final GeographicCRS baseCRS,
+    static ProjectedCRS createUniversal(final int code, final GeographicCRS 
baseCRS, final boolean isUTM,
             final double latitude, final double longitude, final CartesianCS 
derivedCS)
     {
         final OperationMethod method;
         try {
-            method = DefaultFactories.forBuildin(MathTransformFactory.class,
-                                          DefaultMathTransformFactory.class)
-                    .getOperationMethod(TransverseMercator.NAME);
+            method = DefaultFactories.forBuildin(MathTransformFactory.class, 
DefaultMathTransformFactory.class)
+                                .getOperationMethod(isUTM ? 
TransverseMercator.NAME : PolarStereographicA.NAME);
         } catch (NoSuchIdentifierException e) {
-            throw new IllegalStateException(e);     // Should not happen with 
SIS implementation.
+            throw new IllegalStateException(e);                     // Should 
not happen with SIS implementation.
         }
         final ParameterValueGroup parameters = 
method.getParameters().createValue();
-        String name = TransverseMercator.Zoner.UTM.setParameters(parameters, 
true, latitude, longitude);
+        String name = isUTM ? 
TransverseMercator.Zoner.UTM.setParameters(parameters, latitude, longitude)
+                            : PolarStereographicA.setParameters(parameters, 
latitude >= 0);
         final DefaultConversion conversion = new 
DefaultConversion(properties(0, name, null, false), method, null, parameters);
 
         name = baseCRS.getName().getCode() + " / " + name;
@@ -313,16 +317,17 @@ final class StandardDefinitions {
     @SuppressWarnings("fallthrough")
     static CoordinateSystem createCoordinateSystem(final short code) {
         final String name;
-        final int dim;                  // Number of dimension.
+        int type = 0;                   // 0= Cartesian (default), 1= 
Spherical, 2= Ellipsoidal
+        int dim = 2;                    // Number of dimension, default to 2.
         short axisCode;                 // Code of first axis + dim (or code 
after the last axis).
-        boolean isCartesian = false;
-        boolean isSpherical = false;
         switch (code) {
-            case 6422: name = "Ellipsoidal 2D"; dim = 2; axisCode = 108; break;
-            case 6423: name = "Ellipsoidal 3D"; dim = 3; axisCode = 111; break;
-            case 6404: name = "Spherical";      dim = 3; axisCode =  63; 
isSpherical = true; break;
-            case 6500: name = "Earth centred";  dim = 3; axisCode = 118; 
isCartesian = true; break;
-            case 4400: name = "Cartesian 2D";   dim = 2; axisCode =   3; 
isCartesian = true; break;
+            case 6422: name = "Ellipsoidal 2D"; type = 2;          axisCode =  
108; break;
+            case 6423: name = "Ellipsoidal 3D"; type = 2; dim = 3; axisCode =  
111; break;
+            case 6404: name = "Spherical";      type = 1; dim = 3; axisCode =  
 63; break;
+            case 6500: name = "Earth centred";            dim = 3; axisCode =  
118; break;
+            case 4400: name = "Cartesian 2D";                      axisCode =  
  3; break;
+            case 1026: name = "Cartesian 2D for UPS north";        axisCode = 
1067; break;
+            case 1027: name = "Cartesian 2D for UPS south";        axisCode = 
1059; break;
             default:   throw new AssertionError(code);
         }
         final Map<String,?> properties = properties(code, name, null, false);
@@ -334,20 +339,13 @@ final class StandardDefinitions {
             case 1:  xAxis = createAxis(--axisCode);
             case 0:  break;
         }
-        if (isCartesian) {
-            if (zAxis != null) {
-                return new DefaultCartesianCS(properties, xAxis, yAxis, zAxis);
-            } else {
-                return new DefaultCartesianCS(properties, xAxis, yAxis);
-            }
-        } else if (isSpherical) {
-            return new DefaultSphericalCS(properties, xAxis, yAxis, zAxis);
-        } else {
-            if (zAxis != null) {
-                return new DefaultEllipsoidalCS(properties, xAxis, yAxis, 
zAxis);
-            } else {
-                return new DefaultEllipsoidalCS(properties, xAxis, yAxis);
-            }
+        switch (type) {
+            default: throw new AssertionError(type);
+            case 0:  return (zAxis != null) ? new DefaultCartesianCS  
(properties, xAxis, yAxis, zAxis)
+                                            : new DefaultCartesianCS  
(properties, xAxis, yAxis);
+            case 1:  return                   new DefaultSphericalCS  
(properties, xAxis, yAxis, zAxis);
+            case 2:  return (zAxis != null) ? new 
DefaultEllipsoidalCS(properties, xAxis, yAxis, zAxis)
+                                            : new 
DefaultEllipsoidalCS(properties, xAxis, yAxis);
         }
     }
 
@@ -367,12 +365,10 @@ final class StandardDefinitions {
         switch (code) {
             case 1:    name = "Easting";
                        abrv = "E";
-                       unit = Units.METRE;
                        dir  = AxisDirection.EAST;
                        break;
             case 2:    name = "Northing";
                        abrv = "N";
-                       unit = Units.METRE;
                        dir  = AxisDirection.NORTH;
                        break;
             case 60:   name = "Spherical latitude";
@@ -393,7 +389,6 @@ final class StandardDefinitions {
                        break;
             case 62:   name = "Geocentric radius";
                        abrv = "R";                          // See 
HardCodedAxes.GEOCENTRIC_RADIUS in tests.
-                       unit = Units.METRE;
                        dir  = AxisDirection.UP;
                        rm   = RangeMeaning.EXACT;
                        min  = 0;
@@ -440,6 +435,23 @@ final class StandardDefinitions {
                        abrv = "Z";
                        dir  = AxisDirection.GEOCENTRIC_Z;
                        break;
+            case 1057: // Actually no axis allocated by EPSG here, but 
createCoordinateSystem(1027) needs this number.
+            case 1056: name = "Easting";
+                       abrv = "E";
+                       dir  = 
CoordinateSystems.directionAlongMeridian(AxisDirection.NORTH, 90);
+                       break;
+            case 1058: name = "Northing";
+                       abrv = "N";
+                       dir  = 
CoordinateSystems.directionAlongMeridian(AxisDirection.NORTH, 0);
+                       break;
+            case 1065: name = "Easting";
+                       abrv = "E";
+                       dir  = 
CoordinateSystems.directionAlongMeridian(AxisDirection.SOUTH, 90);
+                       break;
+            case 1066: name = "Northing";
+                       abrv = "N";
+                       dir  = 
CoordinateSystems.directionAlongMeridian(AxisDirection.SOUTH, 180);
+                       break;
             default:   throw new AssertionError(code);
         }
         final Map<String,Object> properties = properties(code, name, null, 
false);

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=1783350&r1=1783349&r2=1783350&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] Fri Feb 17 08:50:39 2017
@@ -43,6 +43,7 @@ import org.opengis.referencing.cs.Cartes
 import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.datum.DatumFactory;
 import org.opengis.referencing.datum.EngineeringDatum;
+import org.apache.sis.internal.referencing.provider.TransverseMercator.Zoner;
 import org.apache.sis.internal.referencing.GeodeticObjectBuilder;
 import org.apache.sis.internal.referencing.Resources;
 import org.apache.sis.metadata.iso.citation.Citations;
@@ -60,8 +61,6 @@ import org.apache.sis.util.resources.Err
 import org.apache.sis.util.iso.DefaultNameSpace;
 import org.apache.sis.util.iso.SimpleInternationalString;
 
-import static 
org.apache.sis.internal.referencing.provider.TransverseMercator.Zoner.UTM;
-
 
 /**
  * Creates coordinate reference systems in the "{@code OGC}", "{@code CRS}" or 
{@code "AUTO(2)"} namespaces.
@@ -587,7 +586,7 @@ public class CommonAuthorityFactory exte
              * 42005: WGS 84 / Auto Mollweide         —   defined by 
"Central_Meridian" only.
              */
             case 42001: isUTM  = true; break;
-            case 42002: isUTM  = (latitude == 0) && 
(UTM.centralMeridian(UTM.zone(0, longitude)) == longitude); break;
+            case 42002: isUTM  = (latitude == 0) && 
(Zoner.UTM.centralMeridian(Zoner.UTM.zone(0, longitude)) == longitude); break;
             case 42003: method = "Orthographic";       param = 
Constants.LATITUDE_OF_ORIGIN;  break;
             case 42004: method = "Equirectangular";    param = 
Constants.STANDARD_PARALLEL_1; break;
             case 42005: method = "Mollweide";                                  
               break;
@@ -598,9 +597,9 @@ public class CommonAuthorityFactory exte
          * enumeration if possible because CommonCRS will itself delegate to 
the EPSG factory if possible.
          */
         final CommonCRS datum = CommonCRS.WGS84;
-        final GeographicCRS baseCRS;
-        final ProjectedCRS crs;
-        CartesianCS cs;
+        final GeographicCRS baseCRS;                // To be set, directly or 
indirectly, to WGS84.geographic().
+        final ProjectedCRS crs;                     // Temporary UTM 
projection, for extracting other properties.
+        CartesianCS cs;                             // Coordinate system with 
(E,N) axes in metres.
         try {
             if (isUTM != null && isUTM) {
                 crs = datum.UTM(latitude, longitude);
@@ -640,10 +639,10 @@ public class CommonAuthorityFactory exte
              */
             final GeodeticObjectBuilder builder = new GeodeticObjectBuilder();
             if (isUTM != null) {
-                if (isUTM) {
+                if (isUTM && crs != null) {
                     builder.addName(crs.getName());
                 } // else default to the conversion name, which is "Transverse 
Mercator".
-                builder.setTransverseMercator(isUTM, latitude, longitude);
+                builder.setTransverseMercator(isUTM ? Zoner.UTM : Zoner.ANY, 
latitude, longitude);
             } else {
                 builder.setConversionMethod(method)
                        .addName(PROJECTION_NAMES[projection - 
FIRST_PROJECTION_CODE])

Modified: 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MGRSEncoder.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MGRSEncoder.java?rev=1783350&r1=1783349&r2=1783350&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MGRSEncoder.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/gazetteer/MGRSEncoder.java
 [UTF-8] Fri Feb 17 08:50:39 2017
@@ -61,16 +61,6 @@ final class MGRSEncoder {
     private static final double LATITUDE_BAND_HEIGHT = 8;
 
     /**
-     * Southernmost bound of the first latitude band ({@code 'C'}).
-     */
-    static final double UTM_SOUTH_BOUNDS = -80;
-
-    /**
-     * Northernmost bound of the last latitude band ({@code 'X'}).
-     */
-    static final double UTM_NORTH_BOUNDS = 84;
-
-    /**
      * Special {@link #crsZone} value for the UPS South (Universal Polar 
Stereographic) projection.
      */
     private static final int SOUTH_POLE = -1000;
@@ -244,7 +234,7 @@ final class MGRSEncoder {
      * @return the band letter for the given latitude.
      */
     static char latitudeBand(final double φ) {
-        int band = 'C' + (int) ((φ - UTM_SOUTH_BOUNDS) / LATITUDE_BAND_HEIGHT);
+        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°.
         }
@@ -272,7 +262,9 @@ final class MGRSEncoder {
         final DirectPosition geographic = toGeographic.transform(position, 
owner.geographic);
         owner.geographic = geographic;                      // For reuse in 
next method calls.
         final double φ = geographic.getOrdinate(0);
-        if (φ >= UTM_SOUTH_BOUNDS && φ <= UTM_NORTH_BOUNDS) {
+        if (φ >= TransverseMercator.Zoner.SOUTH_BOUNDS &&
+            φ <  TransverseMercator.Zoner.NORTH_BOUNDS)
+        {
             /*
              * Universal Transverse Mercator (UTM) case.
              */
@@ -286,7 +278,7 @@ final class MGRSEncoder {
             if (sz != crsZone) {
                 if (sz != actualZone) {
                     actualZone   = 0;                           // In case an 
exception is thrown on the next line.
-                    toActualZone = CRS.findOperation(datum.geographic(), 
datum.UTM(φ, λ), null).getMathTransform();
+                    toActualZone = CRS.findOperation(datum.geographic(), 
datum.universal(φ, λ), null).getMathTransform();
                     actualZone   = sz;
                 }
                 owner.normalized = position = 
toActualZone.transform(geographic, owner.normalized);

Modified: 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/TransformTestCase.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/TransformTestCase.java?rev=1783350&r1=1783349&r2=1783350&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/TransformTestCase.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/TransformTestCase.java
 [UTF-8] Fri Feb 17 08:50:39 2017
@@ -90,7 +90,7 @@ public abstract strictfp class Transform
      */
     @Test
     public final void testTransform() throws FactoryException, 
TransformException {
-        final ProjectedCRS    targetCRS  = CommonCRS.WGS84.UTM(10, -123.5);
+        final ProjectedCRS    targetCRS  = CommonCRS.WGS84.universal(10, 
-123.5);
         final GeographicCRS   sourceCRS  = targetCRS.getBaseCRS();
         final Conversion      conversion = targetCRS.getConversionFromBase();
         final MathTransform2D transform  = (MathTransform2D) 
conversion.getMathTransform();
@@ -199,7 +199,7 @@ public abstract strictfp class Transform
     @Test
     @DependsOnMethod("testTransform")
     public final void testTransformNotOverPole() throws FactoryException, 
TransformException {
-        final ProjectedCRS  sourceCRS  = CommonCRS.WGS84.UTM(10, -3.5);
+        final ProjectedCRS  sourceCRS  = CommonCRS.WGS84.universal(10, -3.5);
         final GeographicCRS targetCRS  = sourceCRS.getBaseCRS();
         final Conversion    conversion = 
inverse(sourceCRS.getConversionFromBase());
         final G rectangle = createFromExtremums(sourceCRS, 199980, 4490220, 
309780, 4600020);

Modified: 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/TransverseMercatorTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/TransverseMercatorTest.java?rev=1783350&r1=1783349&r2=1783350&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/TransverseMercatorTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/TransverseMercatorTest.java
 [UTF-8] Fri Feb 17 08:50:39 2017
@@ -62,7 +62,7 @@ public final strictfp class TransverseMe
     }
 
     /**
-     * Tests {@link 
TransverseMercator.Zoner#setParameters(ParameterValueGroup, boolean, double, 
double)}
+     * Tests {@link 
TransverseMercator.Zoner#setParameters(ParameterValueGroup, double, double)}
      * followed by {@link TransverseMercator.Zoner#zone(ParameterValueGroup)}.
      */
     @Test
@@ -72,17 +72,17 @@ public final strictfp class TransverseMe
     })
     public void testSetParameters() {
         final ParameterValueGroup p = 
TransverseMercator.PARAMETERS.createValue();
-        assertEquals("UTM zone 10N", 
TransverseMercator.Zoner.UTM.setParameters(p, true, 0, -122));
+        assertEquals("UTM zone 10N", 
TransverseMercator.Zoner.UTM.setParameters(p, 0, -122));
         assertEquals(Constants.CENTRAL_MERIDIAN, -123, 
p.parameter(Constants.CENTRAL_MERIDIAN).doubleValue(), STRICT);
         assertEquals(Constants.FALSE_NORTHING, 0, 
p.parameter(Constants.FALSE_NORTHING).doubleValue(), STRICT);
         assertEquals("UTM.zone(parameters)", 10, 
TransverseMercator.Zoner.UTM.zone(p));
 
-        assertEquals("Transverse Mercator", 
TransverseMercator.Zoner.UTM.setParameters(p, false, 0, -122));
+        assertEquals("Transverse Mercator", 
TransverseMercator.Zoner.ANY.setParameters(p, 0, -122));
         assertEquals(Constants.CENTRAL_MERIDIAN, -122, 
p.parameter(Constants.CENTRAL_MERIDIAN).doubleValue(), STRICT);
         assertEquals(Constants.FALSE_NORTHING, 0, 
p.parameter(Constants.FALSE_NORTHING).doubleValue(), STRICT);
         assertEquals("UTM.zone(parameters)", 0, 
TransverseMercator.Zoner.UTM.zone(p));
 
-        assertEquals("UTM zone 10S", 
TransverseMercator.Zoner.UTM.setParameters(p, false, -0.0, -123));
+        assertEquals("UTM zone 10S", 
TransverseMercator.Zoner.ANY.setParameters(p, -0.0, -123));
         assertEquals(Constants.CENTRAL_MERIDIAN, -123, 
p.parameter(Constants.CENTRAL_MERIDIAN).doubleValue(), STRICT);
         assertEquals(Constants.FALSE_NORTHING, 10000000, 
p.parameter(Constants.FALSE_NORTHING).doubleValue(), STRICT);
         assertEquals("UTM.zone(parameters)", -10, 
TransverseMercator.Zoner.UTM.zone(p));

Modified: 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java?rev=1783350&r1=1783349&r2=1783350&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/CommonCRSTest.java
 [UTF-8] Fri Feb 17 08:50:39 2017
@@ -79,6 +79,8 @@ public final strictfp class CommonCRSTes
             assertNoCodeCollision(codes, crs, crs.geographic);
             assertNoCodeCollision(codes, crs, crs.geocentric);
             assertNoCodeCollision(codes, crs, crs.geo3D);
+            assertNoCodeCollision(codes, crs, crs.northUPS);
+            assertNoCodeCollision(codes, crs, crs.southUPS);
             for (int zone = crs.firstZone; zone <= crs.lastZone; zone++) {
                 if (crs.northUTM != 0) assertNoCodeCollision(codes, crs, 
crs.northUTM + zone);
                 if (crs.southUTM != 0) assertNoCodeCollision(codes, crs, 
crs.southUTM + zone);
@@ -276,20 +278,41 @@ public final strictfp class CommonCRSTes
     }
 
     /**
-     * Tests {@link CommonCRS#UTM(double, double)}.
+     * Tests {@link CommonCRS#universal(double, double)} with Universal 
Transverse Mercator (UTM) projections.
      *
      * @since 0.7
      */
     @Test
     @DependsOnMethod("testGeographic")
     public void testUTM() {
-        final ProjectedCRS crs = CommonCRS.WGS72.UTM(-45, -122);
+        final ProjectedCRS crs = CommonCRS.WGS72.universal(-45, -122);
         assertEquals("name", "WGS 72 / UTM zone 10S", crs.getName().getCode());
         final ParameterValueGroup pg = 
crs.getConversionFromBase().getParameterValues();
-        assertEquals(Constants.LATITUDE_OF_ORIGIN, -123, 
pg.parameter(Constants.CENTRAL_MERIDIAN).doubleValue(), STRICT);
-        assertEquals(Constants.FALSE_NORTHING, 10000000, 
pg.parameter(Constants.FALSE_NORTHING).doubleValue(),   STRICT);
-        assertSame("Expected a cached instance.", crs, 
CommonCRS.WGS72.UTM(-45, -122));
-        assertNotSame("Expected a new instance.", crs, 
CommonCRS.WGS72.UTM(+45, -122));
+        assertEquals(Constants.LATITUDE_OF_ORIGIN,    0, 
pg.parameter(Constants.LATITUDE_OF_ORIGIN).doubleValue(), STRICT);
+        assertEquals(Constants.CENTRAL_MERIDIAN,   -123, 
pg.parameter(Constants.CENTRAL_MERIDIAN)  .doubleValue(), STRICT);
+        assertEquals(Constants.FALSE_EASTING,    500000, 
pg.parameter(Constants.FALSE_EASTING)     .doubleValue(), STRICT);
+        assertEquals(Constants.FALSE_NORTHING, 10000000, 
pg.parameter(Constants.FALSE_NORTHING)    .doubleValue(), STRICT);
+        assertSame("Expected a cached instance.", crs, 
CommonCRS.WGS72.universal(-45, -122));
+        assertNotSame("Expected a new instance.", crs, 
CommonCRS.WGS72.universal(+45, -122));
+    }
+
+    /**
+     * Tests {@link CommonCRS#universal(double, double)} with Universal Polar 
Stereographic (UPS) projections.
+     *
+     * @since 0.8
+     */
+    @Test
+    @DependsOnMethod("testGeographic")
+    public void testUPS() {
+        final ProjectedCRS crs = CommonCRS.WGS72.universal(-85, -122);
+        assertEquals("name", "WGS 72 / Universal Polar Stereographic South", 
crs.getName().getCode());
+        final ParameterValueGroup pg = 
crs.getConversionFromBase().getParameterValues();
+        assertEquals(Constants.LATITUDE_OF_ORIGIN, -90, 
pg.parameter(Constants.LATITUDE_OF_ORIGIN).doubleValue(), STRICT);
+        assertEquals(Constants.CENTRAL_MERIDIAN,     0, 
pg.parameter(Constants.CENTRAL_MERIDIAN)  .doubleValue(), STRICT);
+        assertEquals(Constants.FALSE_EASTING,  2000000, 
pg.parameter(Constants.FALSE_EASTING)     .doubleValue(), STRICT);
+        assertEquals(Constants.FALSE_NORTHING, 2000000, 
pg.parameter(Constants.FALSE_NORTHING)    .doubleValue(), STRICT);
+        assertSame("Expected a cached instance.", crs, 
CommonCRS.WGS72.universal(-85, -122));
+        assertNotSame("Expected a new instance.", crs, 
CommonCRS.WGS72.universal(+85, -122));
     }
 
     /**

Modified: 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/StandardDefinitionsTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/StandardDefinitionsTest.java?rev=1783350&r1=1783349&r2=1783350&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/StandardDefinitionsTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/StandardDefinitionsTest.java
 [UTF-8] Fri Feb 17 08:50:39 2017
@@ -71,14 +71,15 @@ public final strictfp class StandardDefi
     }
 
     /**
-     * Tests {@link StandardDefinitions#createUTM(int, GeographicCRS, double, 
boolean, CartesianCS)}.
+     * Tests {@link StandardDefinitions#createUniversal(int, GeographicCRS, 
boolean, double, double, CartesianCS)}
+     * for a Universal Transverse Mercator (UTM) projection.
      *
      * @since 0.7
      */
     @Test
     @DependsOnMethod("testCreateGeographicCRS")
     public void testCreateUTM() {
-        final ProjectedCRS crs = StandardDefinitions.createUTM(32610, 
HardCodedCRS.WGS84, 15, -122, HardCodedCS.PROJECTED);
+        final ProjectedCRS crs = StandardDefinitions.createUniversal(32610, 
HardCodedCRS.WGS84, true, 15, -122, HardCodedCS.PROJECTED);
         assertEquals("name", "WGS 84 / UTM zone 10N", crs.getName().getCode());
         final ParameterValueGroup pg = 
crs.getConversionFromBase().getParameterValues();
         assertEquals(Constants.LATITUDE_OF_ORIGIN, -123, 
pg.parameter(Constants.CENTRAL_MERIDIAN).doubleValue(), STRICT);

Modified: 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java?rev=1783350&r1=1783349&r2=1783350&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/factory/sql/EPSGInstallerTest.java
 [UTF-8] Fri Feb 17 08:50:39 2017
@@ -209,7 +209,7 @@ public final strictfp class EPSGInstalle
              * This implies the creation of a coordinate operation.
              */
             final ProjectedCRS p = factory.createProjectedCRS("EPSG:32215");
-            assertTrue(Utilities.deepEquals(CommonCRS.WGS72.UTM(1, -93), p, 
ComparisonMode.DEBUG));
+            assertTrue(Utilities.deepEquals(CommonCRS.WGS72.universal(1, -93), 
p, ComparisonMode.DEBUG));
             /*
              * Get the authority codes. We choose a type that implies an SQL 
statement
              * with both "DEPRECATED" and "SHOW_CRS" conditions in their 
"WHERE" clause.

Modified: 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MGRSEncoderTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MGRSEncoderTest.java?rev=1783350&r1=1783349&r2=1783350&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MGRSEncoderTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/gazetteer/MGRSEncoderTest.java
 [UTF-8] Fri Feb 17 08:50:39 2017
@@ -64,7 +64,7 @@ public final strictfp class MGRSEncoderT
      */
     @Test
     public void verifyZonerConsistency() {
-        for (double φ = MGRSEncoder.UTM_SOUTH_BOUNDS; φ < 
MGRSEncoder.UTM_NORTH_BOUNDS; φ++) {
+        for (double φ = Zoner.SOUTH_BOUNDS; φ < Zoner.NORTH_BOUNDS; φ++) {
             final String latitude = String.valueOf(φ);
             final char band = MGRSEncoder.latitudeBand(φ);
             assertTrue  (latitude, band >= 'C' && band <= 'X');

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=1783350&r1=1783349&r2=1783350&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] Fri Feb 17 08:50:39 2017
@@ -56,21 +56,21 @@ public final strictfp class MilitaryGrid
         /*
          * 41°N 10°E (UTM zone 32)
          */
-        position.setCoordinateReferenceSystem(CommonCRS.WGS84.UTM(41, 10));
+        position.setCoordinateReferenceSystem(CommonCRS.WGS84.universal(41, 
10));
         position.x =  584102;
         position.y = 4539239;
         assertEquals("32TNL8410239239", coder.encode(position));
         /*
          * 82°N 10°W (UTM zone 29) — should instantiate a new MGRSEncoder.
          */
-        position.setCoordinateReferenceSystem(CommonCRS.WGS84.UTM(82, -10));
+        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.
          */
-        position.setCoordinateReferenceSystem(CommonCRS.WGS84.UTM(-41, 10));
+        position.setCoordinateReferenceSystem(CommonCRS.WGS84.universal(-41, 
10));
         position.x =  584102;
         position.y = 5460761;
         assertEquals("32GNV8410260761", coder.encode(position));
@@ -78,7 +78,7 @@ public final strictfp class MilitaryGrid
          * 82°N 10°E (UTM zone 32) — in this special case, zone 32 is replaced 
by zone 33.
          * Call to WGS84.UTM(φ,λ) needs to specify a smaller latitude for 
getting zone 32.
          */
-        position.setCoordinateReferenceSystem(CommonCRS.WGS84.UTM(40, 10));
+        position.setCoordinateReferenceSystem(CommonCRS.WGS84.universal(40, 
10));
         position.x =  515537;
         position.y = 9104963;
         assertEquals("33XVM2240708183", coder.encode(position));
@@ -103,7 +103,7 @@ public final strictfp class MilitaryGrid
     @DependsOnMethod("testEncoding")
     public void testPrecision() throws TransformException {
         final MilitaryGridReferenceSystem.Coder coder = coder();
-        final DirectPosition2D position = new 
DirectPosition2D(CommonCRS.WGS84.UTM(13, 103));
+        final DirectPosition2D position = new 
DirectPosition2D(CommonCRS.WGS84.universal(13, 103));
         position.x =  377299;
         position.y = 1483035;
         assertEquals("precision", 1, coder.getPrecision(), STRICT);
@@ -137,7 +137,7 @@ public final strictfp class MilitaryGrid
     @DependsOnMethod("testPrecision")
     public void testSeparator() throws TransformException {
         final MilitaryGridReferenceSystem.Coder coder = coder();
-        final DirectPosition2D position = new 
DirectPosition2D(CommonCRS.WGS84.UTM(13, 103));
+        final DirectPosition2D position = new 
DirectPosition2D(CommonCRS.WGS84.universal(13, 103));
         position.x =  377299;
         position.y = 1483035;
         assertEquals("separator", "", coder.getSeparator());

Modified: 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java?rev=1783350&r1=1783349&r2=1783350&view=diff
==============================================================================
--- 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
 [UTF-8] Fri Feb 17 08:50:39 2017
@@ -175,7 +175,7 @@ public final strictfp class CoordinateOp
         testIdentityTransform(CommonCRS.WGS84.geographic3D());
         testIdentityTransform(CommonCRS.WGS84.geocentric());
         testIdentityTransform(CommonCRS.WGS84.spherical());
-        testIdentityTransform(CommonCRS.WGS84.UTM(0, 0));
+        testIdentityTransform(CommonCRS.WGS84.universal(0, 0));
         testIdentityTransform(CommonCRS.Vertical.DEPTH.crs());
         testIdentityTransform(CommonCRS.Temporal.JULIAN.crs());
     }

Modified: 
sis/branches/JDK8/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatReader.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatReader.java?rev=1783350&r1=1783349&r2=1783350&view=diff
==============================================================================
--- 
sis/branches/JDK8/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatReader.java
 [UTF-8] (original)
+++ 
sis/branches/JDK8/storage/sis-earth-observation/src/main/java/org/apache/sis/storage/earthobservation/LandsatReader.java
 [UTF-8] Fri Feb 17 08:50:39 2017
@@ -904,7 +904,7 @@ final class LandsatReader {
          */
         if (datum != null) {
             if (utmZone > 0) {
-                metadata.add(datum.UTM(1, 
TransverseMercator.Zoner.UTM.centralMeridian(utmZone)));
+                metadata.add(datum.universal(1, 
TransverseMercator.Zoner.UTM.centralMeridian(utmZone)));
             }
             if (projection != null) {
                 final double sp = 
projection.parameter(Constants.STANDARD_PARALLEL_1).doubleValue();


Reply via email to