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
commit f92855ab0f941c9dc45f057dc1d486642b91d6d6 Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Wed Aug 10 16:08:52 2022 +0200 WKT of DerivedCRS should exclude semi-major and semi-minor parameters when they can be inferred from the geodetic datum. This is the same policy than the one currently applied on ProjectedCRS WKT. --- .../sis/referencing/crs/DefaultDerivedCRS.java | 16 +-- .../sis/referencing/crs/DefaultProjectedCRS.java | 85 +------------ .../sis/referencing/crs/ExplicitParameters.java | 133 +++++++++++++++++++++ 3 files changed, 135 insertions(+), 99 deletions(-) diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultDerivedCRS.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultDerivedCRS.java index d12faa07aa..561d191d85 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultDerivedCRS.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultDerivedCRS.java @@ -22,7 +22,6 @@ import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; -import org.opengis.parameter.GeneralParameterValue; import org.opengis.referencing.datum.Datum; import org.opengis.referencing.datum.GeodeticDatum; import org.opengis.referencing.datum.VerticalDatum; @@ -46,7 +45,6 @@ import org.opengis.referencing.operation.NoninvertibleTransformException; import org.opengis.geometry.MismatchedDimensionException; import org.apache.sis.referencing.AbstractIdentifiedObject; import org.apache.sis.referencing.operation.DefaultConversion; -import org.apache.sis.referencing.operation.DefaultOperationMethod; import org.apache.sis.referencing.cs.AxesConvention; import org.apache.sis.referencing.cs.CoordinateSystems; import org.apache.sis.internal.jaxb.referencing.SC_SingleCRS; @@ -56,7 +54,6 @@ import org.apache.sis.internal.referencing.ReferencingUtilities; import org.apache.sis.internal.referencing.WKTUtilities; import org.apache.sis.internal.referencing.WKTKeywords; import org.apache.sis.io.wkt.Convention; -import org.apache.sis.io.wkt.FormattableObject; import org.apache.sis.io.wkt.Formatter; import org.apache.sis.util.ComparisonMode; @@ -567,18 +564,7 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS<Conversion> implements return WKTKeywords.Fitted_CS; } else { formatter.newLine(); - formatter.append(new FormattableObject() { // Format inside a "DefiningConversion" element. - @Override protected String formatTo(final Formatter formatter) { - WKTUtilities.appendName(conversion, formatter, null); - formatter.newLine(); - formatter.append(DefaultOperationMethod.castOrCopy(conversion.getMethod())); - formatter.newLine(); - for (final GeneralParameterValue param : conversion.getParameterValues().values()) { - WKTUtilities.append(param, formatter); - } - return WKTKeywords.DerivingConversion; - } - }); + formatter.append(new ExplicitParameters(this, WKTKeywords.DerivingConversion)); // Format inside a "DefiningConversion" element. if (convention == Convention.INTERNAL || !isBaseCRS(formatter)) { final CoordinateSystem cs = getCoordinateSystem(); formatCS(formatter, cs, ReferencingUtilities.getUnit(cs), isWKT1); diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultProjectedCRS.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultProjectedCRS.java index 46207ca1d4..6cbcacfc85 100644 --- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultProjectedCRS.java +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/DefaultProjectedCRS.java @@ -19,38 +19,25 @@ package org.apache.sis.referencing.crs; import java.util.Map; import javax.measure.Unit; import javax.measure.quantity.Angle; -import javax.measure.quantity.Length; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; -import org.opengis.parameter.ParameterValue; -import org.opengis.parameter.GeneralParameterValue; -import org.opengis.parameter.GeneralParameterDescriptor; import org.opengis.referencing.crs.ProjectedCRS; import org.opengis.referencing.crs.GeographicCRS; import org.opengis.referencing.cs.CartesianCS; import org.opengis.referencing.cs.CoordinateSystem; // For javadoc -import org.opengis.referencing.datum.Ellipsoid; import org.opengis.referencing.datum.GeodeticDatum; import org.opengis.referencing.operation.Conversion; import org.opengis.referencing.operation.Projection; import org.opengis.geometry.MismatchedDimensionException; -import org.apache.sis.referencing.IdentifiedObjects; import org.apache.sis.referencing.cs.AxesConvention; -import org.apache.sis.referencing.operation.DefaultOperationMethod; import org.apache.sis.internal.referencing.ReferencingUtilities; import org.apache.sis.internal.referencing.AxisDirections; import org.apache.sis.internal.referencing.WKTKeywords; import org.apache.sis.internal.referencing.WKTUtilities; -import org.apache.sis.internal.util.Constants; -import org.apache.sis.internal.system.Loggers; import org.apache.sis.io.wkt.Convention; -import org.apache.sis.io.wkt.FormattableObject; import org.apache.sis.io.wkt.Formatter; import org.apache.sis.util.ComparisonMode; -import org.apache.sis.util.logging.Logging; - -import static java.util.logging.Logger.getLogger; import static org.apache.sis.internal.referencing.WKTUtilities.toFormattable; @@ -404,7 +391,7 @@ public class DefaultProjectedCRS extends AbstractDerivedCRS<Projection> implemen formatter.newLine(); formatter.append(toFormattable(baseCRS)); formatter.newLine(); - final Parameters p = new Parameters(this); + final ExplicitParameters p = new ExplicitParameters(this, WKTKeywords.Conversion); final boolean isBaseCRS; if (isWKT1) { p.append(formatter); // Format outside of any "Conversion" element. @@ -426,76 +413,6 @@ public class DefaultProjectedCRS extends AbstractDerivedCRS<Projection> implemen : formatter.shortOrLong(WKTKeywords.ProjCRS, WKTKeywords.ProjectedCRS); } - /** - * Temporary object for formatting the projection method and parameters inside a {@code Conversion} element. - */ - private static final class Parameters extends FormattableObject { - /** The conversion which specify the operation method and parameters. */ - private final Conversion conversion; - - /** Semi-major and semi-minor axis lengths. */ - private final Ellipsoid ellipsoid; - - /** Creates a new temporary {@code Conversion} elements for the parameters of the given CRS. */ - Parameters(final DefaultProjectedCRS crs) { - conversion = crs.getConversionFromBase(); - ellipsoid = crs.getDatum().getEllipsoid(); - } - - /** Formats this {@code Conversion} element. */ - @Override protected String formatTo(final Formatter formatter) { - WKTUtilities.appendName(conversion, formatter, null); - formatter.newLine(); - append(formatter); - return WKTKeywords.Conversion; - } - - /** Formats this {@code Conversion} element without the conversion name. */ - void append(final Formatter formatter) { - final Unit<Length> axisUnit = ellipsoid.getAxisUnit(); - formatter.append(DefaultOperationMethod.castOrCopy(conversion.getMethod())); - formatter.newLine(); - for (final GeneralParameterValue param : conversion.getParameterValues().values()) { - final GeneralParameterDescriptor desc = param.getDescriptor(); - String name; - if (IdentifiedObjects.isHeuristicMatchForName(desc, name = Constants.SEMI_MAJOR) || - IdentifiedObjects.isHeuristicMatchForName(desc, name = Constants.SEMI_MINOR)) - { - /* - * Do not format semi-major and semi-minor axis length in most cases, since those - * information are provided in the ellipsoid. An exception to this rule occurs if - * the lengths are different from the ones declared in the datum. - */ - if (param instanceof ParameterValue<?>) { - final double value; - try { - value = ((ParameterValue<?>) param).doubleValue(axisUnit); - } catch (IllegalStateException e) { - /* - * May happen if the 'conversionFromBase' parameter group does not provide values - * for "semi_major" or "semi_minor" axis length. This should not happen with SIS - * implementation, but may happen with user-defined map projection implementations. - * Since the intent of this check was to skip those parameters anyway, it is okay - * for the purpose of WKT formatting if there are no parameters for axis lengths. - */ - Logging.recoverableException(getLogger(Loggers.WKT), DefaultProjectedCRS.class, "formatTo", e); - continue; - } - if (Double.isNaN(value)) { - continue; - } - final double expected = (name == Constants.SEMI_MINOR) // using '==' is okay here. - ? ellipsoid.getSemiMinorAxis() : ellipsoid.getSemiMajorAxis(); - if (value == expected) { - continue; - } - } - } - WKTUtilities.append(param, formatter); - } - } - } - diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/ExplicitParameters.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/ExplicitParameters.java new file mode 100644 index 0000000000..61e0d41dbe --- /dev/null +++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/crs/ExplicitParameters.java @@ -0,0 +1,133 @@ +/* + * 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.crs; + +import org.opengis.parameter.ParameterValue; +import org.opengis.parameter.GeneralParameterValue; +import org.opengis.parameter.GeneralParameterDescriptor; +import org.opengis.referencing.datum.Datum; +import org.opengis.referencing.datum.GeodeticDatum; +import org.opengis.referencing.datum.Ellipsoid; +import org.opengis.referencing.operation.Conversion; +import org.apache.sis.referencing.IdentifiedObjects; +import org.apache.sis.referencing.operation.DefaultOperationMethod; +import org.apache.sis.internal.referencing.WKTKeywords; +import org.apache.sis.internal.referencing.WKTUtilities; +import org.apache.sis.internal.util.Constants; +import org.apache.sis.internal.system.Loggers; +import org.apache.sis.io.wkt.FormattableObject; +import org.apache.sis.io.wkt.Formatter; +import org.apache.sis.util.logging.Logging; + +import static java.util.logging.Logger.getLogger; + + +/** + * Temporary object for formatting the projection method and parameters inside a {@code Conversion} element. + * This object formats only the explicit parameters. Implicit parameters derived from source ellipsoid are omitted. + * + * @author Martin Desruisseaux (IRD, Geomatys) + * @version 1.3 + * @since 0.6 + * @module + */ +final class ExplicitParameters extends FormattableObject { + /** + * The conversion which specify the operation method and parameters. + */ + private final Conversion conversion; + + /** + * Semi-major and semi-minor axis lengths, or {@code null} if the datum is not geodetic. + */ + private final Ellipsoid ellipsoid; + + /** + * The keyword to be returned by {@link #formatTo(Formatter)}. + * Should be {@link WKTKeywords#Conversion} or {@link WKTKeywords#DerivingConversion}. + */ + private final String keyword; + + /** + * Creates a new temporary {@code Conversion} elements for the parameters of the given CRS. + */ + ExplicitParameters(final AbstractDerivedCRS<?> crs, final String keyword) { + conversion = crs.getConversionFromBase(); + final Datum datum = crs.getDatum(); + ellipsoid = (datum instanceof GeodeticDatum) ? ((GeodeticDatum) datum).getEllipsoid() : null; + this.keyword = keyword; + } + + /** + * Formats this {@code Conversion} element. + */ + @Override + protected String formatTo(final Formatter formatter) { + WKTUtilities.appendName(conversion, formatter, null); + formatter.newLine(); + append(formatter); + return keyword; + } + + /** + * Formats this {@code Conversion} element without the conversion name. + */ + void append(final Formatter formatter) { + formatter.append(DefaultOperationMethod.castOrCopy(conversion.getMethod())); + formatter.newLine(); + for (final GeneralParameterValue param : conversion.getParameterValues().values()) { + final GeneralParameterDescriptor desc = param.getDescriptor(); + if (ellipsoid != null) { + String name; + if (IdentifiedObjects.isHeuristicMatchForName(desc, name = Constants.SEMI_MAJOR) || + IdentifiedObjects.isHeuristicMatchForName(desc, name = Constants.SEMI_MINOR)) + { + /* + * Do not format semi-major and semi-minor axis length in most cases, since those + * information are provided in the ellipsoid. An exception to this rule occurs if + * the lengths are different from the ones declared in the datum. + */ + if (param instanceof ParameterValue<?>) { + final double value; + try { + value = ((ParameterValue<?>) param).doubleValue(ellipsoid.getAxisUnit()); + } catch (IllegalStateException e) { + /* + * May happen if the 'conversionFromBase' parameter group does not provide values + * for "semi_major" or "semi_minor" axis length. This should not happen with SIS + * implementation, but may happen with user-defined map projection implementations. + * Since the intent of this check was to skip those parameters anyway, it is okay + * for the purpose of WKT formatting if there are no parameters for axis lengths. + */ + Logging.recoverableException(getLogger(Loggers.WKT), DefaultProjectedCRS.class, "formatTo", e); + continue; + } + if (Double.isNaN(value)) { + continue; + } + final double expected = (name == Constants.SEMI_MINOR) // using '==' is okay here. + ? ellipsoid.getSemiMinorAxis() : ellipsoid.getSemiMajorAxis(); + if (value == expected) { + continue; + } + } + } + } + WKTUtilities.append(param, formatter); + } + } +}