Author: desruisseaux
Date: Wed Jan 15 14:58:16 2014
New Revision: 1558411

URL: http://svn.apache.org/r1558411
Log:
Implements the AxesConversion.POSITIVE_RANGE case.

Modified:
    
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java
    
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AxesConvention.java
    
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/Normalizer.java
    
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/AbstractCSTest.java
    
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/CommonAxes.java
    
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/NormalizerTest.java

Modified: 
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java?rev=1558411&r1=1558410&r2=1558411&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java
 [UTF-8] Wed Jan 15 14:58:16 2014
@@ -189,14 +189,16 @@ public class AbstractCS extends Abstract
                 }
             }
             /*
-             * Ensures there is no axis along the same direction
-             * (e.g. two North axes, or an East and a West axis).
+             * Ensures there is no axis along the same direction (e.g. two 
North axes, or an East and a West axis).
+             * An exception to this rule is the time axis, since ISO 19107 
explicitely allows compound CRS to have
+             * more than one time axis. Such case happen in meteorological 
models.
              */
             final AxisDirection dir = AxisDirections.absolute(direction);
             if (!dir.equals(AxisDirection.OTHER)) {
                 for (int j=i; --j>=0;) {
                     final AxisDirection other = axes[j].getDirection();
-                    if (dir.equals(AxisDirections.absolute(other))) {
+                    final AxisDirection abs = AxisDirections.absolute(other);
+                    if (dir.equals(abs) && !abs.equals(AxisDirection.FUTURE)) {
                         throw new IllegalArgumentException(Errors.format(
                                 Errors.Keys.ColinearAxisDirections_2, 
direction, other));
                     }
@@ -336,7 +338,7 @@ public class AbstractCS extends Abstract
             switch (convention) {
                 case NORMALIZED:     cs = Normalizer.normalize(this, true);  
break;
                 case RIGHT_HANDED:   cs = Normalizer.normalize(this, false); 
break;
-                case POSITIVE_RANGE: cs = this; break; // TODO
+                case POSITIVE_RANGE: cs = Normalizer.shiftAxisRange(this);   
break;
                 default: throw new AssertionError(convention);
             }
             for (final AbstractCS existing : derived.values()) {

Modified: 
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AxesConvention.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AxesConvention.java?rev=1558411&r1=1558410&r2=1558411&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AxesConvention.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AxesConvention.java
 [UTF-8] Wed Jan 15 14:58:16 2014
@@ -45,8 +45,32 @@ import org.opengis.referencing.cs.Coordi
  * By default, SIS creates CRS with axis order as defined by the authority. 
Those CRS are created by calls to the
  * {@link org.apache.sis.referencing.CRS#forCode(String)} method. The actual 
axis order can be verified after the CRS
  * creation with {@code System.out.println(crs)}. If 
(<var>x</var>,<var>y</var>) axis order is wanted for compatibility
- * with older OGC specifications or other softwares, CRS forced to longitude 
first axis order can be created using the
- * {@link #NORMALIZED} enumeration value.</p>
+ * with older OGC specifications or other softwares, CRS forced to "longitude 
first" axis order can be created using the
+ * {@link #RIGHT_HANDED} or {@link #NORMALIZED} enumeration value.</p>
+ *
+ * {@section Normalized coordinate systems}
+ * The definition the <cite>normalized coordinate systems</cite> is somewhat 
fuzzy.
+ * This concept appears in the Web Map Services (WMS) 1.3 specification, 
quoted here:
+ *
+ * <blockquote><font size="-1"><b>6.7.2 Map CS</b> —
+ * The usual orientation of the Map CS shall be such that the <var>i</var> 
axis is parallel to the East-to-West axis
+ * of the Layer CRS and increases Eastward, and the <var>j</var> axis is 
parallel to the North-to-South axis of the
+ * Layer CRS and increases Southward. This orientation will not be possible in 
some cases, as (for example) in an
+ * orthographic projection over the South Pole. The convention to be followed 
is that, wherever possible, East shall
+ * be to the right edge and North shall be toward the upper edge of the Map 
CS.</font></blockquote>
+ *
+ * In addition to WMS, this method is used together with
+ * {@link org.apache.sis.referencing.cs.CoordinateSystems#swapAndScaleAxes 
CoordinateSystems.swapAndScaleAxes(…)}
+ * for the creation of transformation steps, as in the example below:
+ *
+ * {@preformat java
+ *     Matrix step1 = swapAndScaleAxes(sourceCS, 
sourceCS.forConvention(NORMALIZED);
+ *     Matrix step2 = ... some coordinate operation working on normalized axes 
...
+ *     Matrix step3 = swapAndScaleAxes(targetCS.forConvention(NORMALIZED), 
targetCS);
+ * }
+ *
+ * A rational for normalized axes order and units is explained in the 
<cite>Axis units and directions</cite>
+ * section of {@linkplain org.apache.sis.referencing.operation.projection map 
projection package description}.
  *
  * {@section Range of longitude values}
  * Most geographic CRS have a longitude axis defined in the [-180 … +180]° 
range. All map projections in Apache SIS are
@@ -117,6 +141,7 @@ public enum AxesConvention {
      * </ul>}
      *
      * @see 
org.apache.sis.referencing.cs.CoordinateSystems#angle(AxisDirection, 
AxisDirection)
+     * @see <a href="http://en.wikipedia.org/wiki/Right_hand_rule";>Right-hand 
rule on Wikipedia</a>
      */
     RIGHT_HANDED,
 

Modified: 
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/Normalizer.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/Normalizer.java?rev=1558411&r1=1558410&r2=1558411&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/Normalizer.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/Normalizer.java
 [UTF-8] Wed Jan 15 14:58:16 2014
@@ -23,6 +23,7 @@ import javax.measure.unit.SI;
 import javax.measure.unit.NonSI;
 import javax.measure.converter.UnitConverter;
 import javax.measure.converter.ConversionException;
+import org.opengis.referencing.cs.RangeMeaning;
 import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.cs.CoordinateSystemAxis;
 import org.apache.sis.internal.referencing.AxisDirections;
@@ -52,6 +53,13 @@ import static org.opengis.referencing.Id
  */
 final class Normalizer implements Comparable<Normalizer> {
     /**
+     * The properties to exclude in calls to {@link 
IdentifiedObjects#getProperties(IdentifiedObject, String...)}.
+     */
+    private static final String[] EXCLUDES = {
+        IDENTIFIERS_KEY
+    };
+
+    /**
      * The axis to be compared by {@link #compareTo(Normalizer)}.
      */
     private final CoordinateSystemAxis axis;
@@ -172,7 +180,7 @@ final class Normalizer implements Compar
         }
         final Map<String,?> properties;
         if (newAbbr.equals(abbreviation)) {
-            properties = IdentifiedObjects.getProperties(axis, 
IDENTIFIERS_KEY);
+            properties = IdentifiedObjects.getProperties(axis, EXCLUDES);
         } else {
             properties = singletonMap(NAME_KEY, 
Vocabulary.format(Vocabulary.Keys.Unnamed));
         }
@@ -220,4 +228,46 @@ final class Normalizer implements Compar
         final StringBuilder buffer = (StringBuilder) 
CharSequences.camelCaseToSentence(cs.getInterface().getSimpleName());
         return cs.createSameType(singletonMap(AbstractCS.NAME_KEY, 
DefaultCompoundCS.createName(buffer, axes)), axes);
     }
+
+    /**
+     * Returns a coordinate system with the same axes than the given CS, 
except that the wrapround axes
+     * are shifted to a range of positive values. This method can be used in 
order to shift between the
+     * [-180 … +180]° and [0 … 360]° ranges of longitude values.
+     *
+     * <p>This method shifts the axis {@linkplain 
CoordinateSystemAxis#getMinimumValue() minimum} and
+     * {@linkplain CoordinateSystemAxis#getMaximumValue() maximum} values by a 
multiple of half the range
+     * (typically 180°). This method does not change the meaning of ordinate 
values. For example a longitude
+     * of -60° still locate the same point in the old and the new coordinate 
system. But the preferred way
+     * to locate that point become the 300° value if the longitude range has 
been shifted to positive values.</p>
+     *
+     * @return A coordinate system using the given kind of longitude range 
(may be {@code axis}).
+     */
+    static AbstractCS shiftAxisRange(final AbstractCS cs) {
+        boolean changed = false;
+        final CoordinateSystemAxis[] axes = new 
CoordinateSystemAxis[cs.getDimension()];
+        for (int i=0; i<axes.length; i++) {
+            CoordinateSystemAxis axis = cs.getAxis(i);
+            final RangeMeaning rangeMeaning = axis.getRangeMeaning();
+            if (RangeMeaning.WRAPAROUND.equals(rangeMeaning)) {
+                double min = axis.getMinimumValue();
+                if (min < 0) {
+                    double max = axis.getMaximumValue();
+                    double offset = (max - min) / 2;
+                    offset *= Math.floor(min/offset + 1E-10);
+                    min -= offset;
+                    max -= offset;
+                    if (min < max) { // Paranoiac check, but also a way to 
filter NaN values when offset is infinite.
+                        axis = new 
DefaultCoordinateSystemAxis(IdentifiedObjects.getProperties(axis, EXCLUDES),
+                                axis.getAbbreviation(), axis.getDirection(), 
axis.getUnit(), min, max, rangeMeaning);
+                        changed = true;
+                    }
+                }
+            }
+            axes[i] = axis;
+        }
+        if (!changed) {
+            return cs;
+        }
+        return cs.createSameType(IdentifiedObjects.getProperties(cs, 
EXCLUDES), axes);
+    }
 }

Modified: 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/AbstractCSTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/AbstractCSTest.java?rev=1558411&r1=1558410&r2=1558411&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/AbstractCSTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/AbstractCSTest.java
 [UTF-8] Wed Jan 15 14:58:16 2014
@@ -55,9 +55,9 @@ public final strictfp class AbstractCSTe
             final CoordinateSystemAxis... expected)
     {
         final AbstractCS derived = cs.forConvention(convention);
-        assertNotSame("Expected a new instance.", cs, derived);
-        assertSame("No change expected.", derived, 
derived.forConvention(convention));
-        assertSame("Shall be cached.", derived, cs.forConvention(convention));
+        assertNotSame("cs.forConvention(…)", cs, derived);
+        assertSame("derived.forConvention(…)", derived, 
derived.forConvention(convention));
+        assertSame("cs.forConvention(…)", derived, 
cs.forConvention(convention));
         assertEquals("dimension", expected.length, cs.getDimension());
         for (int i=0; i<expected.length; i++) {
             assertEquals(expected[i], derived.getAxis(i));
@@ -87,7 +87,7 @@ public final strictfp class AbstractCSTe
     @DependsOnMethod("testForRightHandedConvention")
     public void testForNormalizedConvention() {
         /*
-         * Some expected axes, identical to the one in CommonAxes except for 
name or units.
+         * Some expected axes, identical to the ones in CommonAxes except for 
name or units.
          */
         final DefaultCoordinateSystemAxis EASTING = new 
DefaultCoordinateSystemAxis(
                 singletonMap(NAME_KEY, 
Vocabulary.format(Vocabulary.Keys.Unnamed)), "E",
@@ -107,6 +107,16 @@ public final strictfp class AbstractCSTe
     }
 
     /**
+     * Tests {@link AbstractCS#forConvention(AxesConvention)}
+     * with a {@link AxesConvention#POSITIVE_RANGE} argument.
+     */
+    @Test
+    public void testForPositiveRangeConvention() {
+        final AbstractCS cs = new AbstractCS(singletonMap(NAME_KEY, "Test"), 
CommonAxes.LONGITUDE, CommonAxes.LATITUDE);
+        verifyAxesConvention(AxesConvention.POSITIVE_RANGE, cs, 
CommonAxes.SHIFTED_LONGITUDE, CommonAxes.LATITUDE);
+    }
+
+    /**
      * Tests serialization.
      */
     @Test

Modified: 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/CommonAxes.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/CommonAxes.java?rev=1558411&r1=1558410&r2=1558411&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/CommonAxes.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/CommonAxes.java
 [UTF-8] Wed Jan 15 14:58:16 2014
@@ -70,6 +70,12 @@ public final strictfp class CommonAxes {
             AxisDirection.NORTH, NonSI.DEGREE_ANGLE, -90, 90, 
RangeMeaning.EXACT);
 
     /**
+     * Identical to {@link #LONGITUDE} except for the range of longitude 
values.
+     */
+    public static final DefaultCoordinateSystemAxis SHIFTED_LONGITUDE = 
create("Longitude", "λ",
+            AxisDirection.EAST, NonSI.DEGREE_ANGLE, 0, 360, 
RangeMeaning.WRAPAROUND);
+
+    /**
      * Default axis info for longitudes.
      * Increasing ordinates values go {@linkplain AxisDirection#EAST East}
      * and units are {@linkplain NonSI#DEGREE_ANGLE degrees}.

Modified: 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/NormalizerTest.java
URL: 
http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/NormalizerTest.java?rev=1558411&r1=1558410&r2=1558411&view=diff
==============================================================================
--- 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/NormalizerTest.java
 [UTF-8] (original)
+++ 
sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/cs/NormalizerTest.java
 [UTF-8] Wed Jan 15 14:58:16 2014
@@ -162,7 +162,7 @@ public final strictfp class NormalizerTe
     }
 
     /**
-     * Tests {@link Normalizer#normalize(CoordinateSystemAxis, int)}.
+     * Tests {@link Normalizer#normalize(CoordinateSystemAxis)}.
      */
     @Test
     public void testNormalizeAxis() {


Reply via email to