Author: desruisseaux
Date: Mon Apr 11 11:14:36 2016
New Revision: 1738569
URL: http://svn.apache.org/viewvc?rev=1738569&view=rev
Log:
Add a test and debug the case where axis order does not match the EPSG
definition.
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.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/factory/sql/EPSGDataAccess.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java?rev=1738569&r1=1738568&r2=1738569&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/EPSGDataAccess.java
[UTF-8] Mon Apr 11 11:14:36 2016
@@ -1159,8 +1159,12 @@ addURIs: for (int i=0; ; i++) {
* @return The name together with a set of properties.
*/
private Map<String,Object> createProperties(final String table, final
String name, final Integer code,
- final String domainCode, String scope, String remarks, final
boolean deprecated) throws SQLException, FactoryException
+ final String domainCode, String scope, final String remarks, final
boolean deprecated)
+ throws SQLException, FactoryException
{
+ if ("?".equals(scope)) { // EPSG sometime uses this
value for unspecified scope.
+ scope = null;
+ }
final Map<String,Object> properties = createProperties(table, name,
code, remarks, deprecated);
if (domainCode != null) {
properties.put(Datum.DOMAIN_OF_VALIDITY_KEY,
owner.createExtent(domainCode));
@@ -2895,6 +2899,7 @@ next: while (r.next()) {
}
}
opProperties.put(ReferencingServices.OPERATION_TYPE_KEY, opType);
+ opProperties.put(ReferencingServices.PARAMETERS_KEY,
parameters);
/*
* Following restriction will be removed in a future
SIS version if the method is added to GeoAPI.
*/
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java?rev=1738569&r1=1738568&r2=1738569&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
[UTF-8] Mon Apr 11 11:14:36 2016
@@ -871,11 +871,12 @@ check: for (int isTarget=0; ; isTar
final FormattableObject enclosing = formatter.getEnclosingElement(1);
final boolean isSubOperation = (enclosing instanceof
PassThroughOperation);
final boolean isComponent = (enclosing instanceof
ConcatenatedOperation);
+ final boolean isConcatenated = (this instanceof
ConcatenatedOperation);
if (!isSubOperation) {
if (!isComponent) {
append(formatter, getSourceCRS(), WKTKeywords.SourceCRS);
}
- if (!(this instanceof ConcatenatedOperation)) {
+ if (!isConcatenated) {
append(formatter, getTargetCRS(), WKTKeywords.TargetCRS);
}
}
@@ -899,7 +900,7 @@ check: for (int isTarget=0; ; isTar
formatter.indent(-1);
}
}
- if (!isSubOperation && !isComponent) {
+ if (!isSubOperation && !isConcatenated) {
append(formatter, getInterpolationCRS(),
WKTKeywords.InterpolationCRS);
final double accuracy = getLinearAccuracy();
if (accuracy > 0) {
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=1738569&r1=1738568&r2=1738569&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] Mon Apr 11 11:14:36 2016
@@ -40,6 +40,7 @@ import org.opengis.referencing.operation
import org.apache.sis.referencing.CRS;
import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.referencing.AbstractIdentifiedObject;
import org.apache.sis.referencing.cs.CoordinateSystems;
import org.apache.sis.referencing.operation.matrix.Matrices;
import org.apache.sis.referencing.operation.transform.MathTransforms;
@@ -490,30 +491,33 @@ final class CoordinateOperationRegistry
CoordinateReferenceSystem crs;
if (Utilities.equalsApproximatively(sourceCRS, crs =
operation.getSourceCRS())) sourceCRS = crs;
if (Utilities.equalsApproximatively(targetCRS, crs =
operation.getTargetCRS())) targetCRS = crs;
+ final Map<String,Object> properties = new
HashMap<>(derivedFrom(operation));
/*
* Determine whether the operation to create is a Conversion or a
Transformation.
* Conversion may also be a more accurate type like Projection. We
want the GeoAPI
* interface. The most reliable way is to ask to the operation, but
this is SIS-specific.
* The fallback uses reflection.
*/
- final Class<? extends CoordinateOperation> type;
- if (operation instanceof AbstractCoordinateOperation) {
- type = ((AbstractCoordinateOperation) operation).getInterface();
+ if (operation instanceof AbstractIdentifiedObject) {
+ properties.put(ReferencingServices.OPERATION_TYPE_KEY,
+ ((AbstractIdentifiedObject) operation).getInterface());
} else {
final Class<? extends CoordinateOperation>[] types =
Classes.getLeafInterfaces(operation.getClass(),
CoordinateOperation.class);
- type = (types.length != 0) ? types[0] : SingleOperation.class;
+ if (types.length != 0) {
+ properties.put(ReferencingServices.OPERATION_TYPE_KEY,
types[0]);
+ }
}
/*
* Reuse the same operation method, just changing its number of
dimension.
*/
OperationMethod method = null;
if (operation instanceof SingleOperation) {
- method = DefaultOperationMethod.redimension(((SingleOperation)
operation).getMethod(),
+ final SingleOperation single = (SingleOperation) operation;
+ properties.put(ReferencingServices.PARAMETERS_KEY,
single.getParameterValues());
+ method = DefaultOperationMethod.redimension(single.getMethod(),
transform.getSourceDimensions(),
transform.getTargetDimensions());
}
- final Map<String,Object> properties = new
HashMap<>(derivedFrom(operation));
- properties.put(ReferencingServices.OPERATION_TYPE_KEY, type);
return factorySIS.createSingleOperation(properties, sourceCRS,
targetCRS,
AbstractCoordinateOperation.getInterpolationCRS(operation),
method, transform);
}
Modified:
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
URL:
http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java?rev=1738569&r1=1738568&r2=1738569&view=diff
==============================================================================
---
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
[UTF-8] (original)
+++
sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
[UTF-8] Mon Apr 11 11:14:36 2016
@@ -34,6 +34,7 @@ import org.opengis.referencing.operation
import org.opengis.referencing.operation.Transformation;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.MathTransformFactory;
+import org.apache.sis.internal.referencing.PositionalAccuracyConstant;
import org.apache.sis.internal.system.DefaultFactories;
import org.apache.sis.internal.util.UnmodifiableArrayList;
import org.apache.sis.internal.util.CollectionsExt;
@@ -177,6 +178,7 @@ final class DefaultConcatenatedOperation
final boolean setAccuracy)
throws FactoryException
{
+ double coarsestAccuracy = 0;
CoordinateReferenceSystem previous = null;
for (int i=0; i<operations.length; i++) {
final CoordinateOperation op = operations[i];
@@ -222,12 +224,18 @@ final class DefaultConcatenatedOperation
* See javadoc for a rational about why we take only
transformations in account.
*/
if (setAccuracy && op instanceof Transformation) {
- Collection<PositionalAccuracy> candidates =
op.getCoordinateOperationAccuracy();
+ final Collection<PositionalAccuracy> candidates =
op.getCoordinateOperationAccuracy();
if (!Containers.isNullOrEmpty(candidates)) {
- if (coordinateOperationAccuracy == null) {
- coordinateOperationAccuracy = new LinkedHashSet<>();
+ final double accuracy =
PositionalAccuracyConstant.getLinearAccuracy(op);
+ if (accuracy > coarsestAccuracy) {
+ coarsestAccuracy = accuracy;
+ if (coordinateOperationAccuracy == null) {
+ coordinateOperationAccuracy = new
LinkedHashSet<>(candidates);
+ } else {
+ coordinateOperationAccuracy.clear();
+ coordinateOperationAccuracy.addAll(candidates);
+ }
}
- coordinateOperationAccuracy.addAll(candidates);
}
}
}
@@ -337,6 +345,7 @@ final class DefaultConcatenatedOperation
protected String formatTo(final Formatter formatter) {
super.formatTo(formatter);
for (final CoordinateOperation component : operations) {
+ formatter.newLine();
formatter.append(castOrCopy(component));
}
formatter.setInvalidWKT(this, null);
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=1738569&r1=1738568&r2=1738569&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] Mon Apr 11 11:14:36 2016
@@ -16,10 +16,14 @@
*/
package org.apache.sis.referencing.operation;
+import java.util.List;
import java.text.ParseException;
import org.opengis.util.FactoryException;
+import org.opengis.parameter.ParameterValueGroup;
import org.opengis.referencing.crs.CRSAuthorityFactory;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.SingleOperation;
+import org.opengis.referencing.operation.ConcatenatedOperation;
import org.opengis.referencing.operation.CoordinateOperation;
import org.opengis.referencing.operation.CoordinateOperationAuthorityFactory;
import org.opengis.referencing.operation.TransformException;
@@ -29,22 +33,39 @@ import org.apache.sis.io.wkt.WKTFormat;
// Test dependencies
import org.apache.sis.referencing.operation.transform.MathTransformTestCase;
+import org.apache.sis.test.DependsOnMethod;
+import org.apache.sis.test.DependsOn;
import org.junit.BeforeClass;
import org.junit.AfterClass;
import org.junit.Test;
+import static org.apache.sis.internal.referencing.Formulas.ANGULAR_TOLERANCE;
import static org.apache.sis.test.ReferencingAssert.*;
import static org.junit.Assume.*;
/**
* Tests {@link CoordinateOperationRegistry}.
+ * This class tests the following operations:
+ *
+ * <ul>
+ * <li><cite>"NTF (Paris) to WGS 84 (1)"</cite> operation (EPSG:8094), which
implies a longitude rotation
+ * followed by a geocentric translation in the geographic domain.</li>
+ * </ul>
+ *
+ * The operations are tested with various axis order and dimension in source
and target CRS.
*
* @author Martin Desruisseaux (Geomatys)
* @since 0.7
* @version 0.7
* @module
*/
+@DependsOn({
+ DefaultConversionTest.class,
+ DefaultTransformationTest.class,
+ DefaultPassThroughOperationTest.class,
+ DefaultConcatenatedOperationTest.class
+})
public final strictfp class CoordinateOperationRegistryTest extends
MathTransformTestCase {
/**
* Tolerance threshold for strict comparisons of floating point numbers.
@@ -92,6 +113,9 @@ public final strictfp class CoordinateOp
public static void createFactory() throws ParseException {
factory = new DefaultCoordinateOperationFactory();
parser = new WKTFormat(null, null);
+ parser.addFragment("NTF",
+ "Datum[“Nouvelle Triangulation Française (Paris)”,\n" +
+ " Ellipsoid[“Clarke 1880 (IGN)”, 6378249.2,
293.4660212936269]]");
}
/**
@@ -111,33 +135,104 @@ public final strictfp class CoordinateOp
}
/**
- * Tests a datum shift between two geographic CRS which also implies a
change of prime meridian.
- * The expected coordinate operation is EPSG:8094.
+ * Tests <cite>"NTF (Paris) to WGS 84 (1)"</cite> operation with source
and target CRS conform to EPSG definitions.
*
* @throws ParseException if a CRS used in this test can not be parsed.
* @throws FactoryException if the operation can not be created.
* @throws TransformException if an error occurred while converting the
test points.
*/
@Test
- public void testDatumShiftWithLongitudeRotation() throws ParseException,
FactoryException, TransformException {
+ public void testLongitudeRotationBetweenConformCRS() throws
ParseException, FactoryException, TransformException {
final CoordinateReferenceSystem sourceCRS = parse(
"GeodeticCRS[“NTF (Paris)”,\n" +
- " Datum[“Nouvelle Triangulation Française (Paris)”,\n" +
- " Ellipsoid[“Clarke 1880 (IGN)”, 6378249.2,
293.4660212936269]],\n" +
+ " $NTF,\n" +
" PrimeMeridian[“Paris”, 2.5969213],\n" +
" CS[ellipsoidal, 2],\n" +
" Axis[“Latitude (φ)”, NORTH],\n" +
" Axis[“Longitude (λ)”, EAST],\n" +
- " Unit[“grade”, 0.015707963267948967]\n," +
- " Id[“EPSG”, 4807]]");
+ " Unit[“grade”, 0.015707963267948967]]");
+ // Intentionally omit Id[“EPSG”, 4807] for testing capability
to find it back.
final CoordinateReferenceSystem targetCRS =
CommonCRS.WGS84.geographic();
final CoordinateOperation operation =
registry.createOperation(sourceCRS, targetCRS);
assertEpsgNameAndIdentifierEqual("NTF (Paris) to WGS 84 (1)", 8094,
operation);
- assertEquals("linearAccuracy", 2, CRS.getLinearAccuracy(operation),
STRICT);
+ assertEpsgNameAndIdentifierEqual("NTF (Paris)", 4807,
operation.getSourceCRS());
+ assertEpsgNameAndIdentifierEqual("WGS 84", 4326,
operation.getTargetCRS());
+ verifyNTF(operation);
+ /*
+ * Same test point than the one used in
FranceGeocentricInterpolationTest:
+ *
+ * NTF: 48°50′40.2441″N 2°25′32.4187″E
+ * RGF: 48°50′39.9967″N 2°25′29.8273″E (close to WGS84)
+ */
+ transform = operation.getMathTransform();
+ tolerance = ANGULAR_TOLERANCE;
+ λDimension = new int[] {1};
+ verifyTransform(new double[] {54.271680278, 0.098269657}, // in
grads east of Paris
+ new double[] {48.844443528, 2.424952028}); // in
degrees east of Greenwich
+ validate();
+ }
- transform = operation.getMathTransform();
- assertFalse(transform.isIdentity());
+ /**
+ * Tests <cite>"NTF (Paris) to WGS 84 (1)"</cite> operation with
normalized source and target CRS.
+ * {@link CoordinateOperationRegistry} should be able to find the
operation despite the difference
+ * in axis order an units.
+ *
+ * @throws ParseException if a CRS used in this test can not be parsed.
+ * @throws FactoryException if the operation can not be created.
+ * @throws TransformException if an error occurred while converting the
test points.
+ */
+ @Test
+ @DependsOnMethod("testLongitudeRotationBetweenConformCRS")
+ public void testLongitudeRotationBetweenNormalizedCRS() throws
ParseException, FactoryException, TransformException {
+ final CoordinateReferenceSystem sourceCRS = parse(
+ "GeodeticCRS[“NTF (Paris)”,\n" +
+ " $NTF,\n" +
+ " PrimeMeridian[“Paris”, 2.33722917],\n" +
+ " CS[ellipsoidal, 2],\n" +
+ " Axis[“Longitude (λ)”, EAST],\n" +
+ " Axis[“Latitude (φ)”, NORTH],\n" +
+ " Unit[“degree”, 0.017453292519943295]]");
+
+ final CoordinateReferenceSystem targetCRS =
CommonCRS.WGS84.normalizedGeographic();
+ final CoordinateOperation operation =
registry.createOperation(sourceCRS, targetCRS);
+ verifyNTF(operation);
+
+ transform = operation.getMathTransform();
+ tolerance = ANGULAR_TOLERANCE;
+ λDimension = new int[] {1};
+ verifyTransform(new double[] {0.088442691, 48.844512250}, // in
degrees east of Paris
+ new double[] {2.424952028, 48.844443528}); // in
degrees east of Greenwich
validate();
}
+
+ /**
+ * Verifies a coordinate operation which is expected to be <cite>"NTF
(Paris) to WGS 84 (1)"</cite> (EPSG:8094).
+ */
+ static void verifyNTF(final CoordinateOperation operation) {
+ assertEquals("name", "NTF (Paris) to WGS 84 (1)",
operation.getName().getCode());
+ assertEquals("sourceCRS.name", "NTF (Paris)",
operation.getSourceCRS().getName().getCode());
+ assertEquals("targetCRS.name", "WGS 84",
operation.getTargetCRS().getName().getCode());
+ assertEquals("Should report only the coarsest accuracy.", 1,
operation.getCoordinateOperationAccuracy().size());
+ assertEquals("linearAccuracy", 2,
CRS.getLinearAccuracy(operation), STRICT);
+
+ assertInstanceOf("Operation should have two steps.",
ConcatenatedOperation.class, operation);
+ final List<? extends CoordinateOperation> steps =
((ConcatenatedOperation) operation).getOperations();
+ assertEquals("Operation should have two steps.", 2, steps.size());
+
+ final SingleOperation step1 = (SingleOperation) steps.get(0);
+ final SingleOperation step2 = (SingleOperation) steps.get(1);
+ assertSame("SourceCRS shall be the targetCRS of previous step.",
step1.getTargetCRS(), step2.getSourceCRS());
+ assertEquals("Step 1", "NTF (Paris) to NTF (1)",
step1.getName().getCode());
+ assertEquals("Step 2", "NTF to WGS 84 (1)",
step2.getName().getCode());
+ assertEquals("Method 1", "Longitude rotation",
step1.getMethod().getName().getCode());
+ assertEquals("Method 2", "Geocentric translations (geog2D domain)",
step2.getMethod().getName().getCode());
+
+ final ParameterValueGroup p1 = step1.getParameterValues();
+ final ParameterValueGroup p2 = step2.getParameterValues();
+ assertEquals("Longitude offset", 2.5969213, p1.parameter("Longitude
offset") .doubleValue(), STRICT);
+ assertEquals("X-axis translation", -168, p2.parameter("X-axis
translation").doubleValue(), STRICT);
+ assertEquals("Y-axis translation", -60, p2.parameter("Y-axis
translation").doubleValue(), STRICT);
+ assertEquals("Z-axis translation", 320, p2.parameter("Z-axis
translation").doubleValue(), STRICT);
+ }
}