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 27b60b2 Parse GEOGTRAN element from ESRI WKT. 27b60b2 is described below commit 27b60b23d30d8ed59c1a23ed62b5b15a9fcb5db6 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Thu Feb 24 00:07:48 2022 +0100 Parse GEOGTRAN element from ESRI WKT. https://issues.apache.org/jira/browse/SIS-538 --- .../sis/internal/referencing/WKTKeywords.java | 5 +- .../provider/CoordinateFrameRotation2D.java | 4 +- .../provider/GeocentricTranslation2D.java | 4 +- .../provider/PositionVector7Param2D.java | 4 +- .../apache/sis/io/wkt/GeodeticObjectParser.java | 79 ++++++++++++++++++---- .../sis/io/wkt/GeodeticObjectParserTest.java | 40 ++++++++++- 6 files changed, 117 insertions(+), 19 deletions(-) diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/WKTKeywords.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/WKTKeywords.java index aab1794..5cba02d 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/WKTKeywords.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/WKTKeywords.java @@ -38,7 +38,7 @@ import org.apache.sis.util.ArraysExt; * * @author Martin Desruisseaux (Geomatys) * @author Johann Sorel (Geomatys) - * @version 1.1 + * @version 1.2 * * @see <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html">WKT 2 specification</a> * @see <a href="http://www.geoapi.org/3.0/javadoc/org/opengis/referencing/doc-files/WKT.html">Legacy WKT 1</a> @@ -190,7 +190,8 @@ public final class WKTKeywords extends Static { InterpolationCRS = "InterpolationCRS", Parameter = "Parameter", ParameterFile = "ParameterFile", - ParameterGroup = "ParameterGroup"; + ParameterGroup = "ParameterGroup", + GeogTran = "GeogTran"; // ESRI-specific. /** * Related to {@link org.apache.sis.referencing.operation.transform.AbstractMathTransform}. diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/CoordinateFrameRotation2D.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/CoordinateFrameRotation2D.java index 40811bf..793ee0b 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/CoordinateFrameRotation2D.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/CoordinateFrameRotation2D.java @@ -18,6 +18,7 @@ package org.apache.sis.internal.referencing.provider; import javax.xml.bind.annotation.XmlTransient; import org.opengis.parameter.ParameterDescriptorGroup; +import org.apache.sis.metadata.iso.citation.Citations; /** @@ -26,7 +27,7 @@ import org.opengis.parameter.ParameterDescriptorGroup; * except that the rotation angles have the opposite sign. * * @author Martin Desruisseaux (IRD, Geomatys) - * @version 0.7 + * @version 1.2 * @since 0.7 * @module */ @@ -45,6 +46,7 @@ public final class CoordinateFrameRotation2D extends GeocentricAffineBetweenGeog PARAMETERS = builder() .addIdentifier("9607") .addName("Coordinate Frame Rotation (geog2D domain)") + .addName(Citations.ESRI, "Coordinate_Frame") .createGroupWithSameParameters(PositionVector7Param2D.PARAMETERS); /* * NOTE: we omit the "Bursa-Wolf" alias because it is ambiguous, since it can apply diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricTranslation2D.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricTranslation2D.java index 8d82430..2ddc373 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricTranslation2D.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/GeocentricTranslation2D.java @@ -18,6 +18,7 @@ package org.apache.sis.internal.referencing.provider; import javax.xml.bind.annotation.XmlTransient; import org.opengis.parameter.ParameterDescriptorGroup; +import org.apache.sis.metadata.iso.citation.Citations; /** @@ -26,7 +27,7 @@ import org.opengis.parameter.ParameterDescriptorGroup; * terms can be set to a non-null value. * * @author Martin Desruisseaux (IRD, Geomatys) - * @version 0.7 + * @version 1.2 * @since 0.7 * @module */ @@ -45,6 +46,7 @@ public final class GeocentricTranslation2D extends GeocentricAffineBetweenGeogra PARAMETERS = builder() .addIdentifier("9603") .addName("Geocentric translations (geog2D domain)") + .addName(Citations.ESRI, "Geocentric_Translation") .createGroup(SRC_SEMI_MAJOR, SRC_SEMI_MINOR, TGT_SEMI_MAJOR, diff --git a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PositionVector7Param2D.java b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PositionVector7Param2D.java index fd31367..9ef0cd3 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PositionVector7Param2D.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/internal/referencing/provider/PositionVector7Param2D.java @@ -18,13 +18,14 @@ package org.apache.sis.internal.referencing.provider; import javax.xml.bind.annotation.XmlTransient; import org.opengis.parameter.ParameterDescriptorGroup; +import org.apache.sis.metadata.iso.citation.Citations; /** * The provider for <cite>"Position Vector transformation (geog2D domain)"</cite> (EPSG:9606). * * @author Martin Desruisseaux (IRD, Geomatys) - * @version 0.7 + * @version 1.2 * @since 0.7 * @module */ @@ -43,6 +44,7 @@ public final class PositionVector7Param2D extends GeocentricAffineBetweenGeograp PARAMETERS = builder() .addIdentifier("9606") .addName("Position Vector transformation (geog2D domain)") + .addName(Citations.ESRI, "Position_Vector") .createGroup(SRC_SEMI_MAJOR, SRC_SEMI_MINOR, TGT_SEMI_MAJOR, diff --git a/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java b/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java index 2d30f41..3ed1bf7 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/io/wkt/GeodeticObjectParser.java @@ -98,7 +98,7 @@ import static java.util.Collections.singletonMap; * @author Rémi Eve (IRD) * @author Martin Desruisseaux (IRD, Geomatys) * @author Johann Sorel (Geomatys) - * @version 1.1 + * @version 1.2 * @since 0.6 * @module */ @@ -319,7 +319,8 @@ class GeodeticObjectParser extends MathTransformParser implements Comparator<Coo (object = parseParametricDatum (FIRST, element )) == null && (object = parseEngineeringDatum (FIRST, element, false)) == null && (object = parseImageDatum (FIRST, element )) == null && - (object = parseOperation (FIRST, element)) == null) + (object = parseOperation (FIRST, element)) == null && + (object = parseGeogTranslation (FIRST, element)) == null) { throw element.missingOrUnknownComponent(WKTKeywords.GeodeticCRS); } @@ -407,6 +408,8 @@ class GeodeticObjectParser extends MathTransformParser implements Comparator<Coo * @param fallback the fallback to use if {@code name} is empty. * @return a properties map with the parent name and the optional authority code. * @throws ParseException if an element can not be parsed. + * + * @see #parseParametersAndClose(Element, String, OperationMethod) */ @SuppressWarnings("ReturnOfCollectionOrArrayField") private Map<String,Object> parseMetadataAndClose(final Element parent, final String name, @@ -2248,6 +2251,32 @@ class GeodeticObjectParser extends MathTransformParser implements Comparator<Coo } /** + * Parses a {@code "GeogTran"} element. This is specific to ESRI. + * + * @param mode {@link #FIRST}, {@link #OPTIONAL} or {@link #MANDATORY}. + * @param parent the parent element. + * @return the {@code "GeogTran"} element as a {@link CoordinateOperation} object. + * @throws ParseException if the {@code "GeogTran"} element can not be parsed. + */ + private CoordinateOperation parseGeogTranslation(final int mode, final Element parent) throws ParseException { + final Element element = parent.pullElement(mode, WKTKeywords.GeogTran); + if (element == null) { + return null; + } + final String name = element.pullString("name"); + final CoordinateReferenceSystem sourceCRS = parseCoordinateReferenceSystem(element, true); + final CoordinateReferenceSystem targetCRS = parseCoordinateReferenceSystem(element, true); + final OperationMethod method = parseMethod(element, WKTKeywords.Method); + final Map<String,Object> properties = parseParametersAndClose(element, name, method); + try { + final DefaultCoordinateOperationFactory df = getOperationFactory(); + return df.createSingleOperation(properties, sourceCRS, targetCRS, null, method, null); + } catch (FactoryException e) { + throw element.parseFailed(e); + } + } + + /** * Parses a {@code "CoordinateOperation"} element. The syntax is given by * <a href="http://docs.opengeospatial.org/is/12-063r5/12-063r5.html#113">WKT 2 specification §17</a>. * @@ -2267,26 +2296,50 @@ class GeodeticObjectParser extends MathTransformParser implements Comparator<Coo final CoordinateReferenceSystem interpolationCRS = parseCoordinateReferenceSystem(element, OPTIONAL, WKTKeywords.InterpolationCRS); final OperationMethod method = parseMethod(element, WKTKeywords.Method); final Element accuracy = element.pullElement(OPTIONAL, WKTKeywords.OperationAccuracy); - final Map<String,Object> properties = parseMetadataAndClose(element, name, method); - final ParameterValueGroup parameters = method.getParameters().createValue(); - parseParameters(element, parameters, null, null); - properties.put(CoordinateOperations.PARAMETERS_KEY, parameters); + final Map<String,Object> properties = parseParametersAndClose(element, name, method); if (accuracy != null) { properties.put(CoordinateOperation.COORDINATE_OPERATION_ACCURACY_KEY, TransformationAccuracy.create(accuracy.pullDouble("accuracy"))); accuracy.close(ignoredElements); } try { - final DefaultCoordinateOperationFactory df; - final CoordinateOperationFactory opFactory = factories.getCoordinateOperationFactory(); - if (opFactory instanceof DefaultCoordinateOperationFactory) { - df = (DefaultCoordinateOperationFactory) opFactory; - } else { - df = CoordinateOperations.factory(); - } + final DefaultCoordinateOperationFactory df = getOperationFactory(); return df.createSingleOperation(properties, sourceCRS, targetCRS, interpolationCRS, method, null); } catch (FactoryException e) { throw element.parseFailed(e); } } + + /** + * Parses a sequence of {@code "PARAMETER"} elements, then parses optional metadata elements and close. + * + * @param parent the parent element. + * @param name the name of the parent object being parsed. + * @param method the operation method, also the fallback to use if {@code name} is empty. + * @return a properties map with the parent name, the optional authority code and the parameters. + * @throws ParseException if an element can not be parsed. + * + * @see #parseMetadataAndClose(Element, String, IdentifiedObject) + */ + private Map<String,Object> parseParametersAndClose(final Element parent, final String name, + final OperationMethod method) throws ParseException + { + final ParameterValueGroup parameters = method.getParameters().createValue(); + parseParameters(parent, parameters, null, null); + final Map<String,Object> properties = parseMetadataAndClose(parent, name, method); + properties.put(CoordinateOperations.PARAMETERS_KEY, parameters); + return properties; + } + + /** + * Returns the factory to use for creating coordinate operation. + */ + private DefaultCoordinateOperationFactory getOperationFactory() { + final CoordinateOperationFactory opFactory = factories.getCoordinateOperationFactory(); + if (opFactory instanceof DefaultCoordinateOperationFactory) { + return (DefaultCoordinateOperationFactory) opFactory; + } else { + return CoordinateOperations.factory(); + } + } } diff --git a/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java b/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java index 8aaeb76..e092f7f 100644 --- a/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java +++ b/core/sis-referencing/src/test/java/org/apache/sis/io/wkt/GeodeticObjectParserTest.java @@ -31,6 +31,7 @@ import org.opengis.referencing.datum.*; import org.opengis.referencing.operation.Matrix; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.NoninvertibleTransformException; +import org.opengis.referencing.operation.CoordinateOperation; import org.opengis.parameter.ParameterValue; import org.opengis.parameter.ParameterValueGroup; import org.apache.sis.internal.metadata.AxisNames; @@ -56,7 +57,7 @@ import static org.apache.sis.internal.util.StandardDateFormat.MILLISECONDS_PER_D * Tests {@link GeodeticObjectParser}. * * @author Martin Desruisseaux (IRD, Geomatys) - * @version 1.1 + * @version 1.2 * @since 0.6 * @module */ @@ -1089,6 +1090,43 @@ public final strictfp class GeodeticObjectParserTest extends TestCase { } /** + * Tests the parsing of a {@code GEOGTRAN} coordinate operation. + * This is specific to ESRI. + * + * @throws ParseException if the parsing failed. + * + * @since 1.2 + */ + @Test + @DependsOnMethod("testGeographicWithImplicitAxes") + public void testGeogTran() throws ParseException { + final CoordinateOperation op = parse(CoordinateOperation.class, + "GEOGTRAN[“Palestine_1923_to_WGS_84_1”,\n" + + " GEOGCS[“GCS_Palestine_1923”,\n" + + " DATUM[“D_Palestine_1923”,\n" + + " SPHEROID[“Clarke_1880_Benoit”, 6378300.789, 293.46631553898]],\n" + + " PRIMEM[“Greenwich”, 0.0], UNIT[“Degree”, 0.0174532925199433]],\n" + + " GEOGCS[“GCS_WGS_1984”,\n" + + " DATUM[“D_WGS_1984”,\n" + + " SPHEROID[“WGS_1984”, 6378137.0, 298.257223563]],\n" + + " PRIMEM[“Greenwich”, 0.0], UNIT[“Degree”, 0.0174532925199433]],\n" + + " METHOD[“Position_Vector”],\n" + + " PARAMETER[“X_Axis_Translation”, -275.7224],\n" + + " PARAMETER[“Y_Axis_Translation”, 94.7824],\n" + + " PARAMETER[“Z_Axis_Translation”, 340.8944],\n" + + " PARAMETER[“X_Axis_Rotation”, -8.001],\n" + + " PARAMETER[“Y_Axis_Rotation”, -4.42],\n" + + " PARAMETER[“Z_Axis_Rotation”,-11.821],\n" + + " PARAMETER[“Scale_Difference”, 1.0],\n" + + " AUTHORITY[“EPSG”, 1074]]"); + + final GeographicCRS sourceCRS = (GeographicCRS) op.getSourceCRS(); + final GeographicCRS targetCRS = (GeographicCRS) op.getTargetCRS(); + assertNameAndIdentifierEqual("GCS_Palestine_1923", 0, sourceCRS); + assertNameAndIdentifierEqual("GCS_WGS_1984", 0, targetCRS); + } + + /** * Ensures that parsing a WKT with wrong units throws an exception. */ @Test