sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1734639 - in /sis/branches/JDK8/core: sis-referencing/src/main/java/org/apache/sis/referencing/operation/ sis-utility/src/main/java/org/apache/sis/util/resources/
Date Fri, 11 Mar 2016 22:59:03 GMT
Author: desruisseaux
Date: Fri Mar 11 22:59:03 2016
New Revision: 1734639

URL: http://svn.apache.org/viewvc?rev=1734639&view=rev
Log:
Begin the port of the code that infer a coordinate operation between two CRS.

Added:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java   (with props)
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
      - copied, changed from r1734638, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/OperationPathFinder.java
Removed:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/OperationPathFinder.java
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactory.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java?rev=1734639&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java [UTF-8] Fri Mar 11 22:59:03 2016
@@ -0,0 +1,133 @@
+/*
+ * 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.referencing.operation;
+
+import java.io.Serializable;
+import org.opengis.metadata.extent.GeographicBoundingBox;
+import org.apache.sis.util.ArgumentChecks;
+
+
+/**
+ * Optional information about the context in which a requested coordinate operation will be used.
+ * The context can provide information such as:
+ *
+ * <ul>
+ *   <li>The geographic area where the transformation will be used.</li>
+ *   <li>The desired accuracy. A coarser accuracy may allow SIS to choose a faster transformation method.</li>
+ * </ul>
+ *
+ * While optional, those information can help {@link DefaultCoordinateOperationFactory}
+ * to choose the most suitable coordinate transformation between two CRS.
+ *
+ * <div class="note"><b>Example:</b>
+ * if a transformation from NAD27 to NAD83 is requested without providing context, then Apache SIS will return the
+ * transformation applicable to the widest North American surface. But if the user provides a context saying that
+ * he wants to transform coordinates in Texas, then Apache SIS may return another coordinate transformation with
+ * different {@linkplain org.apache.sis.referencing.datum.BursaWolfParameters Bursa-Wolf parameters} more suitable
+ * to Texas, but not suitable to the rest of North-America.
+ * </div>
+ *
+ * {@code CoordinateOperationContext} is part of the API used by SIS for implementing the <cite>late binding</cite>
+ * model. See {@linkplain org.apache.sis.referencing.operation package javadoc} for a note on early binding versus
+ * late binding implementations.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @since   0.7
+ * @version 0.7
+ * @module
+ */
+public class CoordinateOperationContext implements Serializable {
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = -6944460471653277973L;
+
+    /**
+     * The area of interest, or {@code null} if none.
+     */
+    private GeographicBoundingBox areaOfInterest;
+
+    /**
+     * The desired accuracy in metres, or 0 for the best accuracy available.
+     * See {@link #getDesiredAccuracy()} for more details about what we mean by <cite>"best accuracy"</cite>.
+     */
+    private double desiredAccuracy;
+
+    /**
+     * Creates a new context with no area of interest and the best accuracy available.
+     */
+    public CoordinateOperationContext() {
+    }
+
+    /**
+     * Creates a new context with the given area of interest and desired accuracy.
+     *
+     * @param area     The area of interest, or {@code null} if none.
+     * @param accuracy The desired accuracy in metres, or 0 for the best accuracy available.
+     * See {@link #getDesiredAccuracy()} for more details about what we mean by <cite>"best accuracy"</cite>.
+     */
+    public CoordinateOperationContext(final GeographicBoundingBox area, final double accuracy) {
+        ArgumentChecks.ensurePositive("accuracy", accuracy);
+        areaOfInterest  = area;
+        desiredAccuracy = accuracy;
+    }
+
+    /**
+     * Returns the geographic area of interest, or {@code null} if none.
+     *
+     * @return The area of interest, or {@code null} if none.
+     */
+    public GeographicBoundingBox getAreaOfInterest() {
+        return areaOfInterest;
+    }
+
+    /**
+     * Sets the geographic area of interest, or {@code null} if none.
+     *
+     * @param area The area of interest, or {@code null} if none.
+     */
+    public void setAreaOfInterest(final GeographicBoundingBox area) {
+        areaOfInterest = area;
+    }
+
+    /**
+     * Returns the desired accuracy in metres.
+     * A value of 0 means to search for the most accurate operation.
+     *
+     * <p>When searching for the most accurate operation, SIS considers only the operations specified by the authority.
+     * For example the <cite>Molodensky</cite> method is a better datum shift approximation than <cite>Abridged Molodensky</cite>.
+     * But if all coordinate operations defined by the authority use the Abridged Molodensky method, then SIS will ignore
+     * the Molodensky one.</p>
+     *
+     * @return The desired accuracy in metres.
+     */
+    public double getDesiredAccuracy() {
+        return desiredAccuracy;
+    }
+
+    /**
+     * Sets the desired accuracy in metres.
+     * A value of 0 means to search for the most accurate operation.
+     * See {@link #getDesiredAccuracy()} for more details about what we mean by <cite>"most accurate"</cite>.
+     *
+     * @param accuracy The desired accuracy in metres.
+     */
+    public void setDesiredAccuracy(final double accuracy) {
+        ArgumentChecks.ensurePositive("accuracy", accuracy);
+        desiredAccuracy = accuracy;
+    }
+}

Propchange: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationContext.java
------------------------------------------------------------------------------
    svn:eol-style = native

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

Copied: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java (from r1734638, sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/OperationPathFinder.java)
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java?p2=sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java&p1=sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/OperationPathFinder.java&r1=1734638&r2=1734639&rev=1734639&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/OperationPathFinder.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java [UTF-8] Fri Mar 11 22:59:03 2016
@@ -16,57 +16,463 @@
  */
 package org.apache.sis.referencing.operation;
 
-import java.util.List;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import javax.measure.unit.NonSI;
+import org.opengis.metadata.Identifier;
+import org.opengis.util.FactoryException;
 import org.opengis.referencing.crs.*;
-import org.opengis.referencing.datum.Datum;
+import org.opengis.referencing.operation.CoordinateOperation;
+import org.opengis.referencing.operation.OperationNotFoundException;
+import org.opengis.metadata.extent.GeographicBoundingBox;
+import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.referencing.IdentifiedObject;
+import org.opengis.referencing.datum.PrimeMeridian;
+import org.opengis.referencing.operation.Conversion;
+import org.opengis.referencing.operation.CoordinateOperationFactory;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.MathTransformFactory;
+import org.opengis.referencing.operation.OperationMethod;
+import org.opengis.referencing.operation.SingleOperation;
+import org.apache.sis.internal.metadata.ReferencingServices;
+import org.apache.sis.internal.referencing.Formulas;
+import org.apache.sis.internal.referencing.ReferencingUtilities;
+import org.apache.sis.internal.system.DefaultFactories;
+import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.metadata.iso.extent.Extents;
+import org.apache.sis.parameter.Parameterized;
 import org.apache.sis.referencing.CRS;
-import org.apache.sis.util.Utilities;
+import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.referencing.NamedIdentifier;
+import org.apache.sis.referencing.datum.BursaWolfParameters;
+import org.apache.sis.util.ArgumentChecks;
+import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.Classes;
+import org.apache.sis.util.resources.Errors;
+import org.apache.sis.util.resources.Vocabulary;
 
 
 /**
  * Infers a conversion of transformation path from a source CRS to a target CRS.
  *
- * This is currently only a placeholder for future SIS development (code to be ported from Geotk).
+ * <div class="section">Limitations</div>
+ * <ul>
+ *   <li>Each instance of this class shall be used only once.</li>
+ *   <li>This class is not thread-safe. A new instance shall be created for each coordinate operation to infer.</li>
+ * </ul>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @since   0.6
- * @version 0.6
+ * @since   0.7
+ * @version 0.7
  * @module
  */
-final class OperationPathFinder {
-    private OperationPathFinder() {
+public class CoordinateOperationInference {
+    /**
+     * The identifier for an identity operation.
+     */
+    private static final Identifier IDENTITY = createIdentifier(Vocabulary.Keys.Identity);
+
+    /**
+     * The identifier for conversion using an affine transform for axis swapping and/or unit conversions.
+     */
+    private static final Identifier AXIS_CHANGES = createIdentifier(Vocabulary.Keys.AxisChanges);
+
+    /**
+     * The identifier for a transformation which is a datum shift without {@link BursaWolfParameters}.
+     * Only the changes in ellipsoid axis-length are taken in account.
+     * Such ellipsoid shifts are approximative and may have 1 kilometre error.
+     *
+     * @see org.apache.sis.internal.referencing.PositionalAccuracyConstan#DATUM_SHIFT_OMITTED
+     */
+    private static final Identifier ELLIPSOID_CHANGE = createIdentifier(Vocabulary.Keys.EllipsoidChange);
+
+    /**
+     * The identifier for a transformation which is a datum shift.
+     *
+     * @see org.apache.sis.internal.referencing.PositionalAccuracyConstant#DATUM_SHIFT_APPLIED
+     */
+    private static final Identifier DATUM_SHIFT = createIdentifier(Vocabulary.Keys.DatumShift);
+
+    /**
+     * The identifier for a geocentric conversion.
+     */
+    private static final Identifier GEOCENTRIC_CONVERSION = createIdentifier(Vocabulary.Keys.GeocentricConversion);
+
+    /**
+     * The identifier for an inverse operation.
+     */
+    private static final Identifier INVERSE_OPERATION = createIdentifier(Vocabulary.Keys.InverseOperation);
+
+    /**
+     * Creates an identifier in the Apache SIS namespace for the given vocabulary key.
+     */
+    private static Identifier createIdentifier(final short key) {
+        return new NamedIdentifier(Citations.SIS, Vocabulary.formatInternational(key));
+    }
+
+    /**
+     * The factory to use for creating coordinate operations.
+     */
+    private final CoordinateOperationFactory factory;
+
+    /**
+     * Used only when we need a SIS-specific method.
+     */
+    private final DefaultCoordinateOperationFactory factorySIS;
+
+    /**
+     * The area of interest, or {@code null} if none.
+     */
+    private GeographicBoundingBox areaOfInterest;
+
+    /**
+     * The desired accuracy in metres, or 0 for the best accuracy available.
+     */
+    private double desiredAccuracy;
+
+    /**
+     * Creates a new instance for the given factory and context.
+     *
+     * @param factory The factory to use for creating coordinate operations.
+     * @param context The area of interest and desired accuracy, or {@code null} if none.
+     */
+    public CoordinateOperationInference(final CoordinateOperationFactory factory,
+                                        final CoordinateOperationContext context)
+    {
+        ArgumentChecks.ensureNonNull("factory", factory);
+        this.factory = factory;
+        factorySIS = (factory instanceof DefaultCoordinateOperationFactory) ? (DefaultCoordinateOperationFactory) factory
+                : DefaultFactories.forBuildin(CoordinateOperationFactory.class, DefaultCoordinateOperationFactory.class);
+        if (context != null) {
+            areaOfInterest  = context.getAreaOfInterest();
+            desiredAccuracy = context.getDesiredAccuracy();
+        }
+    }
+
+    /**
+     * Infers an operation for conversion or transformation between two coordinate reference systems.
+     * This method inspects the given CRS and delegates the work to one or many {@code createOperationStep(…)} methods.
+     * This method fails if no path between the CRS is found.
+     *
+     * @param  sourceCRS Input coordinate reference system.
+     * @param  targetCRS Output coordinate reference system.
+     * @return A coordinate operation from {@code sourceCRS} to {@code targetCRS}.
+     * @throws OperationNotFoundException if no operation path was found from {@code sourceCRS} to {@code targetCRS}.
+     * @throws FactoryException if the operation creation failed for some other reason.
+     */
+    public CoordinateOperation createOperation(final CoordinateReferenceSystem sourceCRS,
+                                               final CoordinateReferenceSystem targetCRS)
+            throws OperationNotFoundException, FactoryException
+    {
+        ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
+        ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
+        if (areaOfInterest == null) {
+            areaOfInterest = Extents.intersection(CRS.getGeographicBoundingBox(sourceCRS),
+                                                  CRS.getGeographicBoundingBox(targetCRS));
+        }
+        ////////////////////////////////////////////////////////////////////////////////
+        ////                                                                        ////
+        ////                        Compound  →  various CRS                        ////
+        ////                                                                        ////
+        ////  We check CompoundCRS first because experience shows that it produces  ////
+        ////  simpler transformation chains than if we check them last.             ////
+        ////                                                                        ////
+        ////////////////////////////////////////////////////////////////////////////////
+        if (sourceCRS instanceof CompoundCRS) {
+            final CompoundCRS source = (CompoundCRS) sourceCRS;
+            if (targetCRS instanceof CompoundCRS) {
+//              return createOperationStep(source, (CompoundCRS) targetCRS);
+            }
+            if (targetCRS instanceof SingleCRS) {
+//              return createOperationStep(source, (SingleCRS) targetCRS);
+            }
+        }
+        if (targetCRS instanceof CompoundCRS) {
+            final CompoundCRS target = (CompoundCRS) targetCRS;
+            if (sourceCRS instanceof SingleCRS) {
+//              return createOperationStep((SingleCRS) sourceCRS, target);
+            }
+        }
+        ////////////////////////////////////////////////////////////////////////////////
+        ////                                                                        ////
+        ////                 Projected  →  Projected or Geographic                  ////
+        ////                                                                        ////
+        ////      This check needs to be done before the check for DerivedCRS       ////
+        ////      because ProjectedCRS is a particular kind of derived CRS.         ////
+        ////                                                                        ////
+        ////////////////////////////////////////////////////////////////////////////////
+        if (sourceCRS instanceof ProjectedCRS) {
+            final ProjectedCRS source = (ProjectedCRS) sourceCRS;
+            if (targetCRS instanceof ProjectedCRS) {
+//              return createOperationStep(source, (ProjectedCRS) targetCRS);
+            }
+            if (targetCRS instanceof GeographicCRS) {
+//              return createOperationStep(source, (GeographicCRS) targetCRS);
+            }
+        }
+        ////////////////////////////////////////////////////////////////////////////////
+        ////                                                                        ////
+        ////           Geographic  →  Geographic, Projected or Geocentric           ////
+        ////                                                                        ////
+        ////////////////////////////////////////////////////////////////////////////////
+        if (sourceCRS instanceof GeographicCRS) {
+            final GeographicCRS source = (GeographicCRS) sourceCRS;
+            if (targetCRS instanceof GeographicCRS) {
+//              return createOperationStep(source, (GeographicCRS) targetCRS);
+            }
+            if (targetCRS instanceof ProjectedCRS) {
+//              return createOperationStep(source, (ProjectedCRS) targetCRS);
+            }
+            if (targetCRS instanceof GeocentricCRS) {
+//              return createOperationStep(source, (GeocentricCRS) targetCRS);
+            }
+            if (targetCRS instanceof VerticalCRS) {
+//              return createOperationStep(source, (VerticalCRS) targetCRS);
+            }
+        }
+        ////////////////////////////////////////////////////////////////////////////////
+        ////                                                                        ////
+        ////                Geocentric  →  Geocentric or Geographic                 ////
+        ////                                                                        ////
+        ////////////////////////////////////////////////////////////////////////////////
+        if (sourceCRS instanceof GeocentricCRS) {
+            final GeocentricCRS source = (GeocentricCRS) sourceCRS;
+            if (targetCRS instanceof GeocentricCRS) {
+//              return createOperationStep(source, (GeocentricCRS) targetCRS);
+            }
+            if (targetCRS instanceof GeographicCRS) {
+//              return createOperationStep(source, (GeographicCRS) targetCRS);
+            }
+        }
+        ////////////////////////////////////////////////////////////////////////////////
+        ////                                                                        ////
+        ////                         Vertical  →  Vertical                          ////
+        ////                                                                        ////
+        ////////////////////////////////////////////////////////////////////////////////
+        if (sourceCRS instanceof VerticalCRS) {
+            final VerticalCRS source = (VerticalCRS) sourceCRS;
+            if (targetCRS instanceof VerticalCRS) {
+//              return createOperationStep(source, (VerticalCRS) targetCRS);
+            }
+        }
+        ////////////////////////////////////////////////////////////////////////////////
+        ////                                                                        ////
+        ////                         Temporal  →  Temporal                          ////
+        ////                                                                        ////
+        ////////////////////////////////////////////////////////////////////////////////
+        if (sourceCRS instanceof TemporalCRS) {
+            final TemporalCRS source = (TemporalCRS) sourceCRS;
+            if (targetCRS instanceof TemporalCRS) {
+//              return createOperationStep(source, (TemporalCRS) targetCRS);
+            }
+        }
+        throw new OperationNotFoundException(getErrorMessage(sourceCRS, targetCRS));
+    }
+
+    /**
+     * Returns {@code true} if the Greenwich longitude of the {@code actual} prime meridian is equals to the
+     * Greenwich longitude of the {@code expected} prime meridian. The comparison is performed in degrees.
+     *
+     * <p>A {@code null} argument is interpreted as "unknown prime meridian". Consequently this method
+     * unconditionally returns {@code false} if one or both arguments is {@code null}.</p>
+     *
+     * @param expected The expected prime meridian, or {@code null}.
+     * @param actual The actual prime meridian, or {@code null}.
+     * @return {@code true} if both prime meridians have the same Greenwich longitude.
+     */
+    private static boolean isGreenwichLongitudeEquals(final PrimeMeridian expected, final PrimeMeridian actual) {
+        if (expected == null || actual == null) {
+            return false;                               // See method javadoc.
+        }
+        if (expected == actual) {
+            return true;
+        }
+        final double diff = ReferencingUtilities.getGreenwichLongitude(expected, NonSI.DEGREE_ANGLE)
+                          - ReferencingUtilities.getGreenwichLongitude(actual,   NonSI.DEGREE_ANGLE);
+        return Math.abs(diff) <= Formulas.ANGULAR_TOLERANCE;
+    }
+
+    /**
+     * Returns {@code true} if the specified operation is an identity conversion.
+     * This method always returns {@code false} for transformations even if their
+     * associated math transform is an identity one, because such transformations
+     * are usually datum shift and must be visible.
+     */
+    private static boolean isIdentity(final CoordinateOperation operation) {
+        return (operation instanceof Conversion) && operation.getMathTransform().isIdentity();
     }
 
     /**
-     * Returns {@code true} if the given CRS are using equivalent (ignoring metadata) datum.
-     * If the CRS are {@link CompoundCRS}, then this method verifies that all datum in the
-     * target CRS exists in the source CRS, but not necessarily in the same order.
-     * The target CRS may have less datum than the source CRS.
+     * Concatenates two operation steps.
+     * The new concatenated operation gets an automatically generated name.
      *
-     * @param sourceCRS The target CRS.
-     * @param targetCRS The source CRS.
-     * @return {@code true} if all datum in the {@code targetCRS} exists in the {@code sourceCRS}.
+     * <div class="section">Special case</div>
+     * If one of the given operation steps performs a change of axis order or units,
+     * then that change will be merged with the other operation instead of creating an {@link ConcatenatedOperation}.
+     *
+     * @param  step1 The first  step, or {@code null} for the identity operation.
+     * @param  step2 The second step, or {@code null} for the identity operation.
+     * @return A concatenated operation, or {@code null} if all arguments were null.
+     * @throws FactoryException if the operation can't be constructed.
      */
-    static boolean isConversion(final CoordinateReferenceSystem sourceCRS,
-                                final CoordinateReferenceSystem targetCRS)
+    protected CoordinateOperation concatenate(final CoordinateOperation step1,
+                                              final CoordinateOperation step2)
+            throws FactoryException
     {
-        List<SingleCRS> components = CRS.getSingleComponents(sourceCRS);
-        int n = components.size();   // Number of remaining datum from sourceCRS to verify.
-        final Datum[] datum = new Datum[n];
-        for (int i=0; i<n; i++) {
-            datum[i] = components.get(i).getDatum();
-        }
-        components = CRS.getSingleComponents(targetCRS);
-next:   for (int i=components.size(); --i >= 0;) {
-            final Datum d = components.get(i).getDatum();
-            for (int j=n; --j >= 0;) {
-                if (Utilities.equalsIgnoreMetadata(d, datum[j])) {
-                    System.arraycopy(datum, j+1, datum, j, --n - j);  // Remove the datum from the list.
-                    continue next;
+        if (step1 == null)     return step2;
+        if (step2 == null)     return step1;
+        if (isIdentity(step1)) return step2;
+        if (isIdentity(step2)) return step1;
+        final MathTransform mt1 = step1.getMathTransform();
+        final MathTransform mt2 = step2.getMathTransform();
+        final CoordinateReferenceSystem sourceCRS = step1.getSourceCRS();
+        final CoordinateReferenceSystem targetCRS = step2.getTargetCRS();
+        CoordinateOperation step = null;
+        if (step1.getName() == AXIS_CHANGES && mt1.getSourceDimensions() == mt1.getTargetDimensions()) step = step2;
+        if (step2.getName() == AXIS_CHANGES && mt2.getSourceDimensions() == mt2.getTargetDimensions()) step = step1;
+        if (step instanceof SingleOperation) {
+            /*
+             * Applies only on operation in order to avoid merging with PassThroughOperation.
+             * Also applies only if the transform to hide has identical source and target
+             * dimensions in order to avoid mismatch with the method's dimensions.
+             */
+            final MathTransformFactory mtFactory = factorySIS.getMathTransformFactory();
+            return createFromMathTransform(IdentifiedObjects.getProperties(step),
+                   sourceCRS, targetCRS, mtFactory.createConcatenatedTransform(mt1, mt2),
+                   ((SingleOperation) step).getMethod(), SingleOperation.class);
+        }
+        return factory.createConcatenatedOperation(getTemporaryName(sourceCRS, targetCRS), step1, step2);
+    }
+
+    /**
+     * Creates a coordinate operation from a math transform.
+     *
+     * @param  name       The identifier for the operation to be created.
+     * @param  sourceCRS  The source coordinate reference system.
+     * @param  targetCRS  The destination coordinate reference system.
+     * @param  transform  The math transform.
+     * @return A coordinate operation using the specified math transform.
+     * @throws FactoryException if the operation can not be constructed.
+     */
+    private CoordinateOperation createFromMathTransform(
+            final Identifier                name,
+            final CoordinateReferenceSystem sourceCRS,
+            final CoordinateReferenceSystem targetCRS,
+            final MathTransform             transform) throws FactoryException
+    {
+        return createFromMathTransform(Collections.singletonMap(CoordinateOperation.NAME_KEY, name),
+                sourceCRS, targetCRS, transform, null, SingleOperation.class);
+    }
+
+    /**
+     * Creates a coordinate operation from a math transform.
+     * If the specified math transform is already a coordinate operation, and if source
+     * and target CRS match, then {@code transform} is returned with no change.
+     * Otherwise, a new coordinate operation is created.
+     *
+     * @param  properties The properties to give to the operation.
+     * @param  sourceCRS  The source coordinate reference system.
+     * @param  targetCRS  The destination coordinate reference system.
+     * @param  transform  The math transform.
+     * @param  method     The operation method, or {@code null} if unknown.
+     * @param  type       The required super-class (e.g. <code>{@linkplain Transformation}.class</code>).
+     * @return A coordinate operation using the specified math transform.
+     * @throws FactoryException if the operation can't be constructed.
+     */
+    protected CoordinateOperation createFromMathTransform(
+            final Map<String,?>             properties,
+            final CoordinateReferenceSystem sourceCRS,
+            final CoordinateReferenceSystem targetCRS,
+            final MathTransform             transform,
+                  OperationMethod           method,
+            final Class<? extends CoordinateOperation> type) throws FactoryException
+    {
+        if (transform instanceof CoordinateOperation) {
+            final CoordinateOperation operation = (CoordinateOperation) transform;
+            if (Objects.equals(operation.getSourceCRS(),     sourceCRS) &&
+                Objects.equals(operation.getTargetCRS(),     targetCRS) &&
+                Objects.equals(operation.getMathTransform(), transform) &&
+                (!(operation instanceof SingleOperation) ||
+                    Objects.equals(((SingleOperation) operation).getMethod(), method)))
+            {
+                return operation;
+            }
+        }
+        if (method == null && transform instanceof Parameterized) {
+            final ParameterDescriptorGroup descriptor = ((Parameterized) transform).getParameterDescriptors();
+            if (descriptor != null) {
+                final Identifier name = descriptor.getName();
+                if (name != null) {
+                    method = factory.getOperationMethod(name.getCode());
+                }
+                if (method == null) {
+                    method = factory.createOperationMethod(properties,
+                            sourceCRS.getCoordinateSystem().getDimension(),
+                            targetCRS.getCoordinateSystem().getDimension(),
+                            descriptor);
                 }
             }
-            return false;  // Datum from 'targetCRS' not found in 'sourceCRS'.
         }
-        return true;
+        final Map<String,Object> p = new HashMap<>(properties);
+        p.put(ReferencingServices.OPERATION_TYPE_KEY, type);
+        return factorySIS.createSingleOperation(p, sourceCRS, targetCRS, null, method, transform);
+    }
+
+    /**
+     * The operation to use by {@link #createTransformationStep(GeographicCRS,GeographicCRS)}
+     * for datum shift. This string can have one of the following values, from most accurate
+     * to most approximative operations:
+     *
+     * <ul>
+     *   <li>{@code null} for performing datum shifts in geocentric coordinates.</li>
+     *   <li>{@code "Molodensky"} for the Molodensky transformation.</li>
+     *   <li>{@code "Abridged Molodensky"} for the abridged Molodensky transformation.</li>
+     * </ul>
+     */
+    private String getMolodenskyMethod() {
+        return "Molodensky";
+    }
+
+    /**
+     * Returns a name for the given object, truncating it if needed.
+     */
+    private static String getShortName(final IdentifiedObject object) {
+        String name = IdentifiedObjects.getName(object, null);
+        if (name == null) {
+            name = Classes.getShortClassName(object);
+        } else {
+            int i = 30;                 // Arbitrary length threshold.
+            if (name.length() >= i) {
+                while (i > 15) {        // Arbitrary minimal length.
+                    final int c = name.codePointBefore(i);
+                    if (Character.isSpaceChar(c)) break;
+                    i -= Character.charCount(c);
+                }
+                name = CharSequences.trimWhitespaces(name, 0, i).toString() + '…';
+            }
+        }
+        return name;
+    }
+
+    /**
+     * Returns a temporary name for a transformation between two CRS.
+     */
+    private static Map<String,?> getTemporaryName(CoordinateReferenceSystem source, CoordinateReferenceSystem target) {
+        final String name = getShortName(source) + " → " + getShortName(target);
+        return Collections.singletonMap(IdentifiedObject.NAME_KEY, name);
+    }
+
+    /**
+     * Returns an error message for "No path found from sourceCRS to targetCRS".
+     * This is used for the construction of {@link OperationNotFoundException}.
+     *
+     * @param  source The source CRS.
+     * @param  target The target CRS.
+     * @return A default error message.
+     */
+    private static String getErrorMessage(final IdentifiedObject source, final IdentifiedObject target) {
+        return Errors.format(Errors.Keys.CoordinateOperationNotFound_2, getShortName(source), getShortName(target));
     }
 }

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=1734639&r1=1734638&r2=1734639&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] Fri Mar 11 22:59:03 2016
@@ -19,6 +19,7 @@ package org.apache.sis.referencing.opera
 import java.util.Map;
 import java.util.HashMap;
 import java.util.Collections;
+import java.util.List;
 import org.opengis.util.FactoryException;
 import org.opengis.util.NoSuchIdentifierException;
 import org.opengis.parameter.ParameterValueGroup;
@@ -28,11 +29,13 @@ import org.opengis.referencing.Identifie
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.opengis.referencing.crs.GeographicCRS;
 import org.opengis.referencing.crs.ProjectedCRS;
+import org.opengis.referencing.crs.SingleCRS;
+import org.opengis.referencing.datum.Datum;
 import org.apache.sis.internal.referencing.MergedProperties;
 import org.apache.sis.internal.metadata.ReferencingServices;
 import org.apache.sis.internal.system.DefaultFactories;
 import org.apache.sis.internal.util.CollectionsExt;
-import org.apache.sis.internal.util.Utilities;
+import org.apache.sis.referencing.CRS;
 import org.apache.sis.referencing.factory.InvalidGeodeticParameterException;
 import org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
 import org.apache.sis.util.collection.WeakHashSet;
@@ -42,6 +45,7 @@ import org.apache.sis.util.resources.Err
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.CharSequences;
 import org.apache.sis.util.NullArgumentException;
+import org.apache.sis.util.Utilities;
 
 
 /**
@@ -68,7 +72,7 @@ import org.apache.sis.util.NullArgumentE
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.6
- * @version 0.6
+ * @version 0.7
  * @module
  */
 public class DefaultCoordinateOperationFactory extends AbstractFactory implements CoordinateOperationFactory {
@@ -149,7 +153,7 @@ public class DefaultCoordinateOperationF
      *
      * @return The underlying math transform factory.
      */
-    private MathTransformFactory getMathTransformFactory() {
+    final MathTransformFactory getMathTransformFactory() {
         MathTransformFactory factory = mtFactory;
         if (factory == null) {
             mtFactory = factory = DefaultFactories.forBuildin(MathTransformFactory.class);
@@ -314,6 +318,39 @@ public class DefaultCoordinateOperationF
     }
 
     /**
+     * Returns {@code true} if the given CRS are using equivalent (ignoring metadata) datum.
+     * If the CRS are {@link CompoundCRS}, then this method verifies that all datum in the
+     * target CRS exists in the source CRS, but not necessarily in the same order.
+     * The target CRS may have less datum than the source CRS.
+     *
+     * @param sourceCRS The target CRS.
+     * @param targetCRS The source CRS.
+     * @return {@code true} if all datum in the {@code targetCRS} exists in the {@code sourceCRS}.
+     */
+    private static boolean isConversion(final CoordinateReferenceSystem sourceCRS,
+                                        final CoordinateReferenceSystem targetCRS)
+    {
+        List<SingleCRS> components = CRS.getSingleComponents(sourceCRS);
+        int n = components.size();                      // Number of remaining datum from sourceCRS to verify.
+        final Datum[] datum = new Datum[n];
+        for (int i=0; i<n; i++) {
+            datum[i] = components.get(i).getDatum();
+        }
+        components = CRS.getSingleComponents(targetCRS);
+next:   for (int i=components.size(); --i >= 0;) {
+            final Datum d = components.get(i).getDatum();
+            for (int j=n; --j >= 0;) {
+                if (Utilities.equalsIgnoreMetadata(d, datum[j])) {
+                    System.arraycopy(datum, j+1, datum, j, --n - j);  // Remove the datum from the list.
+                    continue next;
+                }
+            }
+            return false;                               // Datum from 'targetCRS' not found in 'sourceCRS'.
+        }
+        return true;
+    }
+
+    /**
      * Creates a transformation or conversion from the given properties.
      * This method infers by itself if the operation to create is a
      * {@link Transformation}, a {@link Conversion} or a {@link Projection} sub-type
@@ -424,7 +461,7 @@ public class DefaultCoordinateOperationF
          * could be different, which we want to allow.
          */
         if (baseType == SingleOperation.class) {
-            if (OperationPathFinder.isConversion(sourceCRS, targetCRS)) {
+            if (isConversion(sourceCRS, targetCRS)) {
                 if (interpolationCRS == null && sourceCRS instanceof GeographicCRS
                                              && targetCRS instanceof ProjectedCRS)
                 {
@@ -571,7 +608,7 @@ public class DefaultCoordinateOperationF
             return delegate;
         }
         for (final CoordinateOperationFactory factory : java.util.ServiceLoader.load(CoordinateOperationFactory.class)) {
-            if (!Utilities.isSIS(factory.getClass())) {
+            if (!org.apache.sis.internal.util.Utilities.isSIS(factory.getClass())) {
                 delegate = factory;
                 return factory;
             }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java?rev=1734639&r1=1734638&r2=1734639&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/package-info.java [UTF-8] Fri Mar 11 22:59:03 2016
@@ -53,6 +53,43 @@
  *     for converting the longitude axis of source and target CRS to degrees before this operation is applied.</li>
  * </ul>
  *
+ * <div class="section"><cite>Early binding</cite> versus <cite>late binding</cite> implementations</div>
+ * There is sometime multiple ways of transforming coordinates for a given pair of source and target CRS.
+ * For example the {@linkplain org.apache.sis.referencing.datum.BursaWolfParameters Bursa-Wolf parameters}
+ * may vary depending on the area of interest, like in the transformations from NAD27 to NAD83.
+ * Even for a fixed set of Bursa-Wolf parameter, there is various ways to use them (<cite>Molodensky</cite>,
+ * <cite>Abridged Molodensky</cite>, <cite>Geocentric translation</cite>, <cite>etc.</cite>).
+ *
+ * <p>EPSG identifies two approaches for addressing this multiplicity problem.
+ * Quoting the GIGS guideline:</p>
+ *
+ * <blockquote>
+ * <ul class="verbose">
+ *   <li><b>Early binding:</b>
+ *     A priori association of a coordinate transformation with a geodetic CRS.
+ *     The association is usually made at start-up of the session or project, as that is defined in the software,
+ *     but always before any data is associated with the ‘CRS’. In general the ‘coordinate transformation’ specified
+ *     uses the ‘CRS’ of the data as the source ‘CRS’ and WGS 84 as the target ‘CRS’.</li>
+ *
+ *   <li><b>Late binding:</b>
+ *     Association at run time of a coordinate transformation with a CRS.
+ *     Late binding allows the user to select the appropriate transformation upon import of ‘geospatial data’
+ *     or merge of two geospatial datasets. This means that, in cases where there are multiple existing transformations,
+ *     the user can choose the appropriate one, possibly aided by additional information.</li>
+ * </ul>
+ * <p style="text-align:right; font-size:small"><b>Source:</b>
+ * <u>Geospatial Integrity of Geoscience Software Part 1 – GIGS guidelines.</u>
+ * <i>OGP publication, Report No. 430-1, September 2011</i></p>
+ * </blockquote>
+ *
+ * Apache SIS is a <cite>late binding</cite> implementation, while a little trace for <cite>early binding</cite>
+ * exists in the form of the {@link org.apache.sis.referencing.datum.DefaultGeodeticDatum#getBursaWolfParameters()}
+ * method for those who really need it. This means that when searching for a coordinate operation between a given
+ * pair of CRS, Apache SIS will query {@link org.apache.sis.referencing.factory.sql.EPSGFactory} before to try to
+ * {@linkplain org.apache.sis.referencing.operation.CoordinateOperationInference infer the operation path by itelf}.
+ * The {@link org.apache.sis.referencing.operation.CoordinateOperationContext} can be used for further refinements,
+ * for example by specifying the area of interest.
+ *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @version 0.7
  * @since   0.6

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1734639&r1=1734638&r2=1734639&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java [UTF-8] Fri Mar 11 22:59:03 2016
@@ -206,6 +206,11 @@ public final class Errors extends Indexe
         public static final short ColinearAxisDirections_2 = 14;
 
         /**
+         * Coordinate conversion of transformation from system “{0}” to “{1}” has not been found.
+         */
+        public static final short CoordinateOperationNotFound_2 = 219;
+
+        /**
          * Database error while creating a ‘{0}’ object for code “{1}”.
          */
         public static final short DatabaseError_2 = 209;

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1734639&r1=1734638&r2=1734639&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties [ISO-8859-1] Fri Mar 11 22:59:03 2016
@@ -52,6 +52,7 @@ CircularReference                 = Circ
 ClassNotFinal_1                   = Class \u2018{0}\u2019 is not final.
 CloneNotSupported_1               = Can not clone an object of type \u2018{0}\u2019.
 ColinearAxisDirections_2          = Axis directions {0} and {1} are colinear.
+CoordinateOperationNotFound_2     = Coordinate conversion of transformation from system \u201c{0}\u201d to \u201c{1}\u201d has not been found.
 DatabaseError_2                   = Database error while creating a \u2018{0}\u2019 object for code \u201c{1}\u201d.
 DatumOriginShallBeDate            = Origin of temporal datum shall be a date.
 DeadThread_1                      = Thread \u201c{0}\u201d is dead.

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1734639&r1=1734638&r2=1734639&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties [ISO-8859-1] Fri Mar 11 22:59:03 2016
@@ -49,6 +49,7 @@ CircularReference                 = R\u0
 ClassNotFinal_1                   = La classe \u2018{0}\u2019 n\u2019est pas finale.
 CloneNotSupported_1               = Un objet de type \u2018{0}\u2019 ne peut pas \u00eatre clon\u00e9.
 ColinearAxisDirections_2          = Les directions d\u2019axes {0} et {1} sont colin\u00e9aires.
+CoordinateOperationNotFound_2     = La conversion ou transformation des coordonn\u00e9es du syst\u00e8me \u00ab\u202f{0}\u202f\u00bb vers \u00ab\u202f{1}\u202f\u00bb n\u2019a pas \u00e9t\u00e9 trouv\u00e9e.
 DatabaseError_2                   = Erreur de base de donn\u00e9es lors de la cr\u00e9ation d\u2019un objet \u2018{0}\u2019 pour le code \u00ab\u202f{1}\u202f\u00bb.
 DatumOriginShallBeDate            = L\u2019origine d\u2019un r\u00e9f\u00e9rentiel temporel doit \u00eatre une date.
 DeadThread_1                      = La t\u00e2che \u00ab\u202f{0}\u202f\u00bb est morte.

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java?rev=1734639&r1=1734638&r2=1734639&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.java [UTF-8] Fri Mar 11 22:59:03 2016
@@ -86,6 +86,11 @@ public final class Vocabulary extends In
         public static final short Attributes = 4;
 
         /**
+         * Axis changes
+         */
+        public static final short AxisChanges = 98;
+
+        /**
          * Barometric altitude
          */
         public static final short BarometricAltitude = 5;
@@ -161,6 +166,16 @@ public final class Vocabulary extends In
         public static final short DataDirectory = 88;
 
         /**
+         * Datum
+         */
+        public static final short Datum = 99;
+
+        /**
+         * Datum shift
+         */
+        public static final short DatumShift = 100;
+
+        /**
          * Daylight time
          */
         public static final short DaylightTime = 13;
@@ -206,11 +221,31 @@ public final class Vocabulary extends In
         public static final short Ellipsoid = 70;
 
         /**
+         * Ellipsoid change
+         */
+        public static final short EllipsoidChange = 101;
+
+        /**
          * Ellipsoidal height
          */
         public static final short EllipsoidalHeight = 18;
 
         /**
+         * Geocentric
+         */
+        public static final short Geocentric = 102;
+
+        /**
+         * Geocentric conversion
+         */
+        public static final short GeocentricConversion = 103;
+
+        /**
+         * Geocentric radius
+         */
+        public static final short GeocentricRadius = 104;
+
+        /**
          * Geodetic dataset
          */
         public static final short GeodeticDataset = 95;
@@ -226,6 +261,11 @@ public final class Vocabulary extends In
         public static final short Identifier = 20;
 
         /**
+         * Identity
+         */
+        public static final short Identity = 105;
+
+        /**
          * Implementation
          */
         public static final short Implementation = 21;
@@ -246,6 +286,11 @@ public final class Vocabulary extends In
         public static final short Invalid = 89;
 
         /**
+         * Inverse operation
+         */
+        public static final short InverseOperation = 106;
+
+        /**
          * Java extensions
          */
         public static final short JavaExtensions = 23;

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties?rev=1734639&r1=1734638&r2=1734639&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary.properties [ISO-8859-1] Fri Mar 11 22:59:03 2016
@@ -20,6 +20,7 @@ AngularDegrees          = Degrees
 AngularMinutes          = Minutes
 AngularSeconds          = Seconds
 Attributes              = Attributes
+AxisChanges             = Axis changes
 BarometricAltitude      = Barometric altitude
 Cardinality             = Cardinality
 CharacterEncoding       = Character encoding
@@ -35,6 +36,8 @@ CurrentDirectory        = Current direct
 CycleOmitted            = Cycle omitted
 DataBase                = Database
 DataDirectory           = Data directory
+Datum                   = Datum
+DatumShift              = Datum shift
 DaylightTime            = Daylight time
 DefaultValue            = Default value
 Description             = Description
@@ -44,14 +47,20 @@ Directory               = Directory
 DittoMark               = \u2033
 DublinJulian            = Dublin Julian
 Ellipsoid               = Ellipsoid
+EllipsoidChange         = Ellipsoid change
 EllipsoidalHeight       = Ellipsoidal height
+Geocentric              = Geocentric
+GeocentricRadius        = Geocentric radius
+GeocentricConversion    = Geocentric conversion
 GeodeticDataset         = Geodetic dataset
 Height                  = Height
 Identifier              = Identifier
 Implementation          = Implementation
 InBetweenWords          = \u2002in\u2002
+Identity                = Identity
 Index                   = Index
 Invalid                 = Invalid
+InverseOperation        = Inverse operation
 JavaExtensions          = Java extensions
 JavaHome                = Java home directory
 Julian                  = Julian

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties?rev=1734639&r1=1734638&r2=1734639&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties [ISO-8859-1] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/util/resources/Vocabulary_fr.properties [ISO-8859-1] Fri Mar 11 22:59:03 2016
@@ -27,6 +27,7 @@ AngularDegrees          = Degr\u00e9s
 AngularMinutes          = Minutes
 AngularSeconds          = Secondes
 Attributes              = Attributs
+AxisChanges             = Changements d\u2019axes
 BarometricAltitude      = Altitude barom\u00e9trique
 Cardinality             = Cardinalit\u00e9
 CharacterEncoding       = Encodage des caract\u00e8res
@@ -42,6 +43,8 @@ CurrentDirectory        = R\u00e9pertoir
 CycleOmitted            = Cycle omit
 DataBase                = Base de donn\u00e9es
 DataDirectory           = R\u00e9pertoire des donn\u00e9es
+Datum                   = R\u00e9f\u00e9rentiel
+DatumShift              = Changement de r\u00e9f\u00e9rentiel
 DaylightTime            = Heure normale
 DefaultValue            = Valeur par d\u00e9faut
 Description             = Description
@@ -51,14 +54,20 @@ Directory               = R\u00e9pertoir
 DittoMark               = \u2033
 DublinJulian            = Julien Dublin
 Ellipsoid               = Ellipso\u00efde
+EllipsoidChange         = Changement d\u2019ellipso\u00efde
 EllipsoidalHeight       = Hauteur ellipso\u00efdale
+Geocentric              = G\u00e9ocentrique
+GeocentricRadius        = Rayon g\u00e9ocentrique
+GeocentricConversion    = Conversion g\u00e9ocentrique
 GeodeticDataset         = Base de donn\u00e9es g\u00e9od\u00e9sique
 Height                  = Hauteur
 Identifier              = Identifiant
 Implementation          = Impl\u00e9mentation
 InBetweenWords          = \u2002dans\u2002
+Identity                = Identit\u00e9
 Index                   = Index
 Invalid                 = Invalide
+InverseOperation        = Op\u00e9ration inverse
 JavaExtensions          = Extensions du Java
 JavaHome                = R\u00e9pertoire du Java
 Julian                  = Julien



Mime
View raw message