sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1783350 - in /sis/branches/JDK8: core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ core/sis-referencing/src/main/java/org/apache/sis/ref...
Date Fri, 17 Feb 2017 08:50:39 GMT
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();



Mime
View raw message