sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1813110 - in /sis/branches/JDK8/core/sis-referencing/src: main/java/org/apache/sis/referencing/operation/ test/java/org/apache/sis/geometry/
Date Mon, 23 Oct 2017 22:46:16 GMT
Author: desruisseaux
Date: Mon Oct 23 22:46:16 2017
New Revision: 1813110

URL: http://svn.apache.org/viewvc?rev=1813110&view=rev
Log:
Fix change of longitude range when there is also a change of ellipsoid.

Modified:
    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/AbstractSingleOperation.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/EnvelopesTest.java

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=1813110&r1=1813109&r2=1813110&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 Oct 23 22:46:16 2017
@@ -1037,7 +1037,7 @@ check:      for (int isTarget=0; ; isTar
     private void setSource(final CoordinateReferenceSystem crs) {
         if (sourceCRS == null) {
             sourceCRS = crs;
-        } else {
+        } else if (!sourceCRS.equals(crs)) {                    // Could be defined by ConcatenatedOperation.
             MetadataUtilities.propertyAlreadySet(AbstractCoordinateOperation.class, "setSource",
"sourceCRS");
         }
     }
@@ -1056,7 +1056,7 @@ check:      for (int isTarget=0; ; isTar
     private void setTarget(final CoordinateReferenceSystem crs) {
         if (targetCRS == null) {
             targetCRS = crs;
-        } else {
+        } else if (!targetCRS.equals(crs)) {                    // Could be defined by ConcatenatedOperation.
             MetadataUtilities.propertyAlreadySet(AbstractCoordinateOperation.class, "setTarget",
"targetCRS");
         }
     }
@@ -1120,4 +1120,11 @@ check:      for (int isTarget=0; ; isTar
             MetadataUtilities.propertyAlreadySet(AbstractCoordinateOperation.class, "setScope",
"scope");
         }
     }
+
+    /**
+     * Invoked by JAXB after unmarshalling.
+     */
+    void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
+        computeTransientFields();
+    }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java?rev=1813110&r1=1813109&r2=1813110&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/AbstractSingleOperation.java
[UTF-8] Mon Oct 23 22:46:16 2017
@@ -70,7 +70,7 @@ import static org.apache.sis.util.Utilit
  * {@link DefaultPassThroughOperation}.</p>
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.7
+ * @version 0.8
  * @since   0.6
  * @module
  */
@@ -513,7 +513,9 @@ class AbstractSingleOperation extends Ab
      *
      * @see <a href="http://issues.apache.org/jira/browse/SIS-291">SIS-291</a>
      */
-    private void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
+    @Override
+    final void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
+        super.afterUnmarshal(unmarshaller, parent);
         final CoordinateReferenceSystem sourceCRS = super.getSourceCRS();
         final CoordinateReferenceSystem targetCRS = super.getTargetCRS();
         if (transform == null && sourceCRS != null && targetCRS != null &&
parameters != null) try {

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=1813110&r1=1813109&r2=1813110&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 Oct 23 22:46:16 2017
@@ -52,7 +52,7 @@ import static org.apache.sis.util.Utilit
  * reference system associated with the concatenated operation.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.7
+ * @version 0.8
  * @since   0.6
  * @module
  */
@@ -113,18 +113,36 @@ final class DefaultConcatenatedOperation
             throw new IllegalArgumentException(Errors.getResources(properties).getString(
                     Errors.Keys.TooFewOccurrences_2, 2, CoordinateOperation.class));
         }
+        initialize(properties, operations, mtFactory);
+        checkDimensions(properties);
+    }
+
+    /**
+     * Initializes the {@link #sourceCRS}, {@link #targetCRS} and {@link #operations} fields.
+     * If the source or target CRS is already non-null (which may happen on JAXB unmarshalling),
+     * leaves that CRS unchanged.
+     *
+     * @param  properties   the properties specified at construction time, or {@code null}
if unknown.
+     * @param  operations   the operations to concatenate.
+     * @param  mtFactory    the math transform factory to use, or {@code null} for not performing
concatenation.
+     * @throws FactoryException if the factory can not concatenate the math transforms.
+     */
+    private void initialize(final Map<String,?>         properties,
+                            final CoordinateOperation[] operations,
+                            final MathTransformFactory  mtFactory)
+            throws FactoryException
+    {
         final List<CoordinateOperation> flattened = new ArrayList<>(operations.length);
-        initialize(properties, operations, flattened, mtFactory,
-                (coordinateOperationAccuracy == null), (domainOfValidity == null));
+        final CoordinateReferenceSystem crs = initialize(properties, operations, flattened,
mtFactory,
+                (sourceCRS == null), (coordinateOperationAccuracy == null), (domainOfValidity
== null));
+        if (targetCRS == null) {
+            targetCRS = crs;
+        }
         /*
          * At this point we should have flattened.size() >= 2, except if some operations
          * were omitted because their associated math transform were identity operation.
          */
-        operations      = flattened.toArray(new CoordinateOperation[flattened.size()]);
-        this.operations = UnmodifiableArrayList.wrap(operations);
-        this.sourceCRS  = operations[0].getSourceCRS();
-        this.targetCRS  = operations[operations.length - 1].getTargetCRS();
-        checkDimensions(properties);
+        this.operations = UnmodifiableArrayList.wrap(flattened.toArray(new CoordinateOperation[flattened.size()]));
     }
 
     /**
@@ -162,17 +180,20 @@ final class DefaultConcatenatedOperation
      * @param  operations   the operations to concatenate.
      * @param  flattened    the destination list in which to add the {@code SingleOperation}
instances.
      * @param  mtFactory    the math transform factory to use, or {@code null} for not performing
concatenation.
+     * @param  setSource    {@code true} for setting the {@link #sourceCRS} on the very first
CRS (regardless if null or not).
      * @param  setAccuracy  {@code true} for setting the {@link #coordinateOperationAccuracy}
field.
      * @param  setDomain    {@code true} for setting the {@link #domainOfValidity} field.
+     * @return the last target CRS, regardless if null or not.
      * @throws FactoryException if the factory can not concatenate the math transforms.
      */
-    private void initialize(final Map<String,?>             properties,
-                            final CoordinateOperation[]     operations,
-                            final List<CoordinateOperation> flattened,
-                            final MathTransformFactory      mtFactory,
-                            boolean                         setAccuracy,
-                            boolean                         setDomain)
-            throws FactoryException
+    private CoordinateReferenceSystem initialize(
+            final Map<String,?>             properties,
+            final CoordinateOperation[]     operations,
+            final List<CoordinateOperation> flattened,
+            final MathTransformFactory      mtFactory,
+            boolean                         setSource,
+            boolean                         setAccuracy,
+            boolean                         setDomain) throws FactoryException
     {
         CoordinateReferenceSystem previous = null;
         for (int i=0; i<operations.length; i++) {
@@ -182,17 +203,19 @@ final class DefaultConcatenatedOperation
              * Verify consistency of user argument: for each coordinate operation, the number
of dimensions of the
              * source CRS shall be equals to the number of dimensions of the target CRS in
the previous operation.
              */
-            if (previous != null) {
-                final CoordinateReferenceSystem next = op.getSourceCRS();
-                if (next != null) {
-                    final int dim1 = previous.getCoordinateSystem().getDimension();
-                    final int dim2 = next.getCoordinateSystem().getDimension();
-                    if (dim1 != dim2) {
-                        throw new IllegalArgumentException(Errors.getResources(properties).getString(
-                                Errors.Keys.MismatchedDimension_3, "operations[" + i + "].sourceCRS",
dim1, dim2));
-                    }
+            final CoordinateReferenceSystem next = op.getSourceCRS();
+            if (previous != null && next != null) {
+                final int dim1 = previous.getCoordinateSystem().getDimension();
+                final int dim2 = next.getCoordinateSystem().getDimension();
+                if (dim1 != dim2) {
+                    throw new IllegalArgumentException(Errors.getResources(properties).getString(
+                            Errors.Keys.MismatchedDimension_3, "operations[" + i + "].sourceCRS",
dim1, dim2));
                 }
             }
+            if (setSource) {
+                setSource = false;
+                sourceCRS = next;                                               // Take even
if null.
+            }
             previous = op.getTargetCRS();                                       // For next
iteration cycle.
             /*
              * Now that we have verified the CRS dimensions, we should be able to concatenate
the transforms.
@@ -207,11 +230,11 @@ final class DefaultConcatenatedOperation
                 final List<? extends CoordinateOperation> children = ((ConcatenatedOperation)
op).getOperations();
                 @SuppressWarnings("SuspiciousToArrayCall")
                 final CoordinateOperation[] asArray = children.toArray(new CoordinateOperation[children.size()]);
-                initialize(properties, asArray, flattened, (step == null) ? mtFactory : null,
setAccuracy, setDomain);
+                initialize(properties, asArray, flattened, (step == null) ? mtFactory : null,
false, setAccuracy, setDomain);
             } else if (!step.isIdentity()) {
                 flattened.add(op);
             }
-            if (mtFactory != null) {
+            if (mtFactory != null && step != null) {
                 transform = (transform != null) ? mtFactory.createConcatenatedTransform(transform,
step) : step;
             }
             /*
@@ -248,6 +271,7 @@ final class DefaultConcatenatedOperation
                 }
             }
         }
+        return previous;
     }
 
     /**
@@ -388,7 +412,6 @@ final class DefaultConcatenatedOperation
      * Returns the operations to marshal. We use this private methods instead than annotating
      * {@link #getOperations()} in order to force JAXB to invoke the setter method on unmarshalling.
      */
-    @SuppressWarnings("SuspiciousToArrayCall")
     @XmlElement(name = "coordOperation", required = true)
     private CoordinateOperation[] getSteps() {
         final List<? extends CoordinateOperation> operations = getOperations();
@@ -399,9 +422,6 @@ final class DefaultConcatenatedOperation
      * Invoked by JAXB for setting the operations.
      */
     private void setSteps(final CoordinateOperation[] steps) throws FactoryException {
-        final List<CoordinateOperation> flattened = new ArrayList<>(steps.length);
-        initialize(null, steps, flattened, DefaultFactories.forBuildin(MathTransformFactory.class),
-                (coordinateOperationAccuracy == null), (domainOfValidity == null));
-        operations = UnmodifiableArrayList.wrap(flattened.toArray(new CoordinateOperation[flattened.size()]));
+        initialize(null, steps, DefaultFactories.forBuildin(MathTransformFactory.class));
     }
 }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java?rev=1813110&r1=1813109&r2=1813110&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
[UTF-8] Mon Oct 23 22:46:16 2017
@@ -20,6 +20,7 @@ import java.util.Map;
 import java.util.HashMap;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import java.util.ServiceLoader;
 import org.opengis.util.FactoryException;
 import org.opengis.util.NoSuchIdentifierException;
@@ -44,6 +45,8 @@ import org.apache.sis.internal.util.Coll
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.internal.referencing.LazySet;
 import org.apache.sis.referencing.CRS;
+import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.referencing.AbstractIdentifiedObject;
 import org.apache.sis.referencing.factory.InvalidGeodeticParameterException;
 import org.apache.sis.referencing.operation.transform.AbstractMathTransform;
 import org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
@@ -676,6 +679,13 @@ next:   for (int i=components.size(); --
     public CoordinateOperation createConcatenatedOperation(final Map<String,?> properties,
             final CoordinateOperation... operations) throws FactoryException
     {
+        /*
+         * If the user specified a single operation, there is no need to create a ConcatenatedOperation;
+         * the operation to return will be the specified one. The metadata given in argument
are ignored
+         * on the assumption that the single operation has more complete metadata (in particular
an EPSG
+         * code, in which case we do not want to modify any other metadata in order to stay
compliant
+         * with EPSG definition).
+         */
         if (operations != null && operations.length == 1) {
             return operations[0];
         }
@@ -688,14 +698,39 @@ next:   for (int i=components.size(); --
         /*
          * Verifies again the number of single operations.  We may have a singleton if some
operations
          * were omitted because their associated math transform were identity. This happen
for example
-         * if a "Geographic 3D to 2D conversion" as been redimensioned to a "3D to 3D" operation.
+         * if a "Geographic 3D to 2D conversion" has been redimensioned to a "3D to 3D" operation.
          */
         final List<? extends CoordinateOperation> co = op.getOperations();
-        if (co.size() == 1) {
-            assert op.getMathTransform().equals(co.get(0).getMathTransform()) : op;
-            return co.get(0);
+        if (co.size() != 1) {
+            return pool.unique(op);
         }
-        return pool.unique(op);
+        final CoordinateOperation single = co.get(0);
+        assert op.getMathTransform().equals(single.getMathTransform()) : op;
+        if (!Objects.equals(single.getSourceCRS(), op.getSourceCRS()) ||
+            !Objects.equals(single.getTargetCRS(), op.getTargetCRS()))
+        {
+            /*
+             * The CRS of the single operation may be different than the CRS of the concatenated
operation
+             * if the first or the last operation was an identity operation. It happens for
example if the
+             * sole purpose of an operation step was to change the longitude range from [-180
… +180]° to
+             * [0 … 360]°: the MathTransform is identity (because Apache SIS does not
handle those changes
+             * in MathTransform; we handle that elsewhere, for example in the Envelopes utility
class),
+             * but omitting the transform should not cause the lost of the CRS with desired
longitude range.
+             */
+            if (single instanceof SingleOperation) {
+                final Map<String,Object> merge = new HashMap<>(
+                        IdentifiedObjects.getProperties(single, CoordinateOperation.IDENTIFIERS_KEY));
+                merge.put(ReferencingServices.PARAMETERS_KEY, ((SingleOperation) single).getParameterValues());
+                if (single instanceof AbstractIdentifiedObject) {
+                    merge.put(ReferencingServices.OPERATION_TYPE_KEY, ((AbstractIdentifiedObject)
single).getInterface());
+                }
+                merge.putAll(properties);
+                return createSingleOperation(merge, op.getSourceCRS(), op.getTargetCRS(),
+                        AbstractCoordinateOperation.getInterpolationCRS(op),
+                        ((SingleOperation) single).getMethod(), single.getMathTransform());
+            }
+        }
+        return single;
     }
 
     /**

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/EnvelopesTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/EnvelopesTest.java?rev=1813110&r1=1813109&r2=1813110&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/EnvelopesTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/geometry/EnvelopesTest.java
[UTF-8] Mon Oct 23 22:46:16 2017
@@ -190,11 +190,33 @@ public final strictfp class EnvelopesTes
     @Test
     @DependsOnMethod("testAxisRangeChange")
     public void testAxisRangeChange3D() throws FactoryException, TransformException {
+        testAxisRangeChange3D(HardCodedCRS.WGS84);
+    }
+
+    /**
+     * Tests a change of longitude axis range together with change of ellipsoid. This is
the same test
+     * than {@link #testAxisRangeChange3D()} with an additional complexity: a change of ellipsoid.
+     * This causes the execution of different code branches in {@code ConcatenatedOperation}
creation.
+     *
+     * @throws FactoryException if an error occurred while creating the operation.
+     * @throws TransformException if an error occurred while transforming the envelope.
+     *
+     * @since 0.8
+     */
+    @Test
+    @DependsOnMethod("testAxisRangeChange3D")
+    public void testAxisRangeChangeWithDatumShift() throws FactoryException, TransformException
{
+        testAxisRangeChange3D(HardCodedCRS.SPHERE);
+    }
+
+    /**
+     * Implementation of {@link #testAxisRangeChange3D()} and {@link #testAxisRangeChangeWithDatumShift()}.
+     */
+    private void testAxisRangeChange3D(final GeographicCRS targetCRS) throws FactoryException,
TransformException {
         final GeneralEnvelope envelope  = new GeneralEnvelope(new double[] { -0.5, -90, 1000},
                                                               new double[] {354.5, +90, 1002});
         envelope.setCoordinateReferenceSystem(CRS.compound(
                 HardCodedCRS.WGS84.forConvention(AxesConvention.POSITIVE_RANGE), HardCodedCRS.TIME));
-        final GeographicCRS  targetCRS = HardCodedCRS.WGS84;
         final GeneralEnvelope expected = createFromExtremums(targetCRS, -0.5, -90, -5.5,
90);
         assertEnvelopeEquals(expected, Envelopes.transform(envelope, targetCRS), STRICT,
STRICT);
         /*



Mime
View raw message