Author: desruisseaux
Date: Wed Apr 20 22:04:56 2016
New Revision: 1740204
URL: http://svn.apache.org/viewvc?rev=1740204&view=rev
Log:
Fix a mismatched dimension when transforming coordinates using position vector
transformation from geographic 2D to geographic 3D domains.
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationRegistryTest.java
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java?rev=1740204&r1=1740203&r2=1740204&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/cs/AbstractCS.java
[UTF-8] Wed Apr 20 22:04:56 2016
@@ -391,9 +391,10 @@ public class AbstractCS extends Abstract
* @return {@code true} if both objects are equal.
*/
@Override
+ @SuppressWarnings("fallthrough")
public boolean equals(final Object object, final ComparisonMode mode) {
if (object == this) {
- return true; // Slight optimization.
+ return true; // Slight
optimization.
}
if (!super.equals(object, mode)) {
return false;
@@ -403,6 +404,14 @@ public class AbstractCS extends Abstract
// No need to check the class - this check has been done by
super.equals(…).
return Arrays.equals(axes, ((AbstractCS) object).axes);
}
+ case DEBUG: {
+ final int d1 = axes.length;
+ final int d2 = ((CoordinateSystem) object).getDimension();
+ if (d1 != d2) {
+ throw new
AssertionError(Errors.format(Errors.Keys.MismatchedDimension_2, d1, d2));
+ }
+ // Fall through
+ }
default: {
final CoordinateSystem that = (CoordinateSystem) object;
final int dimension = getDimension();
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java?rev=1740204&r1=1740203&r2=1740204&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CRSPair.java
[UTF-8] Wed Apr 20 22:04:56 2016
@@ -16,6 +16,8 @@
*/
package org.apache.sis.referencing.operation;
+import org.opengis.referencing.cs.EllipsoidalCS;
+import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.IdentifiedObject;
import org.apache.sis.referencing.AbstractIdentifiedObject;
@@ -79,8 +81,9 @@ final class CRSPair {
}
/**
- * Returns the name of the GeoAPI interface implemented by the specified
object,
- * followed by the name between brackets.
+ * Returns the name of the GeoAPI interface implemented by the specified
object. In the GeographicCRS
+ * or EllipsoidalCS cases, the trailing CRS or CS suffix is replaced by
the number of dimensions
+ * (e.g. "Geographic3D").
*/
static String label(final IdentifiedObject object) {
if (object == null) {
@@ -92,7 +95,18 @@ final class CRSPair {
} else {
type = Classes.getLeafInterfaces(object.getClass(),
IdentifiedObject.class)[0];
}
- String label = Classes.getShortName(type);
+ String suffix, label = Classes.getShortName(type);
+ if (label.endsWith((suffix = "CRS")) || label.endsWith(suffix = "CS"))
{
+ Object cs = object;
+ if (object instanceof CoordinateReferenceSystem) {
+ cs = ((CoordinateReferenceSystem)
object).getCoordinateSystem();
+ }
+ if (cs instanceof EllipsoidalCS) {
+ final StringBuilder sb = new StringBuilder(label);
+ sb.setLength(label.length() - suffix.length());
+ label = sb.append(((CoordinateSystem)
cs).getDimension()).append('D').toString();
+ }
+ }
String name = IdentifiedObjects.getName(object, null);
if (name != null) {
int i = 30; // Arbitrary
length threshold.
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java?rev=1740204&r1=1740203&r2=1740204&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
[UTF-8] Wed Apr 20 22:04:56 2016
@@ -38,6 +38,7 @@ import org.opengis.referencing.Identifie
import org.opengis.referencing.NoSuchAuthorityCodeException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.GeodeticCRS;
+import org.opengis.referencing.crs.SingleCRS;
import org.opengis.referencing.cs.EllipsoidalCS;
import org.opengis.referencing.operation.*;
@@ -294,7 +295,8 @@ class CoordinateOperationRegistry {
* need to modify the coordinate operation in order to
match the new number of dimensions.
*/
if (combine != 0) {
- operation = propagateVertical(operation, source !=
sourceCRS, target != targetCRS);
+ operation = propagateVertical(sourceCRS, source !=
sourceCRS,
+ targetCRS, target !=
targetCRS, operation);
if (operation == null) {
continue;
}
@@ -303,8 +305,12 @@ class CoordinateOperationRegistry {
return operation;
}
} catch (IllegalArgumentException | ConversionException e) {
- throw new FactoryException(Errors.format(
- Errors.Keys.CanNotInstantiate_1, new
CRSPair(sourceCRS, targetCRS)), e);
+ String message =
Errors.format(Errors.Keys.CanNotInstantiate_1, new CRSPair(sourceCRS,
targetCRS));
+ String details = e.getLocalizedMessage();
+ if (details != null) {
+ message = message + ' ' + details;
+ }
+ throw new FactoryException(message, e);
}
}
}
@@ -538,7 +544,8 @@ class CoordinateOperationRegistry {
final MathTransformFactory
mtFactory)
throws IllegalArgumentException, ConversionException,
FactoryException
{
- assert Utilities.deepEquals(sourceCRS, targetCRS,
ComparisonMode.ALLOW_VARIANT);
+ assert ReferencingUtilities.getDimension(sourceCRS) !=
ReferencingUtilities.getDimension(targetCRS)
+ || Utilities.deepEquals(sourceCRS, targetCRS,
ComparisonMode.ALLOW_VARIANT);
final Matrix m =
CoordinateSystems.swapAndScaleAxes(sourceCRS.getCoordinateSystem(),
targetCRS.getCoordinateSystem());
return (m.isIdentity()) ? null : mtFactory.createAffineTransform(m);
}
@@ -692,16 +699,20 @@ class CoordinateOperationRegistry {
* <cite>best effort</cite> basis. In any cases, the {@link #complete}
method should be invoked
* after this one in order to ensure that the source and target CRS are
the expected ones.</p>
*
- * @param operation the original (typically two-dimensional) coordinate
operation.
+ * @param sourceCRS the potentially three-dimensional source CRS
* @param source3D {@code true} for adding ellipsoidal height in source
coordinates.
+ * @param targetCRS the potentially three-dimensional target CRS
* @param target3D {@code true} for adding ellipsoidal height in target
coordinates.
+ * @param operation the original (typically two-dimensional) coordinate
operation.
* @return a coordinate operation with the source and/or target
coordinates made 3D,
* or {@code null} if this method does not know how to create the
operation.
* @throws IllegalArgumentException if the operation method can not have
the desired number of dimensions.
* @throws FactoryException if an error occurred while creating the
coordinate operation.
*/
- private CoordinateOperation propagateVertical(final CoordinateOperation
operation,
- final boolean source3D, final boolean target3D) throws
IllegalArgumentException, FactoryException
+ private CoordinateOperation propagateVertical(final
CoordinateReferenceSystem sourceCRS, final boolean source3D,
+ final
CoordinateReferenceSystem targetCRS, final boolean target3D,
+ final CoordinateOperation
operation)
+ throws IllegalArgumentException, FactoryException
{
final List<CoordinateOperation> operations = new ArrayList<>();
if (operation instanceof ConcatenatedOperation) {
@@ -709,8 +720,8 @@ class CoordinateOperationRegistry {
} else {
operations.add(operation);
}
- if ((source3D && !propagateVertical(operations.listIterator(), true))
||
- (target3D &&
!propagateVertical(operations.listIterator(operations.size()), false)))
+ if ((source3D && !propagateVertical(sourceCRS, targetCRS,
operations.listIterator(), true)) ||
+ (target3D && !propagateVertical(sourceCRS, targetCRS,
operations.listIterator(operations.size()), false)))
{
return null;
}
@@ -727,13 +738,18 @@ class CoordinateOperationRegistry {
* Appends a vertical axis in the source CRS of the first step {@code
forward = true} or in
* the target CRS of the last step {@code forward = false} of the given
operations chain.
*
+ * @param source3D the potentially three-dimensional source CRS
+ * @param target3D the potentially three-dimensional target CRS
* @param operations the chain of operations in which to add a vertical
axis.
* @param forward {@code true} for adding the vertical axis at the
beginning, or
* {@code false} for adding the vertical axis at the
end.
* @return {@code true} on success.
* @throws IllegalArgumentException if the operation method can not have
the desired number of dimensions.
*/
- private boolean propagateVertical(final ListIterator<CoordinateOperation>
operations, final boolean forward)
+ private boolean propagateVertical(final CoordinateReferenceSystem source3D,
+ final CoordinateReferenceSystem target3D,
+ final ListIterator<CoordinateOperation>
operations,
+ final boolean forward)
throws IllegalArgumentException, FactoryException
{
while (forward ? operations.hasNext() : operations.hasPrevious()) {
@@ -771,18 +787,18 @@ class CoordinateOperationRegistry {
if (op instanceof SingleOperation) {
final MathTransformFactory mtFactory =
factorySIS.getMathTransformFactory();
if (mtFactory instanceof DefaultMathTransformFactory) {
- final CoordinateReferenceSystem source3D =
toGeodetic3D(sourceCRS);
- final CoordinateReferenceSystem target3D =
toGeodetic3D(targetCRS);
+ if (forward) sourceCRS = toGeodetic3D(sourceCRS,
source3D);
+ else targetCRS = toGeodetic3D(targetCRS,
target3D);
final MathTransform mt;
try {
mt = ((DefaultMathTransformFactory)
mtFactory).createParameterizedTransform(
((SingleOperation)
op).getParameterValues(),
-
ReferencingUtilities.createTransformContext(source3D, target3D, null));
+
ReferencingUtilities.createTransformContext(sourceCRS, targetCRS, null));
} catch (InvalidGeodeticParameterException e) {
log(e);
break;
}
- operations.set(recreate(op, source3D, target3D, mt,
mtFactory.getLastMethodUsed()));
+ operations.set(recreate(op, sourceCRS, targetCRS, mt,
mtFactory.getLastMethodUsed()));
return true;
}
}
@@ -813,7 +829,7 @@ class CoordinateOperationRegistry {
* conform to the definition provided by the authority.
*/
final MathTransform mt =
factorySIS.getMathTransformFactory().createAffineTransform(matrix);
- operations.set(recreate(op, toGeodetic3D(sourceCRS),
toGeodetic3D(targetCRS), mt, null));
+ operations.set(recreate(op, toGeodetic3D(sourceCRS, source3D),
toGeodetic3D(targetCRS, target3D), mt, null));
}
/*
* If we processed the operation that change the number of
dimensions, we are done.
@@ -829,13 +845,27 @@ class CoordinateOperationRegistry {
* If the given CRS is two-dimensional, append an ellipsoidal height to it.
* It is caller's responsibility to ensure that the given CRS is
geographic.
*/
- private CoordinateReferenceSystem toGeodetic3D(CoordinateReferenceSystem
crs) throws FactoryException {
+ private CoordinateReferenceSystem toGeodetic3D(CoordinateReferenceSystem
crs,
+ final CoordinateReferenceSystem candidate) throws FactoryException
+ {
assert (crs instanceof GeodeticCRS) && (crs.getCoordinateSystem()
instanceof EllipsoidalCS) : crs;
- if (crs.getCoordinateSystem().getDimension() == 2) {
- crs =
ReferencingServices.getInstance().createCompoundCRS(factorySIS.getCRSFactory(),
factorySIS.getCSFactory(),
- derivedFrom(crs), crs,
CommonCRS.Vertical.ELLIPSOIDAL.crs());
+ if (crs.getCoordinateSystem().getDimension() != 2) {
+ return crs;
+ }
+ /*
+ * The check for same class is a cheap way to ensure that the two CRS
implement the same GeoAPI interface.
+ * This test is stricter than necessary, but the result should still
not wrong if we miss an opportunity
+ * to return the existing instance.
+ */
+ if (crs.getClass() == candidate.getClass() &&
candidate.getCoordinateSystem().getDimension() == 3) {
+ if (Utilities.equalsIgnoreMetadata(((SingleCRS) crs).getDatum(),
((SingleCRS) candidate).getDatum())) {
+ return candidate; // Keep the existing instance
since it may contain useful metadata.
+ }
}
- return crs;
+ return ReferencingServices.getInstance().createCompoundCRS(
+ factorySIS.getCRSFactory(),
+ factorySIS.getCSFactory(),
+ derivedFrom(crs), crs, CommonCRS.Vertical.ELLIPSOIDAL.crs());
}
/**
Modified:
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationRegistryTest.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationRegistryTest.java?rev=1740204&r1=1740203&r2=1740204&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationRegistryTest.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/CoordinateOperationRegistryTest.java
[UTF-8] Wed Apr 20 22:04:56 2016
@@ -328,7 +328,7 @@ public final strictfp class CoordinateOp
} else {
assertEpsgNameWithoutIdentifierEqual("NTF (Paris) to WGS 84 (1)",
operation);
assertEpsgNameWithoutIdentifierEqual("NTF (Paris)",
operation.getSourceCRS());
- assertEpsgNameWithoutIdentifierEqual("WGS 84",
operation.getTargetCRS());
+ assertEquals("name", "WGS 84",
operation.getTargetCRS().getName().getCode());
assertEpsgNameWithoutIdentifierEqual("NTF (Paris) to NTF (1)",
step1);
assertEpsgNameWithoutIdentifierEqual("NTF to WGS 84 (1)",
step2);
}