sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1802708 - in /sis/branches/JDK8: core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/ core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/ core/sis-referencing/src/test/java/org/apache/sis/referencing...
Date Sat, 22 Jul 2017 18:39:58 GMT
Author: desruisseaux
Date: Sat Jul 22 18:39:57 2017
New Revision: 1802708

URL: http://svn.apache.org/viewvc?rev=1802708&view=rev
Log:
Provide a plugin mechanism (SpecializedOperationFactory - may be renamed later) for enabling the use Proj.4 when we detect a pair of CRS that are wrappers around Proj.4.
Specifies axis units of measurement when creating a Proj.4 definition string from a CRS.
Improve documentation.

Added:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/SpecializedOperationFactory.java   (with props)
    sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/internal/
    sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/internal/storage/
    sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/internal/storage/gdal/
    sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/internal/storage/gdal/OperationFactory.java   (with props)
    sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/internal/storage/gdal/package-info.java   (with props)
    sis/branches/JDK8/storage/sis-gdal/src/main/resources/META-INF/
    sis/branches/JDK8/storage/sis-gdal/src/main/resources/META-INF/services/
    sis/branches/JDK8/storage/sis-gdal/src/main/resources/META-INF/services/org.apache.sis.internal.referencing.SpecializedOperationFactory   (with props)
    sis/branches/JDK8/storage/sis-gdal/src/main/resources/META-INF/services/org.opengis.referencing.crs.CRSAuthorityFactory   (with props)
    sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/IntegrationTest.java   (with props)
Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.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/DefaultCoordinateOperationFactory.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransformTest.java
    sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/io/TableAppender.java
    sis/branches/JDK8/ide-project/NetBeans/build.xml
    sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4.java
    sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4Factory.java
    sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Transform.java
    sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/package-info.java
    sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/MTFactory.java
    sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/Proj4FactoryTest.java
    sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/test/suite/GDALTestSuite.java

Added: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/SpecializedOperationFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/SpecializedOperationFactory.java?rev=1802708&view=auto
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/SpecializedOperationFactory.java (added)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/SpecializedOperationFactory.java [UTF-8] Sat Jul 22 18:39:57 2017
@@ -0,0 +1,55 @@
+/*
+ * 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.internal.referencing;
+
+import java.util.Set;
+import org.opengis.util.FactoryException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.CoordinateOperation;
+
+
+/**
+ * Implemented by extension modules capable to provide coordinate operations for some particular pairs of CRS.
+ * Implementations of this interface are not general-purpose factories;
+ * they should not process any pair of CRS other than the one for which they are designed.
+ *
+ * <div class="note"><b>Example:</b>
+ * a module doing the bindings between Apache SIS and another map projection library may create wrappers
+ * around the transformation method of that other library when {@code findOperations(…)} recognizes the
+ * given CRS as wrappers around their data structures.</div>
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 0.8
+ * @since   0.8
+ * @module
+ */
+public interface SpecializedOperationFactory {
+    /**
+     * Returns operations between the given pair of CRS, or an empty set if this factory does not recognize them.
+     * Non-empty sets have precedence over EPSG geodetic dataset or other mechanism used by Apache SIS, so should
+     * be used sparsely.
+     *
+     * @param  sourceCRS  the coordinate reference system of source points (before transformation).
+     * @param  targetCRS  the coordinate reference system of target points (after transformation).
+     * @return the coordinate operations from source to target CRS, or an empty set if this factory
+     *         does not recognize the given pair of CRSs.
+     * @throws FactoryException if this factory recognizes the CRSs given in arguments,
+     *         but an error occurred while creating the coordinate operation.
+     */
+    Set<CoordinateOperation> findOperations(CoordinateReferenceSystem sourceCRS, CoordinateReferenceSystem targetCRS)
+            throws FactoryException;
+}

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

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

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java?rev=1802708&r1=1802707&r2=1802708&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationFinder.java [UTF-8] Sat Jul 22 18:39:57 2017
@@ -41,6 +41,7 @@ import org.apache.sis.internal.referenci
 import org.apache.sis.internal.referencing.provider.GeographicToGeocentric;
 import org.apache.sis.internal.referencing.provider.GeocentricToGeographic;
 import org.apache.sis.internal.referencing.provider.GeocentricAffine;
+import org.apache.sis.internal.referencing.SpecializedOperationFactory;
 import org.apache.sis.internal.referencing.Resources;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.measure.Units;
@@ -221,6 +222,17 @@ public class CoordinateOperationFinder e
             throw new FactoryException(Resources.format(Resources.Keys.RecursiveCreateCallForCode_2, CoordinateOperation.class, key));
         }
         /*
+         * Verify if some extension module handles this pair of CRS in a special way. For example it may
+         * be the "sis-gdal" module checking if the given CRS are wrappers around Proj.4 data structure.
+         */
+        for (final SpecializedOperationFactory sp : factorySIS.getSpecializedFactories()) {
+            for (final CoordinateOperation op : sp.findOperations(sourceCRS, targetCRS)) {
+                if (filter(op)) {
+                    return op;
+                }
+            }
+        }
+        /*
          * If the user did not specified an area of interest, use the domain of validity of the CRS.
          * Then verify in the EPSG dataset if the operation is explicitely defined by an authority.
          */

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=1802708&r1=1802707&r2=1802708&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] Sat Jul 22 18:39:57 2017
@@ -541,12 +541,19 @@ class CoordinateOperationRegistry {
              * FactoryException propagate.
              */
             bestChoice = complete(bestChoice, sourceCRS, targetCRS);
-            if (filter == null || filter.test(bestChoice)) break;
+            if (filter(bestChoice)) break;
         }
         return bestChoice;
     }
 
     /**
+     * Returns {@code true} if the given operation can be accepted.
+     */
+    final boolean filter(final CoordinateOperation op) {
+        return filter == null || filter.test(op);
+    }
+
+    /**
      * Creates the inverse of the given single operation.
      * If this operation succeed, then the returned coordinate operations has the following properties:
      *

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=1802708&r1=1802707&r2=1802708&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] Sat Jul 22 18:39:57 2017
@@ -20,6 +20,7 @@ import java.util.Map;
 import java.util.HashMap;
 import java.util.Collections;
 import java.util.List;
+import java.util.ServiceLoader;
 import org.opengis.util.FactoryException;
 import org.opengis.util.NoSuchIdentifierException;
 import org.opengis.parameter.ParameterValueGroup;
@@ -36,10 +37,12 @@ import org.opengis.referencing.cs.CSFact
 import org.opengis.referencing.datum.Datum;
 import org.apache.sis.internal.referencing.Resources;
 import org.apache.sis.internal.referencing.MergedProperties;
+import org.apache.sis.internal.referencing.SpecializedOperationFactory;
 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.Constants;
+import org.apache.sis.internal.util.LazySet;
 import org.apache.sis.referencing.CRS;
 import org.apache.sis.referencing.factory.InvalidGeodeticParameterException;
 import org.apache.sis.referencing.operation.transform.AbstractMathTransform;
@@ -122,6 +125,17 @@ public class DefaultCoordinateOperationF
     private volatile MathTransformFactory mtFactory;
 
     /**
+     * Factories specialized to some particular pair of CRS. For example a module doing the bindings between
+     * Apache SIS and another map projection library may create wrappers around the transformation method of
+     * that other library when {@code SpecializedOperationFactory.tryCreateOperation(…)} recognizes the given
+     * CRS as wrappers around their data structures.
+     *
+     * <p>This array is created when first needed. After creation, the array shall not be modified anymore.</p>
+     */
+    @SuppressWarnings("VolatileArrayField")
+    private volatile SpecializedOperationFactory[] specializedFactories;
+
+    /**
      * Weak references to existing objects.
      * This set is used in order to return a pre-existing object instead of creating a new one.
      * This applies to objects created explicitly, not to coordinate operations inferred by a
@@ -255,6 +269,20 @@ public class DefaultCoordinateOperationF
     }
 
     /**
+     * Returns all known factories specialized in the creation of coordinate operations between some particular
+     * pairs of CRS.
+     */
+    final SpecializedOperationFactory[] getSpecializedFactories() {
+        SpecializedOperationFactory[] factories = specializedFactories;
+        if (factories == null) {
+            final LazySet<SpecializedOperationFactory> set =
+                    new LazySet<>(ServiceLoader.load(SpecializedOperationFactory.class).iterator());
+            specializedFactories = factories = set.toArray(new SpecializedOperationFactory[set.size()]);
+        }
+        return factories;
+    }
+
+    /**
      * Returns the operation method of the given name. The given argument shall be either a method
      * {@linkplain DefaultOperationMethod#getName() name} (e.g. <cite>"Transverse Mercator"</cite>)
      * or one of its {@linkplain DefaultOperationMethod#getIdentifiers() identifiers} (e.g. {@code "EPSG:9807"}).

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransformTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransformTest.java?rev=1802708&r1=1802707&r2=1802708&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransformTest.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransformTest.java [UTF-8] Sat Jul 22 18:39:57 2017
@@ -239,7 +239,7 @@ public final strictfp class EllipsoidToC
     }
 
     /**
-     * Tests {@link EllipsoidToCentricTransform#concatenate(MathTransform, boolean, MathTransformFactory)}.
+     * Tests {@link EllipsoidToCentricTransform#tryConcatenate(boolean, MathTransform, MathTransformFactory)}.
      * The test creates <cite>"Geographic 3D to 2D conversion"</cite>, <cite>"Geographic/Geocentric conversions"</cite>
      * and <cite>"Geocentric translation"</cite> transforms, then concatenate them.
      *

Modified: sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/io/TableAppender.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/io/TableAppender.java?rev=1802708&r1=1802707&r2=1802708&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/io/TableAppender.java [UTF-8] (original)
+++ sis/branches/JDK8/core/sis-utility/src/main/java/org/apache/sis/io/TableAppender.java [UTF-8] Sat Jul 22 18:39:57 2017
@@ -176,17 +176,17 @@ public class TableAppender extends Appen
     private String lineSeparator;
 
     /**
-     * The column separator.
+     * The column separator, or an empty string if none.
      */
     private final String columnSeparator;
 
     /**
-     * The left table border.
+     * The left table border, or an empty string if none.
      */
     private final String leftBorder;
 
     /**
-     * The right table border.
+     * The right table border, or an empty string if none.
      */
     private final String rightBorder;
 

Modified: sis/branches/JDK8/ide-project/NetBeans/build.xml
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/ide-project/NetBeans/build.xml?rev=1802708&r1=1802707&r2=1802708&view=diff
==============================================================================
--- sis/branches/JDK8/ide-project/NetBeans/build.xml (original)
+++ sis/branches/JDK8/ide-project/NetBeans/build.xml Sat Jul 22 18:39:57 2017
@@ -192,6 +192,13 @@
       </fileset>
     </concat>
 
+    <!-- SpecializedOperationFactory implementations to be loaded by ServiceLoader. -->
+    <concat destfile="${build.classes.dir}/META-INF/services/org.apache.sis.internal.referencing.SpecializedOperationFactory" encoding="UTF-8" fixlastline="yes">
+      <fileset dir="${project.root}">
+        <include name="*/*/src/main/resources/META-INF/services/org.apache.sis.internal.referencing.SpecializedOperationFactory"/>
+      </fileset>
+    </concat>
+
     <!-- DataStoreProvider implementations to be loaded by ServiceLoader. -->
     <concat destfile="${build.classes.dir}/META-INF/services/org.apache.sis.storage.DataStoreProvider" encoding="UTF-8" fixlastline="yes">
       <fileset dir="${project.root}">

Added: sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/internal/storage/gdal/OperationFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/internal/storage/gdal/OperationFactory.java?rev=1802708&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/internal/storage/gdal/OperationFactory.java (added)
+++ sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/internal/storage/gdal/OperationFactory.java [UTF-8] Sat Jul 22 18:39:57 2017
@@ -0,0 +1,57 @@
+/*
+ * 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.internal.storage.gdal;
+
+import java.util.Set;
+import org.opengis.util.FactoryException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.CoordinateOperation;
+import org.apache.sis.internal.referencing.SpecializedOperationFactory;
+import org.apache.sis.internal.util.CollectionsExt;
+import org.apache.sis.storage.gdal.Proj4;
+
+
+/**
+ * The factory for operations between pair of {@literal Proj.4} wrappers.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 0.8
+ * @since   0.8
+ * @module
+ */
+public final class OperationFactory implements SpecializedOperationFactory {
+    /**
+     * Creates a new factory.
+     */
+    public OperationFactory() {
+    }
+
+    /**
+     * Returns an operation between the given pair of CRS, or an empty set if this factory does not recognize
+     * the given CRSs.
+     *
+     * @return the coordinate operation, or an empty set if the given CRSs are not Proj.4 wrappers.
+     * @throws FactoryException if the given CRSs are Proj.4 wrappers and an error occurred while
+     *         creating the coordinate operation.
+     */
+    @Override
+    public Set<CoordinateOperation> findOperations(CoordinateReferenceSystem sourceCRS, CoordinateReferenceSystem targetCRS)
+            throws FactoryException
+    {
+        return CollectionsExt.singletonOrEmpty(Proj4.createOperation(sourceCRS, targetCRS, false));
+    }
+}

Propchange: sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/internal/storage/gdal/OperationFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/internal/storage/gdal/OperationFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Added: sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/internal/storage/gdal/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/internal/storage/gdal/package-info.java?rev=1802708&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/internal/storage/gdal/package-info.java (added)
+++ sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/internal/storage/gdal/package-info.java [UTF-8] Sat Jul 22 18:39:57 2017
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+/**
+ * Service providers for {@code sis-gdal} module.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 0.8
+ * @since   0.8
+ * @module
+ */
+package org.apache.sis.internal.storage.gdal;

Propchange: sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/internal/storage/gdal/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/internal/storage/gdal/package-info.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4.java?rev=1802708&r1=1802707&r2=1802708&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4.java [UTF-8] Sat Jul 22 18:39:57 2017
@@ -23,10 +23,12 @@ import org.opengis.util.FactoryException
 import org.opengis.parameter.ParameterValue;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.GeneralParameterValue;
+import org.opengis.metadata.extent.GeographicBoundingBox;
 import org.opengis.referencing.IdentifiedObject;
 import org.opengis.referencing.crs.GeodeticCRS;
 import org.opengis.referencing.crs.ProjectedCRS;
 import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.cs.CoordinateSystemAxis;
 import org.opengis.referencing.cs.AxisDirection;
 import org.opengis.referencing.cs.CoordinateSystem;
 import org.opengis.referencing.cs.CartesianCS;
@@ -36,8 +38,10 @@ import org.opengis.referencing.datum.Geo
 import org.opengis.referencing.datum.PrimeMeridian;
 import org.opengis.referencing.operation.Projection;
 import org.opengis.referencing.operation.CoordinateOperation;
+import org.apache.sis.referencing.operation.AbstractCoordinateOperation;
 import org.apache.sis.referencing.factory.UnavailableFactoryException;
 import org.apache.sis.referencing.IdentifiedObjects;
+import org.apache.sis.referencing.CRS;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.internal.metadata.AxisDirections;
 import org.apache.sis.internal.system.Modules;
@@ -46,6 +50,7 @@ import org.apache.sis.util.logging.Loggi
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.Static;
+import org.apache.sis.util.iso.Types;
 import org.apache.sis.measure.Units;
 
 
@@ -98,6 +103,7 @@ public final class Proj4 extends Static
     /**
      * Infers a {@literal Proj.4} definition from the given projected, geographic or geocentric coordinate reference system.
      * This method does not need the Proj.4 native library; it can be used in a pure Java application.
+     * However the returned definition string may differ depending on whether the Proj.4 library is available or not.
      *
      * @param  crs  the coordinate reference system for which to create a Proj.4 definition.
      * @return the definition of the given CRS in a Proj.4 format.
@@ -154,21 +160,40 @@ public final class Proj4 extends Static
          * Append the map projection parameters. Those parameters may include axis lengths (a and b),
          * but not necessarily. If axis lengths are specified, then we will ignore the Ellipsoid instance
          * associated to the CRS.
+         *
+         * The "+over" option is for disabling the default wrapping of output longitudes in the -180 to 180 range.
+         * We do that for having the same behavior between Proj.4 and Apache SIS. No wrapping reduce discontinuity
+         * problems with geometries that cross the anti-meridian.
+         *
+         * The "+no_defs" option is for ensuring that no defaults are read from "/usr/share/proj/proj_def.dat" file.
+         * That file contains default values for various map projections, for example "+lat_1=29.5" and "+lat_2=45.5"
+         * for the "aea" projection. Those defaults are assuming that users want Conterminous U.S. map.
+         * This may cause surprising behavior for users outside USA.
          */
         final StringBuilder definition = new StringBuilder(100);
         definition.append(Proj4Factory.PROJ_PARAM).append(method);
         boolean hasSemiMajor = false;
         boolean hasSemiMinor = false;
         if (parameters != null) {
+            definition.append(" +over +no_defs");                                       // See above comment
             for (final GeneralParameterValue parameter : parameters.values()) {
-                if (parameter instanceof ParameterValue) {
-                    final Object value = ((ParameterValue) parameter).getValue();
-                    if (value != null) {
-                        final String pn = name(parameter.getDescriptor());
-                        if (pn.equals("+a")) hasSemiMajor = true;
-                        if (pn.equals("+b")) hasSemiMinor = true;
-                        definition.append(' ').append(pn).append('=').append(value);
+                if (parameter instanceof ParameterValue<?>) {
+                    final ParameterValue<?> pv = (ParameterValue<?>) parameter;
+                    final Object value;
+                    Unit<?> unit = pv.getUnit();
+                    if (unit != null) {
+                        unit = Units.isAngular(unit) ? Units.DEGREE : unit.getSystemUnit();
+                        value = pv.doubleValue(unit);       // Always in metres or degrees.
+                    } else {
+                        value = pv.getValue();
+                        if (value == null) {
+                            continue;
+                        }
                     }
+                    final String pn = name(parameter.getDescriptor());
+                    hasSemiMajor |= pn.equals("+a");
+                    hasSemiMinor |= pn.equals("+b");
+                    definition.append(' ').append(pn).append('=').append(value);
                 }
             }
         }
@@ -190,24 +215,59 @@ public final class Proj4 extends Static
         /*
          * Appends axis directions. This method always format a vertical direction (up or down)
          * even if the coordinate system is two-dimensional, because Proj.4 seems to require it.
+         * Also extract axis units in the process.
          */
+        final Unit<?>[] units = new Unit<?>[2];     // Horizontal at index 0, vertical at index 1.
+        boolean validCS = true;
         definition.append(' ').append(Proj4Factory.AXIS_ORDER_PARAM);
         final int dimension = Math.min(cs.getDimension(), 3);
         boolean hasVertical = false;
         for (int i=0; i<dimension; i++) {
-            final AxisDirection dir = cs.getAxis(i).getDirection();
+            final CoordinateSystemAxis axis = cs.getAxis(i);
+            final AxisDirection dir = axis.getDirection();
+            int unitIndex = 0;
             if (!AxisDirections.isCardinal(dir)) {
                 if (!AxisDirections.isVertical(dir)) {
                     throw new FactoryException(Errors.format(Errors.Keys.UnsupportedAxisDirection_1, dir));
                 }
                 hasVertical = true;
+                unitIndex = 1;
             }
+            final Unit<?> old  = units[unitIndex];
+            units[unitIndex]   = axis.getUnit();
+            validCS &= (old == null || old.equals(units[unitIndex]));
             definition.appendCodePoint(Character.toLowerCase(dir.name().codePointAt(0)));
         }
         if (!hasVertical && dimension < 3) {
             definition.append('u');                    // Add a UP direction if not already present.
         }
-        return definition.toString();
+        /*
+         * Append units of measurement, then verify the coordinate system validity.
+         */
+        for (int i=0; i<units.length; i++) {
+            final Unit<?> unit = units[i];
+            if (unit != null && !unit.equals(Units.DEGREE) && !unit.equals(Units.METRE)) {
+                validCS &= Units.isLinear(unit);
+                definition.append(" +");
+                if (i == 1) definition.append('v');     // "+vto_meter" parameter.
+                definition.append("to_meter=").append(Units.toStandardUnit(unit));
+            }
+        }
+        if (validCS) {
+            return definition.toString();
+        }
+        /*
+         * If we reach this point, we detected a coordinate system that we can not format as a
+         * Proj.4 definition string. Format an error message with axis directions and units.
+         */
+        definition.setLength(0);
+        definition.append('(');
+        for (int i=0; i<units.length; i++) {
+            final CoordinateSystemAxis axis = cs.getAxis(i);
+            if (i != 0) definition.append(", ");
+            definition.append(axis.getUnit()).append(' ').append(Types.getCodeName(axis.getDirection()));
+        }
+        throw new FactoryException(Errors.format(Errors.Keys.IllegalCoordinateSystem_1, definition.append(')')));
     }
 
     /**
@@ -224,6 +284,16 @@ public final class Proj4 extends Static
 
     /**
      * Creates a new CRS from the given {@literal Proj.4} definition string.
+     * Some examples of definition strings are:
+     * <ul>
+     *   <li>{@code "+init=epsg:3395"} (see warning below)</li>
+     *   <li>{@code "+proj=latlong +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"}</li>
+     *   <li>{@code "+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +datum=WGS84 +units=m +ellps=WGS84 +towgs84=0,0,0"}</li>
+     * </ul>
+     *
+     * <b>Warning:</b> despite the {@code "epsg"} word, coordinate reference systems created by {@code "+init=epsg:"}
+     * syntax are not necessarily compliant with EPSG definitions. In particular, the axis order is often different.
+     * Units of measurement may also differ.
      *
      * @param  definition  the Proj.4 definition string.
      * @param  dimension   the number of dimension of the CRS to create (2 or 3).
@@ -248,26 +318,49 @@ public final class Proj4 extends Static
 
     /**
      * Creates an operation for conversion or transformation between two coordinate reference systems.
-     * This implementation always uses Proj.4 for performing the coordinate operations, regardless if
-     * the given CRS were created from a Proj.4 definition string or not. This method fails if it can
-     * not map the given CRS to Proj.4 structures.
-     *
-     * @param  sourceCRS   the source coordinate reference system.
-     * @param  targetCRS   the target coordinate reference system.
-     * @return a coordinate operation for transforming coordinates from the given source CRS to the given target CRS.
-     * @throws UnavailableFactoryException if the Proj.4 native library is not available.
-     * @throws FactoryException if the operation creation failed for another reason.
+     * The given CRSs should be instances created by this package. If not, then there is a choice:
+     *
+     * <ul>
+     *   <li>If {@code force} is {@code false}, then this method returns {@code null}.</li>
+     *   <li>Otherwise this method always uses Proj.4 for performing the coordinate operations,
+     *       regardless if the given CRS were created from Proj.4 definition strings or not.
+     *       This method fails if it can not map the given CRS to Proj.4 data structures.</li>
+     * </ul>
+     *
+     * <p><b>Recommended alternative</b></p>
+     * Provided that an <a href="http://sis.apache.org/epsg.html">EPSG database is available</a>,
+     * Apache SIS {@link CRS#findOperation CRS.findOperation(…)} method produces results that are closer
+     * to the authoritative definitions of coordinate operations (technically, Apache SIS referencing
+     * engine is a <cite>late-binding</cite> implementation while Proj.4 is an <cite>early-binding</cite>
+     * implementation — see EPSG guidance notes for a definition of late versus early-binding approaches).
+     * Apache SIS also attaches metadata about
+     * {@linkplain AbstractCoordinateOperation#getCoordinateOperationAccuracy() coordinate operation accuracy} and
+     * {@linkplain AbstractCoordinateOperation#getDomainOfValidity() domain of validity}, have extended support of
+     * multi-dimensional CRS and provides transform derivatives. This {@code Proj4.createOperation(…)} method should
+     * be reserved to situations where an application needs to reproduce the same numerical results than Proj.4.
+     *
+     * @param  sourceCRS  the source coordinate reference system.
+     * @param  targetCRS  the target coordinate reference system.
+     * @param  force      whether to force the creation of a Proj.4 transform
+     *                    even if the given CRS are not wrappers around Proj.4 data structures.
+     * @return a coordinate operation for transforming coordinates from the given source CRS to the given target CRS, or
+     *         {@code null} if the given CRS are not wrappers around Proj.4 data structures and {@code force} is false.
+     * @throws UnavailableFactoryException if {@code force} is {@code true} and the Proj.4 native library is not available.
+     * @throws FactoryException if {@code force} is {@code true} and this method can not create Proj.4 transform
+     *         for the given pair of coordinate reference systems for another reason.
      *
-     * @see Proj4Factory#createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem)
+     * @see Proj4Factory#createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, boolean)
+     * @see CRS#findOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, GeographicBoundingBox)
      */
     public static CoordinateOperation createOperation(final CoordinateReferenceSystem sourceCRS,
-                                                      final CoordinateReferenceSystem targetCRS)
+                                                      final CoordinateReferenceSystem targetCRS,
+                                                      final boolean force)
             throws FactoryException
     {
         ArgumentChecks.ensureNonNull("sourceCRS", sourceCRS);
         ArgumentChecks.ensureNonNull("targetCRS", targetCRS);
         try {
-            return Proj4Factory.INSTANCE.createOperation(sourceCRS, targetCRS);
+            return Proj4Factory.INSTANCE.createOperation(sourceCRS, targetCRS, force);
         } catch (UnsatisfiedLinkError | NoClassDefFoundError e) {
             throw new UnavailableFactoryException(unavailable(), e);
         }

Modified: sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4Factory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4Factory.java?rev=1802708&r1=1802707&r2=1802708&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4Factory.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Proj4Factory.java [UTF-8] Sat Jul 22 18:39:57 2017
@@ -38,6 +38,7 @@ import org.apache.sis.referencing.Identi
 import org.apache.sis.referencing.operation.DefaultConversion;
 import org.apache.sis.referencing.operation.DefaultCoordinateOperationFactory;
 import org.apache.sis.referencing.factory.InvalidGeodeticParameterException;
+import org.apache.sis.referencing.factory.UnavailableFactoryException;
 import org.apache.sis.referencing.factory.GeodeticAuthorityFactory;
 import org.apache.sis.referencing.CommonCRS;
 import org.apache.sis.internal.util.Constants;
@@ -65,7 +66,7 @@ import org.apache.sis.measure.Units;
  * <ul>
  *   <li>{@link #getAuthority()}</li>
  *   <li>{@link #createCoordinateReferenceSystem(String)}</li>
- *   <li>{@link #createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem)}</li>
+ *   <li>{@link #createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, boolean)}</li>
  *   <li>{@link #createParameterizedTransform(ParameterValueGroup)}</li>
  * </ul>
  *
@@ -101,7 +102,7 @@ public class Proj4Factory extends Geodet
     /**
      * The default factory instance.
      */
-    static final Proj4Factory INSTANCE = new Proj4Factory(null);
+    static final Proj4Factory INSTANCE = new Proj4Factory();
 
     /**
      * The default properties, or an empty map if none. This map shall not change after construction in
@@ -152,6 +153,13 @@ public class Proj4Factory extends Geodet
     private final WeakValueHashMap<String,PJ> pool = new WeakValueHashMap<>(String.class);
 
     /**
+     * Creates a default factory.
+     */
+    public Proj4Factory() {
+        this(null);
+    }
+
+    /**
      * Creates a new {@literal Proj.4} factory. The {@code properties} argument is an optional map
      * for specifying common properties shared by the objects to create. Some available properties are
      * {@linkplain org.apache.sis.referencing.AbstractIdentifiedObject#AbstractIdentifiedObject(Map) listed there}.
@@ -473,7 +481,11 @@ public class Proj4Factory extends Geodet
                 }
             }
         }
-        return createCRS(code, hasHeight);
+        try {
+            return createCRS(code, hasHeight);
+        } catch (UnsatisfiedLinkError | NoClassDefFoundError e) {
+            throw new UnavailableFactoryException(Proj4.unavailable(), e);
+        }
     }
 
     /**
@@ -625,16 +637,17 @@ public class Proj4Factory extends Geodet
 
     /**
      * Gets the {@literal Proj.4} object from the given coordinate reference system. If an existing {@code PJ}
-     * instance is found, returns it. Otherwise creates a new {@code PJ} instance from a Proj.4 definition
-     * inferred from the given CRS. This method is the converse of {@link #createCRS(PJ, boolean)}.
+     * instance is found, returns it. Otherwise if {@code force} is {@code true}, creates a new {@code PJ}
+     * instance from a Proj.4 definition inferred from the given CRS.
+     * This method is the converse of {@link #createCRS(PJ, boolean)}.
      */
-    private PJ unwrapOrCreate(final CoordinateReferenceSystem crs) throws FactoryException {
+    private PJ unwrapOrCreate(final CoordinateReferenceSystem crs, final boolean force) throws FactoryException {
         for (final Identifier id : crs.getIdentifiers()) {
             if (id instanceof PJ) {
                 return (PJ) id;
             }
         }
-        return unique(new PJ(Proj4.definition(crs)));
+        return force ? unique(new PJ(Proj4.definition(crs))) : null;
     }
 
     /**
@@ -671,22 +684,57 @@ public class Proj4Factory extends Geodet
 
     /**
      * Creates an operation for conversion or transformation between two coordinate reference systems.
-     * This implementation always uses Proj.4 for performing the coordinate operations, regardless if
-     * the given CRS were created from a Proj.4 definition string or not. This method fails if it can
-     * not map the given CRS to Proj.4 structures.
+     * The given CRSs should be instances {@linkplain #createCoordinateReferenceSystem created by this factory}.
+     * If not, then there is a choice:
+     *
+     * <ul>
+     *   <li>If {@code force} is {@code false}, then this method returns {@code null}.</li>
+     *   <li>Otherwise this method always uses Proj.4 for performing the coordinate operations,
+     *       regardless if the given CRS were created from Proj.4 definition strings or not.
+     *       This method fails if it can not map the given CRS to Proj.4 data structures.</li>
+     * </ul>
      *
      * @param  sourceCRS  the source coordinate reference system.
      * @param  targetCRS  the target coordinate reference system.
-     * @return a coordinate operation for transforming coordinates from the given source CRS to the given target CRS.
-     * @throws FactoryException if the given CRS are not instances recognized by this class.
+     * @param  force      whether to force the creation of a Proj.4 transform
+     *                    even if the given CRS are not wrappers around Proj.4 data structures.
+     * @return a coordinate operation for transforming coordinates from the given source CRS to the given target CRS, or
+     *         {@code null} if the given CRS are not wrappers around Proj.4 data structures and {@code force} is false.
+     * @throws FactoryException if {@code force} is {@code true} and this method can not create Proj.4 transform
+     *         for the given pair of coordinate reference systems.
      *
-     * @see Proj4#createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem)
+     * @see Proj4#createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, boolean)
      * @see DefaultCoordinateOperationFactory#createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem)
      */
     public CoordinateOperation createOperation(final CoordinateReferenceSystem sourceCRS,
-                                               final CoordinateReferenceSystem targetCRS)
+                                               final CoordinateReferenceSystem targetCRS,
+                                               final boolean force)
             throws FactoryException
     {
+        final PJ source, target;
+        if ((source = unwrapOrCreate(sourceCRS, force)) == null ||
+            (target = unwrapOrCreate(targetCRS, force)) == null)
+        {
+            return null;            // At least one CRS is not a Proj.4 wrapper and 'force' is false.
+        }
+        /*
+         * Before to create a transform, verify if the target CRS already contains a suitable transform.
+         * In such case, returning the existing operation is preferable since it usually contains better
+         * parameter description than what this method build.
+         */
+        if (targetCRS instanceof GeneralDerivedCRS) {
+            final CoordinateOperation op = ((GeneralDerivedCRS) targetCRS).getConversionFromBase();
+            final MathTransform tr = op.getMathTransform();
+            if (tr instanceof Transform && ((Transform) tr).isFor(sourceCRS, source, targetCRS, target)) {
+                return op;
+            }
+        }
+        /*
+         * The 'Transform' construction implies parameter validation, so we do it first before to
+         * construct other objects.
+         */
+        final Transform tr = new Transform(source, is3D("sourceCRS", sourceCRS),
+                                           target, is3D("targetCRS", targetCRS));
         Identifier id;
         String src = null, tgt = null, name = "Unnamed";
         if ((id = sourceCRS.getName()) != null) src = id.getCode();
@@ -697,8 +745,6 @@ public class Proj4Factory extends Geodet
             if (tgt != null) buffer.append(buffer.length() == 0 ? "To " : " to ").append(tgt);
             name = buffer.toString();
         }
-        final Transform tr = new Transform(unwrapOrCreate(sourceCRS), is3D("sourceCRS", sourceCRS),
-                                           unwrapOrCreate(targetCRS), is3D("targetCRS", targetCRS));
         return opFactory().createSingleOperation(identifier(name), sourceCRS, targetCRS, null, Transform.METHOD, tr);
     }
 

Modified: sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Transform.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Transform.java?rev=1802708&r1=1802707&r2=1802708&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Transform.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/Transform.java [UTF-8] Sat Jul 22 18:39:57 2017
@@ -18,6 +18,7 @@ package org.apache.sis.storage.gdal;
 
 import java.io.Serializable;
 import java.util.Collections;
+import org.opengis.util.FactoryException;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.ParameterDescriptor;
 import org.opengis.parameter.ParameterDescriptorGroup;
@@ -26,12 +27,13 @@ import org.opengis.referencing.operation
 import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.TransformException;
 import org.opengis.referencing.operation.MathTransformFactory;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
 import org.apache.sis.internal.util.Constants;
 import org.apache.sis.metadata.iso.citation.Citations;
 import org.apache.sis.parameter.ParameterBuilder;
 import org.apache.sis.referencing.operation.DefaultOperationMethod;
 import org.apache.sis.referencing.operation.transform.AbstractMathTransform;
-import org.opengis.util.FactoryException;
+import org.apache.sis.util.ComparisonMode;
 
 
 /**
@@ -196,4 +198,43 @@ final class Transform extends AbstractMa
         }
         return super.tryConcatenate(applyOtherFirst, other, factory);
     }
+
+    /**
+     * Returns {@code true} if this math transform is for the given pair of source and target CRS.
+     */
+    final boolean isFor(final CoordinateReferenceSystem sourceCRS, final PJ sourcePJ,
+                        final CoordinateReferenceSystem targetCRS, final PJ targetPJ)
+    {
+        return source.equals(sourcePJ) && dimensionMatches(sourceCRS, source3D) &&
+               target.equals(targetPJ) && dimensionMatches(targetCRS, target3D);
+    }
+
+    /**
+     * Tests whether the given CRS matches the expected number of dimensions.
+     */
+    private static boolean dimensionMatches(final CoordinateReferenceSystem crs, final boolean is3D) {
+        return crs.getCoordinateSystem().getDimension() == (is3D ? 3 : 2);
+    }
+
+    /**
+     * Computes a hash value for this transform. This method is invoked by {@link #hashCode()} when first needed.
+     */
+    @Override
+    protected int computeHashCode() {
+        return super.computeHashCode() + source.hashCode() + 31*target.hashCode();
+    }
+
+    /**
+     * Compares the given object with this transform for equality.
+     * This implementation can not ignore metadata or rounding errors.
+     */
+    @Override
+    public boolean equals(final Object object, final ComparisonMode mode) {
+        if (object instanceof Transform) {
+            final Transform that = (Transform) object;
+            return source.equals(that.source) && source3D == that.source3D
+                && target.equals(that.target) && target3D == that.target3D;
+        }
+        return false;
+    }
 }

Modified: sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/package-info.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/package-info.java?rev=1802708&r1=1802707&r2=1802708&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/package-info.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-gdal/src/main/java/org/apache/sis/storage/gdal/package-info.java [UTF-8] Sat Jul 22 18:39:57 2017
@@ -16,9 +16,10 @@
  */
 
 /**
- * Referencing services as wrapper around the C/C++ <a href="http://proj.osgeo.org/">{@literal Proj.4}</a> library.
- * Unless otherwise specified, this optional module requires the native (C/C++) Proj.4 library to be installed
- * on the local machine. This package allows to:
+ * Referencing services as wrapper around the C/C++ {@literal Proj.4} library.
+ * Current version wraps only referencing services, but future versions are expected to wrap more GDAL functionalities.
+ * Unless otherwise specified, this optional module requires the native (C/C++) <a href="http://proj.osgeo.org/">Proj.4</a>
+ * library to be installed on the local machine. This package allows to:
  * <ul>
  *   <li>{@linkplain org.apache.sis.storage.gdal.Proj4#createCRS Create a Coordinate Reference System instance from a Proj.4 definition string}.</li>
  *   <li>Conversely, {@linkplain org.apache.sis.storage.gdal.Proj4#definition get a Proj.4 definition string from a Coordinate Reference System}.</li>
@@ -26,17 +27,41 @@
  * </ul>
  *
  * Note that Apache SIS provides its own map projection engine in pure Java, so this module is usually not needed.
- * This module is useful when a desired map projection is not yet available in Apache SIS, or when an application
- * needs to reproduce the exact same numerical results than Proj.4. But some Apache SIS features like
+ * This module is useful when a map projection is not yet available in Apache SIS, or when an application needs to
+ * reproduce the exact same numerical results than Proj.4. But some Apache SIS features like
  * {@linkplain org.apache.sis.referencing.operation.transform.AbstractMathTransform#derivative transform derivatives}
  * are not available through the Proj.4 wrappers.
  *
+ * <div class="section">Note on Proj.4 definition strings</div>
+ * Proj.4 unconditionally requires 3 letters for the {@code "+axis="} parameter — for example {@code "neu"} for
+ * <cite>North</cite>, <cite>East</cite> and <cite>Up</cite> respectively — regardless the number of dimensions
+ * in the CRS to create. Apache SIS makes the vertical direction optional in order to specify whether the CRS to
+ * create shall contain a vertical axis or not:
+ *
+ * <ul>
+ *   <li>If the vertical direction is present (as in {@code "neu"}), a three-dimensional CRS is created.</li>
+ *   <li>If the vertical direction is absent (as in {@code "ne"}), a two-dimensional CRS is created.</li>
+ * </ul>
+ *
+ * <div class="note"><b>Examples:</b>
+ * <ul>
+ *   <li>{@code "+init=epsg:4326"} (<strong>not</strong> equivalent to the standard EPSG::4326 definition)</li>
+ *   <li>{@code "+proj=latlong +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0"} (default to two-dimensional CRS)</li>
+ *   <li>{@code "+proj=latlon +a=6378137.0 +b=6356752.314245179 +pm=0.0 +axis=ne"} (explicitely two-dimensional)</li>
+ *   <li>{@code "+proj=latlon +a=6378137.0 +b=6356752.314245179 +pm=0.0 +axis=neu"} (three-dimensional)</li>
+ * </ul>
+ * </div>
+ *
+ * <b>Warning:</b> despite the {@code "epsg"} word, coordinate reference systems created by {@code "+init=epsg:"}
+ * syntax are not necessarily compliant with EPSG definitions. In particular, the axis order is often different.
+ * Units of measurement may also differ.
+ *
  * <div class="section">Installation</div>
  * The Proj.4 library needs to be reachable on a platform-dependent library path.
- * For example the operating system may search in the {@code /opt/local/lib} and other directories.
- * One of those directories shall contain a {@code libproj.so}, {@code libproj.dylib} or {@code proj.dll} file,
- * depending on the platform. An easy way to install the library in appropriate directory is to use the package
- * manager provided by the platform.
+ * For example the operating system may search in {@code /usr/lib}, {@code /opt/local/lib} and other directories.
+ * One of those directories shall contain the {@code proj} or {@code libproj} file with platform-specific suffix
+ * (e.g. {@code .so}, {@code .dylib} or {@code .dll}).
+ * An easy way to install the library in appropriate directory is to use the package manager provided by the platform.
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @version 0.8

Added: sis/branches/JDK8/storage/sis-gdal/src/main/resources/META-INF/services/org.apache.sis.internal.referencing.SpecializedOperationFactory
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-gdal/src/main/resources/META-INF/services/org.apache.sis.internal.referencing.SpecializedOperationFactory?rev=1802708&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-gdal/src/main/resources/META-INF/services/org.apache.sis.internal.referencing.SpecializedOperationFactory (added)
+++ sis/branches/JDK8/storage/sis-gdal/src/main/resources/META-INF/services/org.apache.sis.internal.referencing.SpecializedOperationFactory [UTF-8] Sat Jul 22 18:39:57 2017
@@ -0,0 +1 @@
+org.apache.sis.internal.storage.gdal.OperationFactory

Propchange: sis/branches/JDK8/storage/sis-gdal/src/main/resources/META-INF/services/org.apache.sis.internal.referencing.SpecializedOperationFactory
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/storage/sis-gdal/src/main/resources/META-INF/services/org.apache.sis.internal.referencing.SpecializedOperationFactory
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Added: sis/branches/JDK8/storage/sis-gdal/src/main/resources/META-INF/services/org.opengis.referencing.crs.CRSAuthorityFactory
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-gdal/src/main/resources/META-INF/services/org.opengis.referencing.crs.CRSAuthorityFactory?rev=1802708&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-gdal/src/main/resources/META-INF/services/org.opengis.referencing.crs.CRSAuthorityFactory (added)
+++ sis/branches/JDK8/storage/sis-gdal/src/main/resources/META-INF/services/org.opengis.referencing.crs.CRSAuthorityFactory [UTF-8] Sat Jul 22 18:39:57 2017
@@ -0,0 +1 @@
+org.apache.sis.storage.gdal.Proj4Factory

Propchange: sis/branches/JDK8/storage/sis-gdal/src/main/resources/META-INF/services/org.opengis.referencing.crs.CRSAuthorityFactory
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/storage/sis-gdal/src/main/resources/META-INF/services/org.opengis.referencing.crs.CRSAuthorityFactory
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Added: sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/IntegrationTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/IntegrationTest.java?rev=1802708&view=auto
==============================================================================
--- sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/IntegrationTest.java (added)
+++ sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/IntegrationTest.java [UTF-8] Sat Jul 22 18:39:57 2017
@@ -0,0 +1,54 @@
+/*
+ * 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.storage.gdal;
+
+import org.opengis.util.FactoryException;
+import org.opengis.referencing.crs.CoordinateReferenceSystem;
+import org.opengis.referencing.operation.CoordinateOperation;
+import org.apache.sis.referencing.CRS;
+import org.apache.sis.test.TestCase;
+import org.junit.Test;
+import org.opengis.referencing.operation.TransformException;
+
+import static org.opengis.test.Assert.*;
+
+
+/**
+ * Tests the integration of the {@code sis-gdal} module in the Apache SIS framework.
+ *
+ * @author  Martin Desruisseaux (Geomatys)
+ * @version 0.8
+ * @since   0.8
+ * @module
+ */
+public final strictfp class IntegrationTest extends TestCase {
+    /**
+     * Tests usage of {@link CRS#forCode(String)}.
+     *
+     * @throws FactoryException if the coordinate reference system can not be created.
+     * @throws TransformException if an error occurred while testing a coordinate transformation.
+     */
+    @Test
+    @org.junit.Ignore
+    public void testCRS() throws FactoryException, TransformException {
+        final CoordinateReferenceSystem sourceCRS = CRS.forCode("Proj4:+init=epsg:4326");
+        final CoordinateReferenceSystem targetCRS = CRS.forCode("Proj4:+init=epsg:3395");
+        final CoordinateOperation op = CRS.findOperation(sourceCRS, targetCRS, null);
+        assertInstanceOf("Expected Proj.4 wrapper.", Transform.class, op.getMathTransform());
+        Proj4FactoryTest.testMercatorProjection(op.getMathTransform());
+    }
+}

Propchange: sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/IntegrationTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/IntegrationTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain;charset=UTF-8

Modified: sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/MTFactory.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/MTFactory.java?rev=1802708&r1=1802707&r2=1802708&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/MTFactory.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/MTFactory.java [UTF-8] Sat Jul 22 18:39:57 2017
@@ -75,6 +75,27 @@ class MTFactory extends Proj4Factory imp
     }
 
     /**
+     * Creates an operation for conversion or transformation between two coordinate reference systems.
+     * This implementation always uses Proj.4 for performing the coordinate operations, regardless if
+     * the given CRS were created from Proj.4 definition strings or not. This method fails if it can
+     * not map the given CRS to Proj.4 data structures.
+     *
+     * @param  sourceCRS  the source coordinate reference system.
+     * @param  targetCRS  the target coordinate reference system.
+     * @return a coordinate operation for transforming coordinates from the given source CRS to the given target CRS.
+     * @throws FactoryException if the given CRS are not instances recognized by this class.
+     *
+     * @see Proj4#createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem, boolean)
+     */
+    @Override
+    public CoordinateOperation createOperation(final CoordinateReferenceSystem sourceCRS,
+                                               final CoordinateReferenceSystem targetCRS)
+            throws FactoryException
+    {
+        return createOperation(sourceCRS, targetCRS, true);
+    }
+
+    /**
      * Ignores the given {@code method} argument and delegates to
      * <code>{@linkplain #createOperation(CoordinateReferenceSystem, CoordinateReferenceSystem)
      * createOperation}(sourceCRS, targetCRS)</code>.

Modified: sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/Proj4FactoryTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/Proj4FactoryTest.java?rev=1802708&r1=1802707&r2=1802708&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/Proj4FactoryTest.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/storage/gdal/Proj4FactoryTest.java [UTF-8] Sat Jul 22 18:39:57 2017
@@ -113,7 +113,7 @@ public final strictfp class Proj4Factory
         final Proj4Factory  factory   = Proj4Factory.INSTANCE;
         final GeographicCRS sourceCRS = factory.createGeographicCRS("+init=epsg:4326");
         final ProjectedCRS  targetCRS = factory.createProjectedCRS("+init=epsg:3395");
-        final CoordinateOperation op  = factory.createOperation(sourceCRS, targetCRS);
+        final CoordinateOperation op  = factory.createOperation(sourceCRS, targetCRS, true);
         assertInstanceOf("createOperation", Conversion.class, op);
         testMercatorProjection(op.getMathTransform());
     }
@@ -121,7 +121,7 @@ public final strictfp class Proj4Factory
     /**
      * Tests EPSG:3395 on a point.
      */
-    private static void testMercatorProjection(final MathTransform mt) throws TransformException {
+    static void testMercatorProjection(final MathTransform mt) throws TransformException {
         DirectPosition pt = new DirectPosition2D(20, 40);
         pt = mt.transform(pt, pt);
         assertEquals("Easting",  2226389.816, pt.getOrdinate(0), 0.01);

Modified: sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/test/suite/GDALTestSuite.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/test/suite/GDALTestSuite.java?rev=1802708&r1=1802707&r2=1802708&view=diff
==============================================================================
--- sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/test/suite/GDALTestSuite.java [UTF-8] (original)
+++ sis/branches/JDK8/storage/sis-gdal/src/test/java/org/apache/sis/test/suite/GDALTestSuite.java [UTF-8] Sat Jul 22 18:39:57 2017
@@ -34,7 +34,8 @@ import org.junit.runners.Suite;
     org.apache.sis.storage.gdal.Proj4Test.class,
     org.apache.sis.storage.gdal.Proj4ParserTest.class,
     org.apache.sis.storage.gdal.Proj4FactoryTest.class,
-    org.apache.sis.storage.gdal.TransformTest.class
+    org.apache.sis.storage.gdal.TransformTest.class,
+    org.apache.sis.storage.gdal.IntegrationTest.class
 })
 public final strictfp class GDALTestSuite extends TestSuite {
     /**



Mime
View raw message