sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1794062 - in /sis/branches/JDK8/core/sis-referencing/src: main/java/org/apache/sis/internal/referencing/ main/java/org/apache/sis/internal/referencing/provider/ main/java/org/apache/sis/referencing/factory/sql/ main/java/org/apache/sis/ref...
Date Fri, 05 May 2017 14:37:59 GMT
Author: desruisseaux
Date: Fri May  5 14:37:58 2017
New Revision: 1794062

URL: http://svn.apache.org/viewvc?rev=1794062&view=rev
Log:
Fix errors when creating a geographic 3D CRS defined in the EPSG database as a CRS derived
from three-dimensional geocentric CRS using the "Geographic/geocentric conversions" operation
method.

Added:
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/CoordinateOperationTest.java
  (with props)
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicToGeocentric.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/CoordinateOperationSet.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/transform/DefaultMathTransformFactory.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/ConsistencyTest.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java?rev=1794062&r1=1794061&r2=1794062&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.java
[UTF-8] Fri May  5 14:37:58 2017
@@ -275,6 +275,11 @@ public final class Resources extends Ind
         public static final short MissingInterpolationOrdinates = 41;
 
         /**
+         * Missing parameter values for “{0}” coordinate operation.
+         */
+        public static final short MissingParameterValues_1 = 74;
+
+        /**
          * No spatial or temporal dimension found in “{0}”
          */
         public static final short MissingSpatioTemporalDimension_1 = 42;

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties?rev=1794062&r1=1794061&r2=1794062&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources.properties
[ISO-8859-1] Fri May  5 14:37:58 2017
@@ -73,6 +73,7 @@ MissingHorizontalDimension_1      = No h
 MissingVerticalDimension_1        = No vertical dimension found in \u201c{0}\u201d
 MissingTemporalDimension_1        = No temporal dimension found in \u201c{0}\u201d
 MissingSpatioTemporalDimension_1  = No spatial or temporal dimension found in \u201c{0}\u201d
+MissingParameterValues_1          = Missing parameter values for \u201c{0}\u201d coordinate
operation.
 MissingValueForParameter_1        = Missing value for \u201c{0}\u201d parameter.
 NoConvergence                     = No convergence.
 NoConvergenceForPoints_2          = No convergence for points {0} and {1}.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties?rev=1794062&r1=1794061&r2=1794062&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/Resources_fr.properties
[ISO-8859-1] Fri May  5 14:37:58 2017
@@ -78,6 +78,7 @@ MissingHorizontalDimension_1      = Aucu
 MissingVerticalDimension_1        = Aucune dimension verticale n\u2019a \u00e9t\u00e9 trouv\u00e9e
dans \u00ab\u202f{0}\u202f\u00bb.
 MissingTemporalDimension_1        = Aucune dimension temporelle n\u2019a \u00e9t\u00e9 trouv\u00e9e
dans \u00ab\u202f{0}\u202f\u00bb.
 MissingSpatioTemporalDimension_1  = Aucune dimension spatiale ou temporelle n\u2019a \u00e9t\u00e9
trouv\u00e9e dans \u00ab\u202f{0}\u202f\u00bb.
+MissingParameterValues_1          = Il manque les valeurs des param\u00e8tres pour l\u2019op\u00e9ration
\u00ab\u202f{0}\u202f\u00bb.
 MissingValueForParameter_1        = Aucune valeur n\u2019a \u00e9t\u00e9 d\u00e9finie pour
le param\u00e8tre \u00ab\u202f{0}\u202f\u00bb.
 NoConvergence                     = Le calcul ne converge pas.
 NoConvergenceForPoints_2          = Le calcul ne converge pas pour les points {0} et {1}.

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java?rev=1794062&r1=1794061&r2=1794062&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/AbstractProvider.java
[UTF-8] Fri May  5 14:37:58 2017
@@ -34,6 +34,7 @@ import org.apache.sis.metadata.iso.citat
 import org.apache.sis.parameter.ParameterBuilder;
 import org.apache.sis.referencing.operation.DefaultOperationMethod;
 import org.apache.sis.referencing.operation.transform.MathTransformProvider;
+import org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
 import org.apache.sis.util.resources.Vocabulary;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.Workaround;
@@ -43,7 +44,7 @@ import org.apache.sis.util.Workaround;
  * Base class for all providers defined in this package.
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.7
+ * @version 0.8
  * @since   0.6
  * @module
  */
@@ -185,6 +186,28 @@ public abstract class AbstractProvider e
     }
 
     /**
+     * If an operation method is ambiguous according Apache SIS, returns the name of the
method that SIS should use.
+     * Otherwise returns {@code null}. The ambiguities that need to be resolved are:
+     *
+     * <ul>
+     *   <li>Method <cite>"Geographic/geocentric conversions"</cite> (EPSG:9602)
can be either:
+     *     <ul>
+     *       <li>{@code "Ellipsoid_To_Geocentric"} (implemented by {@link GeographicToGeocentric}</li>
+     *       <li>{@code "Geocentric_To_Ellipsoid"} (implemented by {@link GeocentricToGeographic}</li>
+     *     </ul>
+     *   </li>
+     * </ul>
+     *
+     * @param  context   the potentially ambiguous context.
+     * @return name of the provider to use, or {@code null} if there is nothing to change.
+     *
+     * @since 0.8
+     */
+    public String resolveAmbiguity(final DefaultMathTransformFactory.Context context) {
+        return null;
+    }
+
+    /**
      * Flags whether the source and/or target ellipsoid are concerned by this operation.
This method is invoked by
      * {@link org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory}
for determining if this
      * operation has {@code "semi_major"}, {@code "semi_minor"}, {@code "src_semi_major"},
{@code "src_semi_minor"}

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicToGeocentric.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicToGeocentric.java?rev=1794062&r1=1794061&r2=1794062&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicToGeocentric.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeographicToGeocentric.java
[UTF-8] Fri May  5 14:37:58 2017
@@ -22,10 +22,13 @@ import org.opengis.util.FactoryException
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.parameter.ParameterValue;
+import org.opengis.referencing.cs.CartesianCS;
+import org.opengis.referencing.cs.EllipsoidalCS;
 import org.opengis.referencing.operation.Conversion;
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.MathTransformFactory;
 import org.apache.sis.referencing.operation.transform.EllipsoidToCentricTransform;
+import org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.internal.util.Constants;
 
@@ -35,7 +38,7 @@ import org.apache.sis.internal.util.Cons
  * This provider creates transforms from geographic to geocentric coordinate reference systems.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.7
+ * @version 0.8
  *
  * @see GeocentricToGeographic
  *
@@ -85,6 +88,28 @@ public final class GeographicToGeocentri
     }
 
     /**
+     * If the user asked for the <cite>"Geographic/geocentric conversions"</cite>
operation but the parameter types
+     * suggest that (s)he intended to convert in the opposite direction, return the name
of operation method to use.
+     * We need this check because EPSG defines a single operation method for both {@code
"Ellipsoid_To_Geocentric"}
+     * and {@code "Geocentric_To_Ellipsoid"} methods.
+     *
+     * <p><b>Note:</b>  we do not define similar method in {@link GeocentricToGeographic}
class because the only
+     * way to obtain that operation method is to ask explicitely for {@code "Geocentric_To_Ellipsoid"}
operation.
+     * The ambiguity that we try to resolve here exists only if the user asked for the EPSG:9602
operation, which
+     * is defined only in this class.</p>
+     *
+     * @return {@code "Geocentric_To_Ellipsoid"} if the user apparently wanted to get the
inverse of this
+     *         {@code "Ellipsoid_To_Geocentric"} operation, or {@code null} if none.
+     */
+    @Override
+    public String resolveAmbiguity(final DefaultMathTransformFactory.Context context) {
+        if (context.getSourceCS() instanceof CartesianCS && context.getTargetCS()
instanceof EllipsoidalCS) {
+            return GeocentricToGeographic.NAME;
+        }
+        return super.resolveAmbiguity(context);
+    }
+
+    /**
      * Notifies {@code DefaultMathTransformFactory} that Geographic/geocentric conversions
      * require values for the {@code "semi_major"} and {@code "semi_minor"} parameters.
      *

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/CoordinateOperationSet.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/CoordinateOperationSet.java?rev=1794062&r1=1794061&r2=1794062&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/CoordinateOperationSet.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/factory/sql/CoordinateOperationSet.java
[UTF-8] Fri May  5 14:37:58 2017
@@ -21,7 +21,9 @@ import java.util.HashMap;
 import org.opengis.metadata.Identifier;
 import org.opengis.util.FactoryException;
 import org.opengis.referencing.AuthorityFactory;
+import org.opengis.referencing.crs.GeneralDerivedCRS;
 import org.opengis.referencing.crs.CRSAuthorityFactory;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.operation.CoordinateOperation;
 import org.opengis.referencing.operation.CoordinateOperationAuthorityFactory;
 import org.apache.sis.metadata.iso.citation.Citations;
@@ -32,9 +34,31 @@ import org.apache.sis.referencing.factor
 /**
  * A lazy set of {@link CoordinateOperation} objects to be returned by the
  * {@link EPSGDataAccess#createFromCoordinateReferenceSystemCodes(String, String)} method.
+ * There is two different ways in which {@link EPSGDataAccess} get coordinate operations:
  *
- * @author  Martin Desruisseaux (IRD)
- * @version 0.7
+ * <ol>
+ *   <li>The coordinate operation may be the <cite>conversion from base</cite>
property of a projected CRS.
+ *       Those conversions are obtained by a SQL query like below (note that this query can
return at most
+ *       one result, because {@code COORD_REF_SYS_CODE} is a primary key):
+ *
+ *       {@preformat sql
+ *         SELECT PROJECTION_CONV_CODE FROM "Coordinate Reference System" WHERE SOURCE_GEOGCRS_CODE
= ? AND COORD_REF_SYS_CODE = ?
+ *       }
+ *   </li>
+ *
+ *   <li>The coordinate operation may be standalone. This is the case of coordinate
transformations having stochastic errors.
+ *       Those transformations are obtained by a SQL query like below (note that this query
can return many results):
+ *
+ *       {@preformat sql
+ *         SELECT COORD_OP_CODE FROM "Coordinate_Operation" … WHERE … AND SOURCE_CRS_CODE
= ? AND TARGET_CRS_CODE = ?
+ *       }
+ *   </li>
+ * </ol>
+ *
+ * We distinguish those two cases by the presence or absence of a coordinate operation code
in the {@link #projections} map.
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @version 0.8
  * @since   0.7
  * @module
  */
@@ -42,6 +66,15 @@ final class CoordinateOperationSet exten
     /**
      * The codes of {@link org.opengis.referencing.crs.ProjectedCRS} objects for
      * the specified {@link org.opengis.referencing.operation.Conversion} codes.
+     *
+     * <ul>
+     *   <li>Keys a coordinate operation codes.</li>
+     *   <li>Values are coordinate reference system codes. They are usually {@code
ProjectedCRS},
+     *       but the EPSG database sometime use this mechanisms for other kind of CRS.</li>
+     * </ul>
+     *
+     * This map does <strong>not</strong> contain all operations to be returned
by this {@code CoordinateOperationSet},
+     * but only the ones to be returned by the first SQL query documented in the class Javadoc.
      */
     private final Map<String,Integer> projections;
 
@@ -77,15 +110,40 @@ final class CoordinateOperationSet exten
     }
 
     /**
-     * Creates an object for the specified code.
+     * Creates a coordinate operation for the specified EPSG code.
      */
     @Override
     protected CoordinateOperation createObject(final String code) throws FactoryException
{
-        final Integer crs = projections.get(code);
-        if (crs != null) {
-            return ((CRSAuthorityFactory) factory).createProjectedCRS(String.valueOf(crs)).getConversionFromBase();
-        } else {
-            return ((CoordinateOperationAuthorityFactory) factory).createCoordinateOperation(code);
+        final Integer base = projections.get(code);
+        if (base != null) {
+            /*
+             * First case documented in class Javadoc:
+             *
+             *     SELECT PROJECTION_CONV_CODE FROM "Coordinate Reference System" …
+             *
+             * The result is usually a ProjectedCRS, but not always.
+             */
+            CoordinateReferenceSystem crs;
+            crs = ((CRSAuthorityFactory) factory).createCoordinateReferenceSystem(String.valueOf(base));
+            if (crs instanceof GeneralDerivedCRS) {
+                return ((GeneralDerivedCRS) crs).getConversionFromBase();
+            }
         }
+        /*
+         * Following line is either for the second case documented in class Javadoc, or the
first case
+         * when the result is not a derived CRS. Note that we could create a derived CRS
here as below:
+         *
+         *     CoordinateOperation op = …,
+         *     if (crs != null && op instanceof Conversion) {
+         *         return DefaultDerivedCRS.create(IdentifiedObjects.getProperties(crs),
baseCRS,
+         *                 (Conversion) op, crs.getCoordinateSystem()).getConversionFromBase();
+         *     }
+         *
+         * We don't do that for now because because EPSGDataAccess.createCoordinateReferenceSystem(String)
+         * would be a better place, by generalizing the work done for ProjectedCRS.
+         *
+         * https://issues.apache.org/jira/browse/SIS-357
+         */
+        return ((CoordinateOperationAuthorityFactory) factory).createCoordinateOperation(code);
     }
 }

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=1794062&r1=1794061&r2=1794062&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] Fri May  5 14:37:58 2017
@@ -407,13 +407,13 @@ class CoordinateOperationRegistry {
             } finally {
                 Semaphores.clear(Semaphores.METADATA_ONLY);
             }
-        } catch (NoSuchAuthorityCodeException | MissingFactoryResourceException exception)
{
+        } catch (NoSuchAuthorityCodeException | MissingFactoryResourceException e) {
             /*
              * sourceCode or targetCode is unknown to the underlying authority factory.
              * Ignores the exception and fallback on the generic algorithm provided by
              * CoordinateOperationFinder.
              */
-            log(exception);
+            log(null, e);
             return null;
         }
         /*
@@ -490,6 +490,14 @@ class CoordinateOperationRegistry {
                 if (bestChoice instanceof DeferredCoordinateOperation) {
                     bestChoice = ((DeferredCoordinateOperation) bestChoice).create();
                 }
+                if (bestChoice instanceof SingleOperation && bestChoice.getMathTransform()
== null) {
+                    bestChoice = fromDefiningConversion((SingleOperation) bestChoice,
+                                                        inverse ? targetCRS : sourceCRS,
+                                                        inverse ? sourceCRS : targetCRS);
+                    if (bestChoice == null) {
+                        return null;
+                    }
+                }
                 if (inverse) {
                     bestChoice = inverse(bestChoice);
                 }
@@ -510,7 +518,7 @@ class CoordinateOperationRegistry {
                     removed = operations.remove(deferred);
                 }
                 if (removed) {
-                    log(e);
+                    log(null, e);
                     continue;                                   // Try again with the next
best case.
                 }
                 // Should never happen, but if happen anyway we should fail for avoiding
never-ending loop.
@@ -654,6 +662,12 @@ class CoordinateOperationRegistry {
                                                   final MathTransformFactory      mtFactory)
             throws IllegalArgumentException, IncommensurableException, FactoryException
     {
+        /*
+         * Assertion: source and target CRS must be equals, ignoring change in axis order
or units.
+         * The first line is for disabling this check if the number of dimensions are not
the same
+         * (e.g. as in the "geographic 3D to geographic 2D" conversion) because ALLOW_VARIANT
mode
+         * still requires a matching number of dimensions.
+         */
         assert ReferencingUtilities.getDimension(sourceCRS) != ReferencingUtilities.getDimension(targetCRS)
                 || Utilities.deepEquals(sourceCRS, targetCRS, ComparisonMode.ALLOW_VARIANT);
         final Matrix m = CoordinateSystems.swapAndScaleAxes(sourceCRS.getCoordinateSystem(),
targetCRS.getCoordinateSystem());
@@ -796,6 +810,42 @@ class CoordinateOperationRegistry {
     }
 
     /**
+     * Creates a complete coordinate operation from a defining conversion. Defining conversions
usually have
+     * null source and target CRS, but this method nevertheless checks that, in order to
reuse the operation
+     * CRS if it happens to have some.
+     *
+     * @param  operation  the operation specified by the authority.
+     * @param  sourceCRS  the source CRS specified by the user.
+     * @param  targetCRS  the target CRS specified by the user
+     * @return a new operation from the given source CRS to target CRS.
+     * @throws FactoryException if an error occurred while creating the new operation.
+     */
+    private CoordinateOperation fromDefiningConversion(final SingleOperation     operation,
+                                                       CoordinateReferenceSystem sourceCRS,
+                                                       CoordinateReferenceSystem targetCRS)
+            throws FactoryException
+    {
+        final ParameterValueGroup parameters = operation.getParameterValues();
+        if (parameters != null) {
+            CoordinateReferenceSystem crs;
+            if (Utilities.equalsApproximatively(sourceCRS, crs = operation.getSourceCRS()))
sourceCRS = crs;
+            if (Utilities.equalsApproximatively(targetCRS, crs = operation.getTargetCRS()))
targetCRS = crs;
+            final MathTransformFactory mtFactory = factorySIS.getMathTransformFactory();
+            if (mtFactory instanceof DefaultMathTransformFactory) {
+                MathTransform mt = ((DefaultMathTransformFactory) mtFactory).createParameterizedTransform(
+                        parameters, ReferencingUtilities.createTransformContext(sourceCRS,
targetCRS, null));
+                return factorySIS.createSingleOperation(IdentifiedObjects.getProperties(operation),
+                        sourceCRS, targetCRS, null, operation.getMethod(), mt);
+            }
+        } else {
+            // Should never happen because parameters are mandatory, but let be safe.
+            log(Resources.forLocale(null).getLogRecord(Level.WARNING, Resources.Keys.MissingParameterValues_1,
+                    IdentifiedObjects.getIdentifierOrName(operation)), null);
+        }
+        return null;
+    }
+
+    /**
      * Returns a new coordinate operation with the ellipsoidal height added either in the
source coordinates,
      * in the target coordinates or both. If there is an ellipsoidal transform, then this
method updates the
      * transforms in order to use the ellipsoidal height (it has an impact on the transformed
values).
@@ -905,7 +955,7 @@ class CoordinateOperationRegistry {
                                     ((SingleOperation) op).getParameterValues(),
                                     ReferencingUtilities.createTransformContext(sourceCRS,
targetCRS, null));
                         } catch (InvalidGeodeticParameterException e) {
-                            log(e);
+                            log(null, e);
                             break;
                         }
                         operations.set(recreate(op, sourceCRS, targetCRS, mt, mtFactory.getLastMethodUsed()));
@@ -1121,10 +1171,13 @@ class CoordinateOperationRegistry {
      * come from {@link CoordinateOperationFinder} since this is the public API which
      * use this {@code CoordinateOperationRegistry} class.
      *
-     * @param exception  the exception which occurred.
+     * @param record     the record to log, or {@code null} for creating from the exception.
+     * @param exception  the exception which occurred, or {@code null} if a {@code record}
is specified instead.
      */
-    private static void log(final Exception exception) {
-        final LogRecord record = new LogRecord(Level.WARNING, exception.getLocalizedMessage());
+    private static void log(LogRecord record, final Exception exception) {
+        if (record == null) {
+            record = new LogRecord(Level.WARNING, exception.getLocalizedMessage());
+        }
         record.setLoggerName(Loggers.COORDINATE_OPERATION);
         /*
          * We usually do not log the stack trace since this method should be invoked only
for exceptions

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java?rev=1794062&r1=1794061&r2=1794062&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/DefaultMathTransformFactory.java
[UTF-8] Fri May  5 14:37:58 2017
@@ -848,7 +848,8 @@ public class DefaultMathTransformFactory
          * <p>The given method and parameters are stored in the {@link #provider} and
{@link #parameters}
          * fields respectively. The actual stored values may differ from the values given
to this method.</p>
          *
-         * @param  method  description of the transform to be created, or {@code null} if
unknown.
+         * @param  factory  the enclosing factory.
+         * @param  method   description of the transform to be created, or {@code null} if
unknown.
          * @return the exception if the operation failed, or {@code null} if none. This exception
is not thrown now
          *         because the caller may succeed in creating the transform anyway, or otherwise
may produce a more
          *         informative exception.
@@ -858,9 +859,23 @@ public class DefaultMathTransformFactory
          * @see #getCompletedParameters()
          */
         @SuppressWarnings("null")
-        final RuntimeException completeParameters(OperationMethod method, final ParameterValueGroup
userParams)
-                throws IllegalArgumentException
+        final RuntimeException completeParameters(final DefaultMathTransformFactory factory,
OperationMethod method,
+                final ParameterValueGroup userParams) throws FactoryException, IllegalArgumentException
         {
+            /*
+             * The "Geographic/geocentric conversions" conversion (EPSG:9602) can be either:
+             *
+             *    - "Ellipsoid_To_Geocentric"
+             *    - "Geocentric_To_Ellipsoid"
+             *
+             * EPSG defines both by a single operation, but Apache SIS needs to distinguish
them.
+             */
+            if (method instanceof AbstractProvider) {
+                final String alt = ((AbstractProvider) method).resolveAmbiguity(this);
+                if (alt != null) {
+                    method = factory.getOperationMethod(alt);
+                }
+            }
             provider   = method;
             parameters = userParams;
             /*
@@ -896,8 +911,8 @@ public class DefaultMathTransformFactory
                 if (targetEllipsoid != null) n |= 2;
             }
             /*
-             * Set the ellipsoid axis-length parameter values. Those parameters may appear
in the source
-             * ellipsoid, in the target ellipsoid or in both ellipsoids.
+             * Set the ellipsoid axis-length parameter values. Those parameters may appear
in the source ellipsoid,
+             * in the target ellipsoid or in both ellipsoids.
              */
             switch (n) {
                 case 0: return null;
@@ -1020,7 +1035,7 @@ public class DefaultMathTransformFactory
                  * since the standard place where to provide this information is in the ellipsoid
object.
                  */
                 if (context != null) {
-                    failure = context.completeParameters(method, parameters);
+                    failure    = context.completeParameters(this, method, parameters);
                     parameters = context.parameters;
                     method     = context.provider;
                 }
@@ -1048,8 +1063,10 @@ public class DefaultMathTransformFactory
             lastMethod.set(method);     // May be null in case of failure, which is intended.
             if (context != null) {
                 context.provider = null;
-                // For now we conservatively reset the provider information to null. But
if we choose to make
-                // that information public in a future SIS version, then we would remove
this code.
+                /*
+                 * For now we conservatively reset the provider information to null. But
if we choose to
+                 * make that information public in a future SIS version, then we would remove
this code.
+                 */
             }
         }
         return transform;

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/ConsistencyTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/ConsistencyTest.java?rev=1794062&r1=1794061&r2=1794062&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/ConsistencyTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/ConsistencyTest.java
[UTF-8] Fri May  5 14:37:58 2017
@@ -35,6 +35,7 @@ import org.apache.sis.io.wkt.Unformattab
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.Utilities;
+import org.apache.sis.test.DependsOn;
 import org.apache.sis.test.TestCase;
 import org.junit.Test;
 
@@ -57,13 +58,17 @@ import static org.junit.Assert.*;
  * @since   0.7
  * @module
  */
+@DependsOn({
+    org.apache.sis.referencing.CRSTest.class,
+    org.apache.sis.io.wkt.WKTFormatTest.class
+})
 public final strictfp class ConsistencyTest extends TestCase {
     /**
      * Codes to exclude for now.
      */
     private static final Set<String> EXCLUDES = new HashSet<>(Arrays.asList(
-            "CRS:1",            // Computer display
-            "EPSG:5819"         // EPSG topocentric example A
+        "CRS:1",            // Computer display
+        "EPSG:5819"         // EPSG topocentric example A
     ));
 
     /**

Added: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/CoordinateOperationTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/CoordinateOperationTest.java?rev=1794062&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/CoordinateOperationTest.java
(added)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/CoordinateOperationTest.java
[UTF-8] Fri May  5 14:37:58 2017
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.test.integration;
+
+import java.util.Random;
+import java.util.Collections;
+import org.opengis.util.FactoryException;
+import org.opengis.referencing.datum.Ellipsoid;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.CoordinateOperation;
+import org.opengis.referencing.operation.TransformException;
+import org.opengis.referencing.operation.CoordinateOperationFactory;
+import org.apache.sis.math.MathFunctions;
+import org.apache.sis.referencing.CommonCRS;
+import org.apache.sis.referencing.crs.AbstractCRS;
+import org.apache.sis.referencing.cs.AxesConvention;
+import org.apache.sis.referencing.datum.DefaultEllipsoid;
+import org.apache.sis.referencing.operation.transform.MathTransformTestCase;
+import org.apache.sis.internal.referencing.CoordinateOperations;
+import org.apache.sis.test.DependsOn;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+import static java.lang.StrictMath.*;
+
+
+/**
+ * Tests mixing use of EPSG dataset, change of axes convention, application of math transforms,
+ * orthodromic distances, <i>etc</i>.
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @version 0.8
+ * @since   0.8
+ * @module
+ */
+@DependsOn({
+    org.apache.sis.referencing.CRSTest.class,
+    org.apache.sis.referencing.CommonCRSTest.class,
+    org.apache.sis.referencing.datum.DefaultEllipsoidTest.class,
+    org.apache.sis.referencing.operation.DefaultCoordinateOperationFactoryTest.class,
+    org.apache.sis.referencing.operation.transform.EllipsoidToCentricTransformTest.class
+})
+public final strictfp class CoordinateOperationTest extends MathTransformTestCase {
+    /**
+     * The transformation factory to use for testing.
+     */
+    private final CoordinateOperationFactory opFactory;
+
+    /**
+     * Creates the test suite.
+     */
+    public CoordinateOperationTest() {
+        opFactory = CoordinateOperations.factory();
+    }
+
+    /**
+     * Tests a "geographic to geocentric" conversion.
+     *
+     * @throws FactoryException if an error occurred while creating a test CRS.
+     * @throws TransformException if an error occurred while testing a coordinate conversion.
+     */
+    @Test
+    public void testGeocentricTransform() throws FactoryException, TransformException {
+        final Random random = new Random(661597560);
+        /*
+         * Gets the math transform from WGS84 to a geocentric transform.
+         */
+        final Ellipsoid                 ellipsoid = CommonCRS.WGS84.ellipsoid();
+        final CoordinateReferenceSystem sourceCRS = AbstractCRS.castOrCopy(CommonCRS.WGS84.geographic3D()).forConvention(AxesConvention.RIGHT_HANDED);
+        final CoordinateReferenceSystem targetCRS = CommonCRS.WGS84.geocentric();
+        final CoordinateOperation       operation = opFactory.createOperation(sourceCRS,
targetCRS);
+        transform = operation.getMathTransform();
+        final int dimension = transform.getSourceDimensions();
+        assertEquals("Source dimension", 3, dimension);
+        assertEquals("Target dimension", 3, transform.getTargetDimensions());
+        assertSame("Inverse transform", transform, transform.inverse().inverse());
+        validate();
+        /*
+         * Constructs an array of random points. The first 8 points
+         * are initialized to know values. Other points are left random.
+         */
+        final double   cartesianDistance[] = new double[4];
+        final double orthodromicDistance[] = new double[4];
+        final double[] array0 = new double[900];                    // Must be divisible
by 3.
+        for (int i=0; i<array0.length; i++) {
+            final int range;
+            switch (i % 3) {
+                case 0:  range =   360; break;                      // Longitude
+                case 1:  range =   180; break;                      // Latitidue
+                case 2:  range = 10000; break;                      // Altitude
+                default: range =     0; break;                      // Should not happen
+            }
+            array0[i] = random.nextDouble() * range - (range/2);
+        }
+        array0[0]=35.0; array0[1]=24.0; array0[2]=8000;             // 24°N 35°E 8km
+        array0[3]=34.8; array0[4]=24.7; array0[5]=5000;             // … about 80 km away
+        cartesianDistance  [0] = 80284.00;
+        orthodromicDistance[0] = 80302.99;                          // Not really exact.
+
+        array0[6]=  0; array0[ 7]=0.0; array0[ 8]=0;
+        array0[9]=180; array0[10]=0.0; array0[11]=0;                // Antipodes; distance
should be 2*6378.137 km
+        cartesianDistance  [1] = ellipsoid.getSemiMajorAxis() * 2;
+        orthodromicDistance[1] = ellipsoid.getSemiMajorAxis() * PI;
+
+        array0[12]=  0; array0[13]=-90; array0[14]=0;
+        array0[15]=180; array0[16]=+90; array0[17]=0;               // Antipodes; distance
should be 2*6356.752 km
+        cartesianDistance  [2] = ellipsoid.getSemiMinorAxis() * 2;
+        orthodromicDistance[2] = 20003931.46;
+
+        array0[18]= 95; array0[19]=-38; array0[20]=0;
+        array0[21]=-85; array0[22]=+38; array0[23]=0;               // Antipodes
+        cartesianDistance  [3] = 12740147.19;
+        orthodromicDistance[3] = 20003867.86;
+        /*
+         * Transforms all points, and then inverse transform them. The resulting
+         * array2 should be equal to array0 except for rounding errors. We tolerate
+         * maximal error of 0.1 second in longitude or latitude and 1 cm in height.
+         */
+        final double[] array1 = new double[array0.length];
+        final double[] array2 = new double[array0.length];
+        transform          .transform(array0, 0, array1, 0, array0.length / dimension);
+        transform.inverse().transform(array1, 0, array2, 0, array1.length / dimension);
+        for (int i=0; i<array0.length;) {
+            assertEquals("Longitude", array2[i], array0[i], 0.1/3600); i++;
+            assertEquals("Latitude",  array2[i], array0[i], 0.1/3600); i++;
+            assertEquals("Height",    array2[i], array0[i], 0.01); i++;
+        }
+        /*
+         * Compares the distances between "special" points with expected distances.
+         * This tests the ellipsoid orthodromic distance computation as well.
+         * We require a precision of 10 centimetres.
+         */
+        for (int i=0; i < array0.length / 6; i++) {
+            final int base = i*6;
+            final double cartesian = MathFunctions.magnitude(
+                    array1[base+0] - array1[base+3],
+                    array1[base+1] - array1[base+4],
+                    array1[base+2] - array1[base+5]);
+            if (i < cartesianDistance.length) {
+                assertEquals("Cartesian distance", cartesianDistance[i], cartesian, 0.1);
+            }
+            /*
+             * Compares with orthodromic distance. Distance is computed using an ellipsoid
+             * at the maximal altitude (i.e. the length of semi-major axis is increased to
+             * fit the maximal altitude).
+             */
+            try {
+                final double altitude = max(array0[base+2], array0[base+5]);
+                final DefaultEllipsoid ellip = DefaultEllipsoid.createFlattenedSphere(
+                        Collections.singletonMap(Ellipsoid.NAME_KEY, "Temporary"),
+                        ellipsoid.getSemiMajorAxis() + altitude,
+                        ellipsoid.getInverseFlattening(),
+                        ellipsoid.getAxisUnit());
+                double orthodromic = ellip.orthodromicDistance(array0[base+0], array0[base+1],
+                                                               array0[base+3], array0[base+4]);
+                orthodromic = hypot(orthodromic, array0[base+2] - array0[base+5]);
+                if (i < orthodromicDistance.length) {
+                    assertEquals("Orthodromic distance", orthodromicDistance[i], orthodromic,
0.1);
+                }
+                assertTrue("Distance consistency", cartesian <= orthodromic);
+            } catch (ArithmeticException exception) {
+                // Orthodromic distance computation didn't converge. Ignore...
+            }
+        }
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/CoordinateOperationTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/integration/CoordinateOperationTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java?rev=1794062&r1=1794061&r2=1794062&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
[UTF-8] Fri May  5 14:37:58 2017
@@ -246,6 +246,7 @@ import org.junit.BeforeClass;
 
     org.apache.sis.distance.LatLonPointRadiusTest.class,        // Pending refactoring in
a geometry package.
 
+    org.apache.sis.test.integration.CoordinateOperationTest.class,
     org.apache.sis.test.integration.DatumShiftTest.class,
     org.apache.sis.test.integration.MetadataTest.class,
     org.apache.sis.test.integration.ConsistencyTest.class



Mime
View raw message