This is an automated email from the ASF dual-hosted git repository.
desruisseaux pushed a commit to branch geoapi-4.0
in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new 8f1e806 Begin implementation of "Modified Azimuthal Equidistant" projection (EPSG:9832).
Only forward projection for now. Inverse projection and derivative will be in a next commit.
8f1e806 is described below
commit 8f1e80667c5b2249d405b0aedd380c1040d966be
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Tue Mar 17 22:43:52 2020 +0100
Begin implementation of "Modified Azimuthal Equidistant" projection (EPSG:9832).
Only forward projection for now. Inverse projection and derivative will be in a next commit.
https://issues.apache.org/jira/browse/SIS-237
---
.../provider/ModifiedAzimuthalEquidistant.java | 163 +++++++++++++++++
.../projection/ModifiedAzimuthalEquidistant.java | 198 +++++++++++++++++++++
...g.opengis.referencing.operation.OperationMethod | 1 +
.../referencing/provider/ProvidersTest.java | 1 +
.../ModifiedAzimuthalEquidistantTest.java | 50 ++++++
.../sis/test/suite/ReferencingTestSuite.java | 1 +
6 files changed, 414 insertions(+)
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ModifiedAzimuthalEquidistant.java
b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ModifiedAzimuthalEquidistant.java
new file mode 100644
index 0000000..9b2abd1
--- /dev/null
+++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/ModifiedAzimuthalEquidistant.java
@@ -0,0 +1,163 @@
+/*
+ * 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.provider;
+
+import javax.xml.bind.annotation.XmlTransient;
+import org.opengis.parameter.ParameterDescriptor;
+import org.opengis.parameter.ParameterDescriptorGroup;
+import org.apache.sis.parameter.ParameterBuilder;
+import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.parameter.Parameters;
+import org.apache.sis.referencing.operation.projection.NormalizedProjection;
+import org.opengis.referencing.operation.PlanarProjection;
+
+
+/**
+ * The provider for <cite>"Modified Azimuthal Equidistant"</cite> projection
(EPSG:9832).
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.1
+ *
+ * @see <a href="http://geotiff.maptools.org/proj_list/azimuthal_equidistant.html">GeoTIFF
parameters for Azimuthal Equidistant</a>
+ *
+ * @since 1.1
+ * @module
+ */
+@XmlTransient
+public final class ModifiedAzimuthalEquidistant extends MapProjection {
+ /**
+ * For cross-version compatibility.
+ */
+ private static final long serialVersionUID = -9025540136016917410L;
+
+ /**
+ * The operation parameter descriptor for the <cite>Latitude of natural origin</cite>
(φ₀) parameter value.
+ * Valid values range is (-90 … 90)° and default value is 0°.
+ *
+ * <!-- Generated by ParameterNameTableGenerator -->
+ * <table class="sis">
+ * <caption>Parameter names</caption>
+ * <tr><td> EPSG: </td><td> Latitude of natural origin </td></tr>
+ * <tr><td> GeoTIFF: </td><td> CenterLat </td></tr>
+ * <tr><td> Proj4: </td><td> lat_0 </td></tr>
+ * </table>
+ */
+ public static final ParameterDescriptor<Double> LATITUDE_OF_ORIGIN;
+
+ /**
+ * The operation parameter descriptor for the <cite>Longitude of natural origin</cite>
(λ₀) parameter value.
+ * Valid values range is [-180 … 180]° and default value is 0°.
+ *
+ * <!-- Generated by ParameterNameTableGenerator -->
+ * <table class="sis">
+ * <caption>Parameter names</caption>
+ * <tr><td> EPSG: </td><td> Longitude of natural origin
</td></tr>
+ * <tr><td> GeoTIFF: </td><td> CenterLong </td></tr>
+ * <tr><td> Proj4: </td><td> lon_0 </td></tr>
+ * </table>
+ */
+ public static final ParameterDescriptor<Double> LONGITUDE_OF_ORIGIN;
+
+ /**
+ * The operation parameter descriptor for the <cite>False easting</cite>
(FE) parameter value.
+ * Valid values range is unrestricted and default value is 0 metre.
+ *
+ * <!-- Generated by ParameterNameTableGenerator -->
+ * <table class="sis">
+ * <caption>Parameter names</caption>
+ * <tr><td> EPSG: </td><td> False easting </td></tr>
+ * <tr><td> GeoTIFF: </td><td> FalseEasting </td></tr>
+ * <tr><td> Proj4: </td><td> x_0 </td></tr>
+ * </table>
+ */
+ public static final ParameterDescriptor<Double> FALSE_EASTING;
+
+ /**
+ * The operation parameter descriptor for the <cite>False northing</cite>
(FN) parameter value.
+ * Valid values range is unrestricted and default value is 0 metre.
+ *
+ * <!-- Generated by ParameterNameTableGenerator -->
+ * <table class="sis">
+ * <caption>Parameter names</caption>
+ * <tr><td> EPSG: </td><td> False northing </td></tr>
+ * <tr><td> GeoTIFF: </td><td> FalseNorthing </td></tr>
+ * <tr><td> Proj4: </td><td> y_0 </td></tr>
+ * </table>
+ */
+ public static final ParameterDescriptor<Double> FALSE_NORTHING;
+
+ /**
+ * Returns a parameter with the same names and identifiers than the given parameter,
+ * except OGC, ESRI and netCDF names which are omitted. We omit those names for now
+ * because we have not seen a reference about what those parameter names should be.
+ * This may be revisited in future SIS versions.
+ *
+ * <p>The OGC and GeoTIFF names kept by this method are actually the names for
+ * <cite>Azimuthal Equidistant</cite> (not modified) projection.</p>
+ */
+ private static ParameterBuilder erase(final ParameterBuilder builder, ParameterDescriptor<?>
template) {
+ return builder.addNamesAndIdentifiers(template) // Copy from
this parameter…
+ .rename(Citations.OGC, (CharSequence[]) null) // … except
for those names.
+ .rename(Citations.ESRI, (CharSequence[]) null)
+ .rename(Citations.NETCDF, (CharSequence[]) null);
+ }
+
+ /**
+ * The group of all parameters expected by this coordinate operation.
+ */
+ static final ParameterDescriptorGroup PARAMETERS;
+ static {
+ final ParameterBuilder builder = builder();
+ LATITUDE_OF_ORIGIN = createLatitude (erase(builder, Orthographic.LATITUDE_OF_ORIGIN),
true);
+ LONGITUDE_OF_ORIGIN = createLongitude(erase(builder, Orthographic.LONGITUDE_OF_ORIGIN));
+ FALSE_EASTING = createShift (erase(builder, Orthographic.FALSE_EASTING));
+ FALSE_NORTHING = createShift (erase(builder, Orthographic.FALSE_NORTHING));
+
+ PARAMETERS = builder.addIdentifier("9832")
+ .addName("Modified Azimuthal Equidistant")
+ .createGroupForMapProjection(
+ LATITUDE_OF_ORIGIN,
+ LONGITUDE_OF_ORIGIN,
+ FALSE_EASTING,
+ FALSE_NORTHING);
+ }
+
+ /**
+ * Constructs a new provider.
+ */
+ public ModifiedAzimuthalEquidistant() {
+ super(PARAMETERS);
+ }
+
+ /**
+ * Returns the operation type for this map projection.
+ */
+ @Override
+ public Class<PlanarProjection> getOperationType() {
+ return PlanarProjection.class;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @return the map projection created from the given parameter values.
+ */
+ @Override
+ protected final NormalizedProjection createProjection(final Parameters parameters) {
+ return new org.apache.sis.referencing.operation.projection.ModifiedAzimuthalEquidistant(this,
parameters);
+ }
+}
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ModifiedAzimuthalEquidistant.java
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ModifiedAzimuthalEquidistant.java
new file mode 100644
index 0000000..51e5663
--- /dev/null
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/ModifiedAzimuthalEquidistant.java
@@ -0,0 +1,198 @@
+/*
+ * 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 java.util.EnumMap;
+import org.opengis.referencing.operation.Matrix;
+import org.opengis.referencing.operation.OperationMethod;
+import org.opengis.parameter.ParameterDescriptor;
+import org.apache.sis.parameter.Parameters;
+import org.apache.sis.referencing.operation.transform.ContextualParameters;
+import org.apache.sis.referencing.operation.matrix.MatrixSIS;
+import org.apache.sis.internal.util.Numerics;
+import org.apache.sis.util.ComparisonMode;
+import org.apache.sis.util.Workaround;
+
+import static java.lang.Math.*;
+import static org.apache.sis.internal.referencing.provider.ModifiedAzimuthalEquidistant.*;
+
+
+/**
+ * <cite>Modified Azimuthal Equidistant</cite> projection (EPSG:9832).
+ * See the following references for an overview:
+ * <ul>
+ * <li><a href="https://en.wikipedia.org/wiki/Azimuthal_equidistant_projection">Azimuthal
equidistant projection</a></li>
+ * <li><a href="https://mathworld.wolfram.com/AzimuthalEquidistantProjection.html">Azimuthal
Equidistant Projection</a></li>
+ * </ul>
+ *
+ * <h2>Description</h2>
+ * An approximation of the oblique form of the <cite>Azimuthal Equidistant</cite>
projection.
+ * For relatively short distances (e.g. under 800 kilometres) this modification introduces
no significant error.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.1
+ * @since 1.1
+ * @module
+ */
+public class ModifiedAzimuthalEquidistant extends NormalizedProjection {
+ /**
+ * Sine and cosine of the latitude of origin φ₀.
+ */
+ private final double sinφ0, cosφ0;
+
+ /**
+ * The radius of curvature (assuming <var>a</var>=1) at the latitude of origin
+ * multiplied by the sine of that latitude.
+ */
+ private final double ℯ2_ν0_sinφ0;
+
+ /**
+ * The ℯ⋅sin(φ₀)/√(1 − ℯ²) term.
+ */
+ private final double G;
+
+ /**
+ * The ℯ⋅cos(φ₀)/√(1 − ℯ²) term. This is the <var>H</var> term
in EPSG guidance notes
+ * but without the cos(α) term.
+ */
+ private final double Hp;
+
+ /**
+ * Work around for RFE #4093999 in Sun's bug database
+ * ("Relax constraint on placement of this()/super() call in constructors").
+ */
+ @Workaround(library="JDK", version="1.8")
+ private static Initializer initializer(final OperationMethod method, final Parameters
parameters) {
+ final EnumMap<ParameterRole, ParameterDescriptor<Double>> roles = new
EnumMap<>(ParameterRole.class);
+ roles.put(ParameterRole.CENTRAL_MERIDIAN, LONGITUDE_OF_ORIGIN);
+ roles.put(ParameterRole.FALSE_EASTING, FALSE_EASTING);
+ roles.put(ParameterRole.FALSE_NORTHING, FALSE_NORTHING);
+ return new Initializer(method, parameters, roles, (byte) 0);
+ }
+
+ /**
+ * Creates a Modified Azimuthal Equidistant projection from the given parameters.
+ * The {@code method} argument can be the description of one of the following:
+ *
+ * <ul>
+ * <li><cite>"Modified Azimuthal Equidistant"</cite>.</li>
+ * </ul>
+ *
+ * @param method description of the projection parameters.
+ * @param parameters the parameter values of the projection to create.
+ */
+ public ModifiedAzimuthalEquidistant(final OperationMethod method, final Parameters parameters)
{
+ this(initializer(method, parameters));
+ }
+
+ /**
+ * Work around for RFE #4093999 in Sun's bug database
+ * ("Relax constraint on placement of this()/super() call in constructors").
+ */
+ @Workaround(library="JDK", version="1.8")
+ private ModifiedAzimuthalEquidistant(final Initializer initializer) {
+ super(initializer);
+ final double φ0 = toRadians(initializer.getAndStore(LATITUDE_OF_ORIGIN));
+ cosφ0 = cos(φ0);
+ sinφ0 = sin(φ0);
+ final double ν0 = initializer.radiusOfCurvature(sinφ0);
+ ℯ2_ν0_sinφ0 = eccentricitySquared * ν0 * sinφ0;
+ final double f = eccentricity / sqrt(1 - eccentricitySquared);
+ G = f * sinφ0;
+ Hp = f * cosφ0;
+
+ final MatrixSIS denormalize = context.getMatrix(ContextualParameters.MatrixRole.DENORMALIZATION);
+ denormalize.convertBefore(0, ν0, null);
+ denormalize.convertBefore(1, ν0, null);
+ }
+
+ /**
+ * Converts the specified (λ,φ) coordinate and stores the (<var>x</var>,<var>y</var>)
result in {@code dstPts}.
+ *
+ * @return the matrix of the projection derivative at the given source position,
+ * or {@code null} if the {@code derivate} argument is {@code false}.
+ * @throws ProjectionException if the coordinate can not be converted.
+ */
+ @Override
+ public Matrix transform(final double[] srcPts, final int srcOff,
+ final double[] dstPts, final int dstOff,
+ final boolean derivate) throws ProjectionException
+ {
+ final double λ = srcPts[srcOff ];
+ final double φ = srcPts[srcOff+1];
+ final double cosλ = cos(λ);
+ final double sinλ = sin(λ);
+ final double cosφ = cos(φ);
+ final double sinφ = sin(φ);
+ final double rν = sqrt(1 - eccentricitySquared*(sinφ*sinφ));
+ final double Ψ = atan((1 - eccentricitySquared)*tan(φ) + ℯ2_ν0_sinφ0*rν/cosφ);
+ final double α = atan2(sinλ, cosφ0*tan(Ψ) - sinφ0*cosλ);
+ final double sinα = sin(α);
+ final double cosα = cos(α);
+ final double H = cosα * Hp;
+ double c;
+ if (abs(α) < ANGULAR_TOLERANCE) {
+ c = cosφ0*sin(Ψ) - sinφ0*cos(Ψ);
+ if (abs(α) > PI/2) c = -c;
+ } else {
+ c = sinλ*cos(Ψ) / sinα;
+ }
+ c = asin(c); // After this line this is the `s` value in EPSG
guidance notes.
+ final double s2 = c * c;
+ final double s3 = s2 * c;
+ final double s4 = s2 * s2;
+ final double s5 = s4 * c;
+ final double H2 = H*H;
+ final double GH = G*H;
+ c *= 1 - (s2/6 * H2*(1 - H2))
+ + (s3/8 * GH*(1 - 2*H2))
+ + (s4/120 * (H2*(4 - 7*H2) - 3*(G*G)*(1 - 7*H2)))
+ - (s5/48 * GH);
+ if (dstPts != null) {
+ dstPts[dstOff ] = c*sinα;
+ dstPts[dstOff+1] = c*cosα;
+ }
+ if (!derivate) {
+ return null;
+ }
+ throw new ProjectionException("Derivative not yet implemented.");
+ }
+
+ /**
+ * Converts the specified (<var>x</var>,<var>y</var>) coordinates
+ * and stores the result in {@code dstPts} (angles in radians).
+ */
+ @Override
+ protected void inverseTransform(final double[] srcPts, final int srcOff,
+ final double[] dstPts, final int dstOff)
+ throws ProjectionException
+ {
+ throw new ProjectionException("Inverse transform not yet implemented.");
+ }
+
+ /**
+ * Compares the given object with this transform for equivalence.
+ */
+ @Override
+ public boolean equals(final Object object, final ComparisonMode mode) {
+ if (super.equals(object, mode)) {
+ final ModifiedAzimuthalEquidistant that = (ModifiedAzimuthalEquidistant) object;
+ return Numerics.epsilonEqual(ℯ2_ν0_sinφ0, that.ℯ2_ν0_sinφ0, mode);
+ }
+ return false;
+ }
+}
diff --git a/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod
b/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod
index ae5ddfe..b549967 100644
--- a/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod
+++ b/core/sis-referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.OperationMethod
@@ -55,6 +55,7 @@ org.apache.sis.internal.referencing.provider.ObliqueMercatorCenter
org.apache.sis.internal.referencing.provider.ObliqueMercatorTwoPoints
org.apache.sis.internal.referencing.provider.ObliqueMercatorTwoPointsCenter
org.apache.sis.internal.referencing.provider.Orthographic
+org.apache.sis.internal.referencing.provider.ModifiedAzimuthalEquidistant
org.apache.sis.internal.referencing.provider.ZonedTransverseMercator
org.apache.sis.internal.referencing.provider.Sinusoidal
org.apache.sis.internal.referencing.provider.Polyconic
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java
b/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java
index 3373bae..7bc59ed 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/internal/referencing/provider/ProvidersTest.java
@@ -104,6 +104,7 @@ public final strictfp class ProvidersTest extends TestCase {
ObliqueMercatorTwoPoints.class,
ObliqueMercatorTwoPointsCenter.class,
Orthographic.class,
+ ModifiedAzimuthalEquidistant.class,
ZonedTransverseMercator.class,
SatelliteTracking.class,
Sinusoidal.class,
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ModifiedAzimuthalEquidistantTest.java
b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ModifiedAzimuthalEquidistantTest.java
new file mode 100644
index 0000000..f131653
--- /dev/null
+++ b/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/projection/ModifiedAzimuthalEquidistantTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.referencing.operation.TransformException;
+import org.opengis.util.FactoryException;
+import org.apache.sis.test.DependsOn;
+import org.junit.Test;
+
+
+/**
+ * Tests the {@link ModifiedAzimuthalEquidistant} class.
+ *
+ * @author Martin Desruisseaux (Geomatys)
+ * @version 1.1
+ * @since 1.1
+ * @module
+ */
+@DependsOn(NormalizedProjectionTest.class)
+public final strictfp class ModifiedAzimuthalEquidistantTest extends MapProjectionTestCase
{
+ /**
+ * Tests the <cite>"Modified Azimuthal Equidistant"</cite> (EPSG:9832) projection
method.
+ * 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#testModifiedAzimuthalEquidistant()
+ */
+ @Test
+ @org.junit.Ignore("Implementation not yet completed")
+ public void runGeoapiTest() throws FactoryException, TransformException {
+ createGeoApiTest(new org.apache.sis.internal.referencing.provider.ModifiedAzimuthalEquidistant())
+ .testModifiedAzimuthalEquidistant();
+ }
+}
diff --git a/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
b/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
index 5e26fe4..7d9facb 100644
--- a/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
+++ b/core/sis-referencing/src/test/java/org/apache/sis/test/suite/ReferencingTestSuite.java
@@ -192,6 +192,7 @@ import org.junit.BeforeClass;
org.apache.sis.referencing.operation.projection.PolyconicTest.class,
org.apache.sis.referencing.operation.projection.MollweideTest.class,
org.apache.sis.referencing.operation.projection.OrthographicTest.class,
+ org.apache.sis.referencing.operation.projection.ModifiedAzimuthalEquidistantTest.class,
org.apache.sis.referencing.operation.projection.SatelliteTrackingTest.class,
// Coordinate operation and derived Coordinate Reference Systems (cyclic dependency).
|