This is an automated email from the ASF dual-hosted git repository.

desruisseaux pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 01af1418e07eefd503fd21b8ebe846c24f34307c
Merge: 0e0cde0 4f07986
Author: Martin Desruisseaux <martin.desruisse...@geomatys.com>
AuthorDate: Mon Feb 21 13:02:13 2022 +0100

    Merge branch 'geoapi-3.1'

 .../coverage/grid/FractionalGridCoordinates.java   |   2 +-
 .../apache/sis/coverage/grid/GridCoverage2D.java   |   6 +-
 .../apache/sis/coverage/grid/GridDerivation.java   |  65 ++--
 .../apache/sis/coverage/grid/GridEvaluator.java    | 215 ++++++++++-
 .../apache/sis/coverage/grid/ReshapedImage.java    |  77 ++--
 .../java/org/apache/sis/filter/LeafExpression.java |  15 +-
 .../sis/internal/coverage/j2d/TilePlaceholder.java |   3 -
 .../sis/internal/coverage/j2d/TiledImage.java      |  23 +-
 .../sis/coverage/grid/GridCoverage2DTest.java      |  37 +-
 .../sis/coverage/grid/GridDerivationTest.java      |   2 +-
 .../coverage/grid/ResampledGridCoverageTest.java   |   2 +-
 .../apache/sis/test/suite/FeatureTestSuite.java    |   1 -
 .../apache/sis/geometry}/WraparoundAdjustment.java | 409 ++++++++++++++-------
 .../apache/sis/internal/referencing/RTreeNode.java |  26 +-
 .../internal/referencing/WraparoundApplicator.java |   2 +-
 .../internal/referencing/WraparoundAxesFinder.java |  86 +++++
 .../operation/projection/ObliqueStereographic.java |   9 +-
 .../transform/SpecializableTransform.java          |  11 +-
 .../sis/geometry}/WraparoundAdjustmentTest.java    |  80 ++--
 .../projection/ObliqueStereographicTest.java       |  38 +-
 .../sis/test/suite/ReferencingTestSuite.java       |   1 +
 .../sis/util/collection/WeakValueHashMap.java      | 140 ++++++-
 .../sis/internal/converter/AngleConverterTest.java |   4 +-
 .../test/java/org/apache/sis/util/NumbersTest.java |   5 +-
 .../org/apache/sis/util/collection/CacheTest.java  |  18 +-
 .../org/apache/sis/util/collection/IntObject.java  |  65 ++++
 .../sis/util/collection/WeakHashSetTest.java       |  14 +-
 .../sis/util/collection/WeakValueHashMapTest.java  |  96 +++--
 pom.xml                                            |   4 +-
 .../org/apache/sis/storage/geotiff/DataCube.java   |   2 +-
 .../apache/sis/storage/geotiff/GeoTiffStore.java   |   4 +-
 .../apache/sis/internal/netcdf/RasterResource.java |  39 +-
 .../sis/internal/storage/AbstractGridResource.java |  60 ++-
 .../sis/internal/storage/AbstractResource.java     |  58 +++
 .../org/apache/sis/internal/storage/Resources.java |   5 +
 .../sis/internal/storage/Resources.properties      |   1 +
 .../sis/internal/storage/Resources_fr.properties   |   1 +
 .../sis/internal/storage/TiledGridCoverage.java    |  55 ++-
 .../org/apache/sis/storage/CoverageSubset.java     |   6 +-
 .../apache/sis/test/storage/SubsampledImage.java   |   7 +-
 40 files changed, 1297 insertions(+), 397 deletions(-)

diff --cc 
core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridEvaluator.java
index a5fe607,f246d44..8a38c1a
--- 
a/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridEvaluator.java
+++ 
b/core/sis-feature/src/main/java/org/apache/sis/coverage/grid/GridEvaluator.java
@@@ -24,13 -26,17 +26,17 @@@ import org.opengis.referencing.operatio
  import org.opengis.referencing.operation.TransformException;
  import org.opengis.referencing.operation.CoordinateOperation;
  import org.opengis.referencing.crs.CoordinateReferenceSystem;
 -import org.opengis.coverage.CannotEvaluateException;
 -import org.opengis.coverage.PointOutsideCoverageException;
  import org.apache.sis.coverage.SampleDimension;
  import org.apache.sis.internal.coverage.j2d.ImageUtilities;
- import org.apache.sis.referencing.CRS;
+ import org.apache.sis.internal.referencing.DirectPositionView;
+ import org.apache.sis.internal.referencing.WraparoundAxesFinder;
  import org.apache.sis.referencing.operation.transform.MathTransforms;
+ import org.apache.sis.referencing.CRS;
+ import org.apache.sis.internal.system.Modules;
  import org.apache.sis.util.ArgumentChecks;
+ import org.apache.sis.util.logging.Logging;
 +import org.apache.sis.coverage.CannotEvaluateException;
 +import org.apache.sis.coverage.PointOutsideCoverageException;
  
  
  /**
diff --cc 
core/sis-feature/src/main/java/org/apache/sis/filter/LeafExpression.java
index 2ab4039,fee716d..14819e8
--- a/core/sis-feature/src/main/java/org/apache/sis/filter/LeafExpression.java
+++ b/core/sis-feature/src/main/java/org/apache/sis/filter/LeafExpression.java
@@@ -134,14 -135,17 +134,17 @@@ abstract class LeafExpression<R,V> exte
           * @return builder of the added property.
           */
          @Override
 -        public PropertyTypeBuilder expectedType(FeatureType ignored, final 
FeatureTypeBuilder addTo) {
 +        public PropertyTypeBuilder expectedType(DefaultFeatureType ignored, 
final FeatureTypeBuilder addTo) {
              final Class<?> valueType = getValueClass();
-             DefaultAttributeType<?> propertyType = TYPES.get(valueType);
-             if (propertyType == null) {
-                 final Class<?> standardType = 
Classes.getStandardType(valueType);
-                 propertyType = TYPES.computeIfAbsent(standardType, 
Literal::newType);
-                 if (valueType != standardType) {
-                     TYPES.put(valueType, propertyType);
 -            AttributeType<?> propertyType;
++            DefaultAttributeType<?> propertyType;
+             synchronized (TYPES) {
+                 propertyType = TYPES.get(valueType);
+                 if (propertyType == null) {
+                     final Class<?> standardType = 
Classes.getStandardType(valueType);
+                     propertyType = TYPES.computeIfAbsent(standardType, 
Literal::newType);
+                     if (valueType != standardType) {
+                         TYPES.put(valueType, propertyType);
+                     }
                  }
              }
              return addTo.addProperty(propertyType);
diff --cc 
core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridCoverage2DTest.java
index 8209562,bf19bde..597742d
--- 
a/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridCoverage2DTest.java
+++ 
b/core/sis-feature/src/test/java/org/apache/sis/coverage/grid/GridCoverage2DTest.java
@@@ -27,7 -27,9 +27,8 @@@ import java.awt.image.WritableRaster
  import java.awt.image.WritableRenderedImage;
  import org.opengis.geometry.DirectPosition;
  import org.opengis.geometry.MismatchedDimensionException;
 -import org.opengis.coverage.PointOutsideCoverageException;
  import org.opengis.referencing.operation.MathTransform1D;
+ import org.opengis.referencing.operation.MathTransform;
  import org.opengis.referencing.datum.PixelInCell;
  import org.apache.sis.coverage.SampleDimension;
  import org.apache.sis.geometry.DirectPosition2D;
diff --cc 
core/sis-referencing/src/main/java/org/apache/sis/geometry/WraparoundAdjustment.java
index 32017c2,505b5f5..fb3d4c5
--- 
a/core/sis-referencing/src/main/java/org/apache/sis/geometry/WraparoundAdjustment.java
+++ 
b/core/sis-referencing/src/main/java/org/apache/sis/geometry/WraparoundAdjustment.java
@@@ -128,21 -169,105 +169,105 @@@ public class WraparoundAdjustment 
      }
  
      /**
-      * If the coordinate reference system is a projected CRS, replaces it by 
another CRS where wraparound axes can
-      * be identified. The wraparound axes are identifiable in base geographic 
CRS. If such replacement is applied,
-      * remember that we may need to transform the result later.
+      * Finds a coordinate operation from the given source CRS to target CRS.
+      * This method is invoked by all codes that need to find a coordinate 
operation.
       *
-      * @return whether the replacement has been done. If {@code true}, then 
{@link #geographicToAOI} is non-null.
+      * @param  source  the source CRS of the desired coordinate operation.
+      * @param  target  the target CRS of the desired coordinate operation.
+      * @return operation from {@code source} to {@code target}.
+      * @throws TransformException if the operation can not be computed.
       */
-     private boolean replaceCRS() {
-         if (crs instanceof ProjectedCRS) {
-             final ProjectedCRS p = (ProjectedCRS) crs;
-             crs = p.getBaseCRS();                                          // 
Geographic, so a wraparound axis certainly exists.
-             geographicToAOI = p.getConversionFromBase().getMathTransform();
-             return true;
-         } else {
-             return false;
+     private CoordinateOperation findOperation(final CoordinateReferenceSystem 
source,
+                                               final CoordinateReferenceSystem 
target)
+             throws TransformException
+     {
+         /*
+          * The (source ≉ target) condition is a quick check for avoiding
+          * unnecessary calculation of `geographicDomain` in common cases.
+          */
+         if (!geographicDomainKnown && !Utilities.equalsIgnoreMetadata(source, 
target)) try {
+             geographicDomainKnown = true;                       // Shall be 
set even in case of failure.
+             geographicDomain = 
ReferencingServices.getInstance().setBounds(domainOfValidity, null, null);
+         } catch (TransformException e) {
+             
Logging.ignorableException(Logging.getLogger(Loggers.COORDINATE_OPERATION), 
WraparoundAdjustment.class, "<init>", e);
+             // No more attempt will be done.
+         }
+         try {
+             return CRS.findOperation(source, target, geographicDomain);
+         } catch (FactoryException e) {
 -            throw new TransformException(e);
++            throw new TransformException(e.getMessage(), e);
+         }
+     }
+ 
+     /**
+      * Initializes this {@code WraparoundAdjustment} for an AOI or POI having 
the given coordinate reference system.
+      * If the given CRS is the same than the CRS given in last call to this 
method, then this method does nothing as
+      * this {@code WraparoundAdjustment} is assumed already initialized. 
Otherwise this method performs those steps:
+      *
+      * <ul>
+      *   <li>If the given coordinate reference system is a projected CRS,
+      *       replaces it by another CRS where wraparound axes can be 
identified.</li>
+      *   <li>Set {@link #shiftableDomain} to an envelope in above CRS.</li>
+      *   <li>Set {@link #periods} to an array with the periods of wraparound 
axes.</li>
+      *   <li>Set {@link #inputToResult} to the final transform to apply in 
{@code shift(…)} methods.</li>
+      * </ul>
+      *
+      * @return whether there is at least one wraparound axis.
+      */
+     private boolean initialize(CoordinateReferenceSystem crs) throws 
TransformException {
+         if (crs == null) {
+             crs = domainOfValidity.getCoordinateReferenceSystem();
+             if (crs == null && domainToInput == null) {
+                 /*
+                  * If `inputCRS` is also null, `inputToResult` will not be 
initialized by next block.
+                  * Initialize here with the assumption that following CRS as 
same as domain CRS:
+                  *
+                  *   - Input CRS, as specified in `shift(…)` method contract.
+                  *   - Result CRS, as specified in constructor contract.
+                  *
+                  * Note that this field is considered modifiable only if 
`domainToInput` is null (see its javadoc).
+                  */
+                 inputToResult = 
MathTransforms.identity(domainOfValidity.getDimension());
+             }
+         }
+         if (crs != inputCRS) {
+             inputCRS          = crs;
+             periods           = null;
+             inputToShiftable  = null;       // Will not be used if `crs` is 
null.
+             shiftableToResult = null;
+             shiftableDomain   = domainOfValidity;
+             /*
+              * Get the transform from input CRS (before replacement by 
"shiftable" CRS)
+              * to the CRS of all results. It will be needed by all `shift(…)` 
methods.
+              * Note that by convention, `inputToResult` is considered 
modifiable only
+              * if `domainToInput` is null (see its javadoc).
+              */
+             if (domainToInput == null) {
+                 if (crs != null && resultCRS != null) {
+                     inputToResult = findOperation(crs, 
resultCRS).getMathTransform();
+                 } else {
+                     inputToResult = MathTransforms.identity(
+                             (crs != null) ? 
ReferencingUtilities.getDimension(crs)
+                                           : domainOfValidity.getDimension());
+                 }
+             }
+             /*
+              * At this point we got a CRS which may have wraparound axes. 
Search for those axes.
+              * The `periods` array will become non-null only if we find at 
least one such axis.
+              */
+             if (crs != null) {
+                 /*
+                  * Replace the input CRS by an intermediate CRS where 
wraparound axes can be found.
+                  * We try to select a CRS as close as possible (simplest 
transform) to the input.
+                  */
+                 final WraparoundAxesFinder f = new WraparoundAxesFinder(crs);
+                 inputToShiftable = f.preferredToSpecified.inverse();
+                 if ((periods = f.periods()) != null) {
+                     transformDomain(f.preferredCRS);
+                 }
+             }
          }
+         return (periods != null);
      }
  
      /**
diff --cc 
core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ObliqueStereographicTest.java
index c57d4c7,f705115..1eaa2da
--- 
a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ObliqueStereographicTest.java
+++ 
b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ObliqueStereographicTest.java
@@@ -211,6 -223,42 +222,27 @@@ public final strictfp class ObliqueSter
      }
  
      /**
 -     * Tests the <cite>Oblique Stereographic</cite> case (EPSG:9809).
 -     * This test is defined in GeoAPI conformance test suite.
 -     *
 -     * @throws FactoryException if an error occurred while creating the map 
projection.
 -     * @throws TransformException if an error occurred while projecting a 
coordinate.
 -     *
 -     * @see 
org.opengis.test.referencing.ParameterizedTransformTest#testObliqueStereographic()
 -     */
 -    @Test
 -    @DependsOnMethod({"testTransform", "testInverseTransform"})
 -    public void testObliqueStereographic() throws FactoryException, 
TransformException {
 -        createGeoApiTest(new 
org.apache.sis.internal.referencing.provider.ObliqueStereographic()).testObliqueStereographic();
 -    }
 -
 -    /**
+      * Tests consistency between forward and inverse projection using a point 
that was known to fail.
+      *
+      * @throws FactoryException if an error occurred while creating the map 
projection.
+      * @throws TransformException if an error occurred while projecting a 
coordinate.
+      *
+      * @see <a 
href="https://issues.apache.org/jira/browse/SIS-537";>SIS-537</a>
+      */
+     @Test
+     public void testObliqueStereographicConsistency() throws 
FactoryException, TransformException {
+         final OperationMethod op = new 
org.apache.sis.internal.referencing.provider.ObliqueStereographic();
+         final ParameterValueGroup p = op.getParameters().createValue();
+         p.parameter("semi_major").setValue(WGS84_A);
+         p.parameter("semi_minor").setValue(WGS84_B);
+         p.parameter("Latitude of natural origin") .setValue( 45, 
Units.DEGREE);
+         p.parameter("Longitude of natural origin").setValue(-70, 
Units.DEGREE);
+         createCompleteTransform(op, p);
+         tolerance = Formulas.ANGULAR_TOLERANCE;
 -        verifyInverse(30, 45);
++        verifyInverse(new double[] {30, 45});
+     }
+ 
+     /**
       * Verifies the consistency of spherical formulas with the elliptical 
formulas.
       * This test transforms the point given in the EPSG guide and takes the 
result
       * of the elliptical implementation as a reference.

Reply via email to