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() {