This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/sis.git
commit aad6819d0be89e10362c863142286ef226a2f662 Merge: dadfde5d17 b0a78e75af Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Fri May 3 12:00:01 2024 +0200 Merge branch 'geoapi-3.1'. Contains the addition of two map projections. * https://issues.apache.org/jira/browse/SIS-233 * https://issues.apache.org/jira/browse/SIS-599 ...g.opengis.referencing.operation.OperationMethod | 2 + .../main/module-info.java | 2 + .../operation/projection/AlbersEqualArea.java | 19 +- .../operation/projection/CassiniSoldner.java | 16 +- .../operation/projection/CylindricalEqualArea.java | 23 +- .../projection/EquidistantCylindrical.java | 261 ++++++++++++++++++++ .../operation/projection/Initializer.java | 7 +- .../projection/LambertConicConformal.java | 19 +- .../referencing/operation/projection/Mercator.java | 19 +- .../projection/ModifiedAzimuthalEquidistant.java | 19 +- .../operation/projection/Mollweide.java | 11 - .../operation/projection/NormalizedProjection.java | 79 ++---- .../operation/projection/ObliqueStereographic.java | 27 ++- .../operation/projection/PolarStereographic.java | 19 +- .../operation/projection/Polyconic.java | 19 +- .../operation/projection/ProjectionVariant.java | 19 +- .../referencing/operation/projection/Robinson.java | 264 +++++++++++++++++++++ .../operation/projection/SatelliteTracking.java | 16 +- .../operation/projection/Sinusoidal.java | 24 +- .../operation/projection/TransverseMercator.java | 26 +- .../operation/provider/AlbersEqualArea.java | 2 +- .../provider/AzimuthalEquidistantSpherical.java | 2 +- .../operation/provider/CassiniSoldner.java | 2 +- .../sis/referencing/operation/provider/ESRI.java | 2 +- .../operation/provider/EquidistantCylindrical.java | 81 +++++++ .../operation/provider/Equirectangular.java | 26 +- .../provider/LambertAzimuthalEqualArea.java | 2 +- .../operation/provider/LambertConformal1SP.java | 2 +- .../operation/provider/LambertConformal2SP.java | 2 +- .../provider/LambertConformalBelgium.java | 2 +- .../provider/LambertCylindricalEqualArea.java | 2 +- .../operation/provider/MapProjection.java | 2 +- .../operation/provider/Mercator1SP.java | 2 +- .../operation/provider/Mercator2SP.java | 2 +- .../operation/provider/MillerCylindrical.java | 2 +- .../provider/ModifiedAzimuthalEquidistant.java | 2 +- .../referencing/operation/provider/Mollweide.java | 11 +- .../operation/provider/ObliqueMercator.java | 2 +- .../operation/provider/ObliqueMercatorCenter.java | 2 +- .../operation/provider/ObliqueStereographic.java | 2 +- .../operation/provider/Orthographic.java | 2 +- .../operation/provider/PolarStereographicA.java | 19 ++ .../operation/provider/PolarStereographicB.java | 2 +- .../provider/PolarStereographicSouth.java | 2 +- .../referencing/operation/provider/Polyconic.java | 2 +- .../provider/{Mollweide.java => Robinson.java} | 39 ++- .../referencing/operation/provider/Sinusoidal.java | 13 +- .../operation/provider/TransverseMercator.java | 2 +- .../provider/TransverseMercatorSouth.java | 2 +- .../referencing/operation/provider/Wraparound.java | 7 +- .../operation/transform/ContextualParameters.java | 17 +- .../operation/transform/MathTransformProvider.java | 8 +- .../apache/sis/referencing/ClenshawSummation.java | 214 +++++++++++++++-- .../operation/projection/CassiniSoldnerTest.java | 6 +- .../projection/EquidistantCylindricalTest.java | 75 ++++++ .../projection/LambertAzimuthalEqualAreaTest.java | 2 +- .../projection/MapProjectionTestCase.java | 26 ++ .../projection/ObliqueStereographicTest.java | 4 +- .../projection/PolarStereographicTest.java | 2 +- .../operation/projection/RobinsonTest.java | 118 +++++++++ .../operation/provider/ProvidersTest.java | 2 + .../apache/sis/storage/landsat/MetadataReader.java | 2 +- .../apache/sis/storage/geotiff/base/GeoKeys.java | 2 +- .../apache/sis/storage/geotiff/package-info.java | 2 +- .../geotiff/reader/ImageMetadataBuilder.java | 2 +- .../sis/storage/geotiff/writer/GeoEncoder.java | 4 +- .../apache/sis/storage/base/MetadataBuilder.java | 80 ++++++- .../main/org/apache/sis/storage/tiling/Tile.java | 21 +- .../org/apache/sis/storage/tiling/TileMatrix.java | 71 +++++- .../apache/sis/storage/tiling/TileMatrixSet.java | 52 +++- .../main/org/apache/sis/storage/wkt/Store.java | 4 +- .../main/org/apache/sis/math/Fraction.java | 42 ++-- .../main/org/apache/sis/pending/jdk/JDK15.java | 48 ++++ .../main/org/apache/sis/util/privy/Strings.java | 3 +- 74 files changed, 1604 insertions(+), 336 deletions(-) diff --cc endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/NormalizedProjection.java index 91f2af5d61,1226a486e1..7e64327033 --- a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/NormalizedProjection.java +++ b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/projection/NormalizedProjection.java @@@ -55,10 -51,9 +51,9 @@@ import org.apache.sis.referencing.privy import org.apache.sis.system.Modules; import org.apache.sis.util.privy.Constants; import org.apache.sis.util.privy.Numerics; - import org.apache.sis.util.resources.Errors; -// Specific to the geoapi-3.1 and geoapi-4.0 branches: -import org.opengis.metadata.Identifier; +// Specific to the main branch: +import org.opengis.referencing.ReferenceIdentifier; /** diff --cc endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/EquidistantCylindricalTest.java index 0000000000,cf14b0a4d0..8e02203e0e mode 000000,100644..100644 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/EquidistantCylindricalTest.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/EquidistantCylindricalTest.java @@@ -1,0 -1,90 +1,75 @@@ + /* + * 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.projection; + + import org.opengis.util.FactoryException; + import org.opengis.referencing.operation.TransformException; + import org.apache.sis.parameter.Parameters; + import org.apache.sis.geometry.DirectPosition2D; + import org.apache.sis.referencing.privy.Formulas; + import org.apache.sis.referencing.operation.provider.MapProjection; + + // Test dependencies + import org.junit.jupiter.api.Test; + import static org.junit.jupiter.api.Assertions.*; + + + /** + * Tests the {@link EquidistantCylindrical} projection. + * + * @author Martin Desruisseaux (Geomatys) + */ + public final class EquidistantCylindricalTest extends MapProjectionTestCase { + /** + * Creates a new test case. + */ + public EquidistantCylindricalTest() { + } + + /** + * Returns the provider for the "Equidistant Cylindrical" projection. + */ + private static MapProjection provider() { + return new org.apache.sis.referencing.operation.provider.EquidistantCylindrical(); + } + + /** + * Tests the point given in EPSG example. - * This is the same test as {@link #runGeoapiTest()} but is repeated here for easier debugging. + * + * @throws FactoryException if an error occurred while creating the map projection. + * @throws TransformException if an error occurred while projecting a coordinate. + */ + @Test + public void testSinglePoint() throws FactoryException, TransformException { + final MapProjection provider = provider(); + final Parameters pg = Parameters.castOrWrap(provider.getParameters().createValue()); + pg.parameter("semi-major").setValue(WGS84_A); + pg.parameter("semi-minor").setValue(WGS84_B); + transform = provider.createMathTransform(null, pg); + + final double λ = 10; + final double φ = 55; + final var p = new DirectPosition2D(λ, φ); + assertSame(p, transform.transform(p, p)); + assertEquals(1113194.91, p.x, 0.005); + assertEquals(6097230.31, p.y, 0.005); + + assertSame(p, transform.inverse().transform(p, p)); + assertEquals(λ, p.x, Formulas.ANGULAR_TOLERANCE); + assertEquals(φ, p.y, Formulas.ANGULAR_TOLERANCE); + } - - /** - * Tests the <q>Equidistant Cylindrical</q> (EPSG:1028) projection. - * 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#testEquidistantCylindrical() - */ - @Test - public void runGeoapiTest() throws FactoryException, TransformException { - createGeoApiTest(provider()).testEquidistantCylindrical(); - } + } diff --cc endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java index 9c37254533,83aebfe4e1..94e1457b79 --- a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java +++ b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/projection/MapProjectionTestCase.java @@@ -78,10 -84,49 +81,33 @@@ abstract class MapProjectionTestCase ex * @param provider the provider of the projection to test. * @return the GeoAPI test class using the given provider. */ - static ParameterizedTransformTest createGeoApiTest(final MapProjection provider) { - return new ParameterizedTransformTest(new MathTransformFactoryMock(provider)); - } - - /** - * Instantiates the object to use for running GeoAPI test without derivative tests. - * - * @param provider the provider of the projection to test. - * @return the GeoAPI test class using the given provider. - */ - static ParameterizedTransformTest createGeoApiTestNoDerivatives(final MapProjection provider) { - final class Tester extends ParameterizedTransformTest { - Tester(final MapProjection provider) { - super(new MathTransformFactoryMock(provider)); - isDerivativeSupported = false; - } - } - return new Tester(provider); + static ParameterizedTransformTestMock createGeoApiTest(final MapProjection provider) { + return new ParameterizedTransformTestMock(new MathTransformFactoryMock(provider)); } + /** + * Creates a context with the given factory and parameters, used for map projection construction. + * The given parameters should not be {@code null}, but this method nevertheless accepts null when + * the caller knows that the tested code will not use parameters. + * + * @param factory the factory to use, or {@code null} for the default one. + * @param parameters the parameters. Should not be null, but null is nevertheless accepted for testing purposes. + * @return the context to use in map projection construction. + */ + static MathTransformProvider.Context context(final MathTransformFactory factory, final ParameterValueGroup parameters) { + return new MathTransformProvider.Context() { + /** Returns the specified factory, or the default one if none. */ + @Override public MathTransformFactory getFactory() { + return (factory != null) ? factory : MathTransformProvider.Context.super.getFactory(); + } + + /** Returns the specified parameters (possible null). */ + @Override public ParameterValueGroup getCompletedParameters() { + return parameters; + } + }; + } + /** * Returns the parameters to use for instantiating the projection to test. * The parameters are initialized with the ellipse semi-axis lengths. diff --cc endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java index cecc265cee,3056e53727..a58ca86ac7 --- a/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java +++ b/endorsed/src/org.apache.sis.storage/main/org/apache/sis/storage/base/MetadataBuilder.java @@@ -1926,6 -1945,59 +1948,58 @@@ public class MetadataBuilder return true; } + /** + * Adds linear and temporal resolutions computed from an array of resolutions for each CRS axis. + * This method tries to separate the horizontal, vertical and temporal components. + * The horizontal components can be linear or angular. + * Storage locations are: + * + * <ul> + * <li>{@code metadata/identificationInfo/spatialResolution/distance}</li> + * <li>{@code metadata/identificationInfo/temporalResolution}</li> + * </ul> + * + * @param resolution the resolution for each coordinate system axis, or {@code null} if unknown. + * @param cs the coordinate system, or {@code null} if unknown. + */ + public final void addSpatioTemporalResolution(final double[] resolution, final CoordinateSystem cs) { + if (resolution != null && cs != null) try { + final int dimension = Math.min(resolution.length, cs.getDimension()); + for (int i=0; i<dimension; i++) { + final CoordinateSystemAxis axis = cs.getAxis(i); + final Unit<?> unit = axis.getUnit(); + final Unit<?> targetUnit; + final BiConsumer<DefaultResolution,Double> setter; + if (Units.isLinear(unit)) { + targetUnit = Units.METRE; + if (AxisDirections.isVertical(axis.getDirection())) { + setter = DefaultResolution::setVertical; + } else { + setter = DefaultResolution::setDistance; + } + } else if (Units.isAngular(unit)) { + targetUnit = Units.DEGREE; + setter = DefaultResolution::setAngularDistance; - } else if (Units.isTemporal(unit) && AxisDirections.isTemporal(axis.getDirection())) { - targetUnit = Units.DAY; - setter = null; + } else { + continue; + } + final double distance = unit.getConverterToAny(targetUnit).convert(resolution[i]); - if (setter == null) { - addTemporalResolution(distance); - } else if (Double.isFinite(distance)) { ++ /* ++ * Handling of temporal units is not available in this branch, ++ * because `Duration` is not available in GeoAPI 3.0 interfaces. ++ */ ++ if (Double.isFinite(distance)) { + var r = new DefaultResolution(); + setter.accept(r, shared(distance)); + addIfNotPresent(identification().getSpatialResolutions(), r); + } + } + } catch (IncommensurableException e) { + // Should never happen because we verified that the unit was linear or temporal. + Logging.unexpectedException(StoreUtilities.LOGGER, MetadataBuilder.class, "addSpatioTemporalResolution", e); + } + } + /** * Adds a linear resolution in metres. * Storage location is: