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 94cdd0cb3b Complete the support of the new WKT keywords for
`GeographicCRS` and other CRS types. Change the default unit of measurement of
`PARAMETER` as clarified in ISO 19162:2019. Replace usage of `Date` by
`java.time` in WKT parsing of temporal CRS.
94cdd0cb3b is described below
commit 94cdd0cb3b68225c53773abc86b2bcfa77c4ff19
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Mon Sep 8 11:59:11 2025 +0200
Complete the support of the new WKT keywords for `GeographicCRS` and other
CRS types.
Change the default unit of measurement of `PARAMETER` as clarified in ISO
19162:2019.
Replace usage of `Date` by `java.time` in WKT parsing of temporal CRS.
---
.../org/apache/sis/console/CRSCommandTest.java | 2 +-
.../org/apache/sis/temporal/LenientDateFormat.java | 4 +-
.../sis/coordinate/DefaultCoordinateMetadata.java | 2 +-
.../main/org/apache/sis/io/wkt/Convention.java | 57 +++----
.../main/org/apache/sis/io/wkt/Element.java | 16 +-
.../org/apache/sis/io/wkt/FormattableObject.java | 4 +-
.../main/org/apache/sis/io/wkt/Formatter.java | 48 +++---
.../apache/sis/io/wkt/GeodeticObjectParser.java | 59 +++++---
.../main/org/apache/sis/io/wkt/WKTFormat.java | 6 +-
.../sis/parameter/DefaultParameterValue.java | 165 ++++++++++-----------
.../sis/referencing/AbstractIdentifiedObject.java | 4 +-
.../main/org/apache/sis/referencing/CRS.java | 2 +-
.../sis/referencing/crs/DefaultDerivedCRS.java | 4 +
.../sis/referencing/crs/DefaultGeodeticCRS.java | 13 +-
.../sis/referencing/crs/DefaultGeographicCRS.java | 4 +-
.../sis/referencing/crs/DefaultProjectedCRS.java | 2 +-
.../org/apache/sis/referencing/crs/DynamicCRS.java | 2 +-
.../referencing/datum/DefaultPrimeMeridian.java | 2 +-
.../referencing/factory/GeodeticObjectFactory.java | 2 +-
.../org/apache/sis/referencing/internal/Epoch.java | 18 +--
.../apache/sis/referencing/privy/WKTKeywords.java | 11 +-
.../apache/sis/referencing/privy/WKTUtilities.java | 4 +-
.../test/org/apache/sis/io/wkt/ElementTest.java | 4 +-
.../sis/io/wkt/GeodeticObjectParserTest.java | 8 +-
.../sis/parameter/DefaultParameterValueTest.java | 3 +-
.../referencing/crs/DefaultCompoundCRSTest.java | 2 +-
.../sis/referencing/crs/DefaultDerivedCRSTest.java | 2 +-
.../referencing/crs/DefaultGeographicCRSTest.java | 6 +-
.../referencing/crs/DefaultProjectedCRSTest.java | 14 +-
.../datum/DefaultGeodeticDatumTest.java | 1 +
.../apache/sis/referencing/internal/EpochTest.java | 11 +-
.../operation/CoordinateOperationFinderTest.java | 6 +-
.../operation/CoordinateOperationRegistryTest.java | 10 +-
.../DefaultConcatenatedOperationTest.java | 4 +-
.../DefaultCoordinateOperationFactoryTest.java | 6 +-
.../org/apache/sis/gui/referencing/WKTPane.java | 2 +
36 files changed, 272 insertions(+), 238 deletions(-)
diff --git
a/endorsed/src/org.apache.sis.console/test/org/apache/sis/console/CRSCommandTest.java
b/endorsed/src/org.apache.sis.console/test/org/apache/sis/console/CRSCommandTest.java
index ac42465ab6..9fd80d809e 100644
---
a/endorsed/src/org.apache.sis.console/test/org/apache/sis/console/CRSCommandTest.java
+++
b/endorsed/src/org.apache.sis.console/test/org/apache/sis/console/CRSCommandTest.java
@@ -43,7 +43,7 @@ public final class CRSCommandTest extends TestCase {
public CRSCommandTest() {
final String name = "\"WGS\\E\\s?(?:19)?\\Q84\"";
// Accept "WGS 84" or "WGS 1984".
WGS84 = "(?m)\\Q" +
// Multilines.
- "GeodeticCRS[" + name + ",\n" +
+ "GeographicCRS[" + name + ",\n" +
" Ensemble[\"World Geodetic System 1984\\E\\s?\\w*\\Q\",\n" +
// Ignore any suffix in the name.
"\\E(?: Member\\[\".+\"\\],\n)+\\Q" +
// At least one MEMBER[…].
" Ellipsoid[" + name + ", 6378137.0, 298.257223563],\n" +
diff --git
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/LenientDateFormat.java
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/LenientDateFormat.java
index 4649c7c3be..c564507a2b 100644
---
a/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/LenientDateFormat.java
+++
b/endorsed/src/org.apache.sis.metadata/main/org/apache/sis/temporal/LenientDateFormat.java
@@ -367,7 +367,7 @@ replace: if (Character.isWhitespace(c)) {
@Override
public Date parse(final String text, final ParsePosition position) {
try {
- return Date.from(TemporalDate.toInstant(format.parse(text,
position), getZone()));
+ return
TemporalDate.toDate(TemporalDate.toInstant(format.parse(text, position),
getZone()));
} catch (DateTimeException | ArithmeticException e) {
position.setErrorIndex(getErrorIndex(e, position));
return null;
@@ -384,7 +384,7 @@ replace: if (Character.isWhitespace(c)) {
@Override
public Date parse(final String text) throws ParseException {
try {
- return Date.from(TemporalDate.toInstant(format.parse(toISO(text,
0, text.length())), getZone()));
+ return
TemporalDate.toDate(TemporalDate.toInstant(format.parse(toISO(text, 0,
text.length())), getZone()));
} catch (RuntimeException e) {
throw (ParseException) new ParseException(e.getLocalizedMessage(),
getErrorIndex(e, null)).initCause(e);
}
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/coordinate/DefaultCoordinateMetadata.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/coordinate/DefaultCoordinateMetadata.java
index 74911cd66b..45181647ca 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/coordinate/DefaultCoordinateMetadata.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/coordinate/DefaultCoordinateMetadata.java
@@ -199,7 +199,7 @@ public class DefaultCoordinateMetadata extends
FormattableObject
protected String formatTo(final Formatter formatter) {
formatter.append(WKTUtilities.toFormattable(crs));
if (epoch != null) {
- formatter.append(new Epoch(epoch, false));
+ formatter.append(new Epoch(epoch, WKTKeywords.Epoch));
}
return WKTKeywords.CoordinateMetadata;
}
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Convention.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Convention.java
index 7fc4c24e13..714363fe7f 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Convention.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Convention.java
@@ -26,9 +26,9 @@ import org.apache.sis.metadata.iso.citation.Citations;
* This enumeration specifies whether to use the <i>Well Known Text</i> format
defined by <abbr>ISO</abbr> 19162
* (also known as “WKT 2”), or whether to use the format previously defined in
OGC 01-009 (referenced as “WKT 1”).
*
- * <h2>WKT 1 variants</h2>
- * The WKT 2 format should be parsed and formatted consistently by all
software products.
- * But the WKT 1 format has been interpreted differently by various
implementers.
+ * <h2><abbr title="Well Known Text">WKT</abbr> 1 variants</h2>
+ * The <abbr>WKT</abbr> 2 format should be parsed and formatted consistently
by all software products.
+ * But the <abbr>WKT</abbr> 1 format has been interpreted differently by
various implementers.
* Apache SIS can adapt itself to different WKT variants, sometimes
automatically. But some aspects cannot be guessed.
* One noticeable source of confusion is the unit of measurement of {@code
PRIMEM[…]} and {@code PARAMETER[…]} elements:
*
@@ -44,7 +44,7 @@ import org.apache.sis.metadata.iso.citation.Citations;
* Despite the first interpretation being specified by both OGC 01-009 and ISO
19162 standards, the second
* interpretation appears to be in wide use for WKT 1. Apache SIS uses the
standard interpretation by default,
* but the {@link #WKT1_COMMON_UNITS} enumeration allows parsing and
formatting using the older interpretation.
- * The {@link #WKT1_IGNORE_AXES} enumeration mimics the most minimalist WKT 1
parsers,
+ * The {@link #WKT1_IGNORE_AXES} enumeration mimics the most minimalist
<abbr>WKT</abbr> 1 parsers,
* but should be avoided when not imposed by compatibility reasons.
*
* @author Martin Desruisseaux (Geomatys)
@@ -67,7 +67,7 @@ public enum Convention {
* <p>This is the default convention used by {@link
FormattableObject#toWKT()}
* and for new {@link WKTFormat} instances.</p>
*/
- WKT2(true, false),
+ WKT2(true),
/**
* The ISO 19162 format with omission of some optional elements. This
convention is identical
@@ -100,7 +100,7 @@ public enum Convention {
*
* <p>This is the default convention used by {@link
FormattableObject#toString()}.</p>
*/
- WKT2_SIMPLIFIED(false, false),
+ WKT2_SIMPLIFIED(false),
/**
* The ISO 19162:2019 format, also known as “WKT 2”.
@@ -112,7 +112,7 @@ public enum Convention {
*
* @since 1.5
*/
- WKT2_2019(true, false),
+ WKT2_2019(true),
/**
* The ISO 19162:2015 format, also known as “WKT 2”.
@@ -124,7 +124,7 @@ public enum Convention {
*
* @since 1.5
*/
- WKT2_2015(true, false),
+ WKT2_2015(true),
/**
* The OGC 01-009 format, also known as “WKT 1”.
@@ -162,7 +162,7 @@ public enum Convention {
* </table>
* </div></div>
*/
- WKT1(true, false),
+ WKT1(true),
/**
* The <cite>Simple Feature</cite> format, also known as “WKT 1”.
@@ -179,7 +179,7 @@ public enum Convention {
* (e.g. <q>meter</q> instead of <q>metre</q>).</li>
* </ul>
*/
- WKT1_COMMON_UNITS(true, true),
+ WKT1_COMMON_UNITS(true),
/**
* The <cite>Simple Feature</cite> format without parsing of axis elements.
@@ -196,7 +196,7 @@ public enum Convention {
*
* @since 0.6
*/
- WKT1_IGNORE_AXES(true, true),
+ WKT1_IGNORE_AXES(true),
/**
* A special convention for formatting objects as stored internally by
Apache SIS.
@@ -222,7 +222,7 @@ public enum Convention {
* This convention is used only for debugging purpose.
*/
@Debug
- INTERNAL(false, false);
+ INTERNAL(false);
/**
* The default conventions.
@@ -234,25 +234,11 @@ public enum Convention {
*/
final boolean toUpperCase;
- /**
- * {@code true} for a frequently-used convention about units instead of
the standard one.
- * <ul>
- * <li>If {@code true}, forces {@code PRIMEM} and {@code PARAMETER}
angular units to degrees
- * instead of inferring the unit from the context. The standard
value is {@code false},
- * which means that the angular units are inferred from the context
as required by the
- * WKT 1 specification.</li>
- * <li>If {@code true}, uses US unit names instead of the international
names.
- * For example, Americans said {@code "meter"} instead of {@code
"metre"}.</li>
- * </ul>
- */
- final boolean usesCommonUnits;
-
/**
* Creates a new enumeration value.
*/
- private Convention(final boolean toUpperCase, final boolean
usesCommonUnits) {
- this.toUpperCase = toUpperCase;
- this.usesCommonUnits = usesCommonUnits;
+ private Convention(final boolean toUpperCase) {
+ this.toUpperCase = toUpperCase;
}
/**
@@ -290,6 +276,21 @@ public enum Convention {
return this == WKT2_SIMPLIFIED || ordinal() >= WKT1.ordinal();
}
+ /**
+ * {@code true} for a frequently-used convention about units instead of
the standard one.
+ * <ul>
+ * <li>If {@code true}, forces {@code PRIMEM} and {@code PARAMETER}
angular units to degrees
+ * instead of inferring the unit from the context. The standard
value is {@code false},
+ * which means that the angular units are inferred from the context
as required by the
+ * WKT 1 specification.</li>
+ * <li>If {@code true}, uses <abbr>US</abbr> unit names instead of the
international names.
+ * For example, Americans said {@code "meter"} instead of {@code
"metre"}.</li>
+ * </ul>
+ */
+ final boolean usesCommonUnits() {
+ return this == WKT1_COMMON_UNITS || this == WKT1_IGNORE_AXES;
+ }
+
/**
* Returns the default authority to look for when fetching identified
object names and identifiers.
* The difference between various authorities are most easily seen in
projection and parameter names.
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Element.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Element.java
index e34dddbdd8..b627aaa0d0 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Element.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Element.java
@@ -16,14 +16,13 @@
*/
package org.apache.sis.io.wkt;
-import java.util.Date;
import java.util.Map;
import java.util.Set;
import java.util.List;
import java.util.LinkedList;
import java.util.Iterator;
import java.util.Locale;
-import java.time.Instant;
+import java.time.temporal.Temporal;
import java.text.ParsePosition;
import java.text.ParseException;
import org.opengis.referencing.cs.CoordinateSystem;
@@ -34,6 +33,7 @@ import org.apache.sis.util.CharSequences;
import org.apache.sis.util.resources.Errors;
import org.apache.sis.referencing.privy.WKTKeywords;
import org.apache.sis.referencing.internal.Resources;
+import org.apache.sis.temporal.TemporalDate;
import org.apache.sis.util.privy.CollectionsExt;
import static org.apache.sis.util.CharSequences.skipLeadingWhitespaces;
@@ -342,7 +342,7 @@ final class Element {
valueType =
ArraysExt.containsIgnoreCase(TIME_KEYWORDS, keyword) ? TEMPORAL : NUMERIC;
}
switch (valueType) {
- case TEMPORAL: value = parser.parseDate (text,
position); break;
+ case TEMPORAL: value =
TemporalDate.toTemporal(parser.parseDate(text, position)); break;
case NUMERIC: value = parser.parseNumber(text,
position); break;
default: throw new AssertionError(valueType);
// Should never happen.
}
@@ -549,19 +549,19 @@ final class Element {
}
/**
- * Removes the next {@link Date} from the children and returns it.
+ * Removes the next {@link Temporal} from the children and returns it.
*
* @param key the parameter name. Used for formatting an error message
if no date is found.
- * @return the next {@link Date} among the children.
+ * @return the next {@link Temporal} among the children.
* @throws ParseException if no more date is available.
*/
- public Instant pullDate(final String key) throws ParseException {
+ public Temporal pullTime(final String key) throws ParseException {
final Iterator<Object> iterator = children.iterator();
while (iterator.hasNext()) {
final Object object = iterator.next();
- if (object instanceof Date) {
+ if (object instanceof Temporal) {
iterator.remove();
- return ((Date) object).toInstant();
+ return (Temporal) object;
}
}
throw missingComponent(key);
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/FormattableObject.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/FormattableObject.java
index 89f6451925..d87c8bc983 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/FormattableObject.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/FormattableObject.java
@@ -220,11 +220,11 @@ public abstract class FormattableObject implements
Printable {
* This method is automatically invoked by {@link WKTFormat} when a
formattable element is found.
*
* <p>Keywords, opening and closing brackets shall not be formatted here.
- * For example if this formattable element is for a {@code GeodeticCRS[…]}
element,
+ * For example if this formattable element is for a {@code
GeographicCRS[…]} element,
* then this method shall write the content starting at the insertion
point shown below:</p>
*
* <pre class="text">
- * GeodeticCRS[ ]
+ * GeographicCRS[ ]
* ↑
* (insertion point)</pre>
*
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
index 8aa6c12db6..608d66edd6 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/Formatter.java
@@ -85,6 +85,7 @@ import org.apache.sis.referencing.DefaultObjectDomain;
import org.apache.sis.referencing.ImmutableIdentifier;
import org.apache.sis.referencing.privy.WKTKeywords;
import org.apache.sis.referencing.privy.WKTUtilities;
+import org.apache.sis.referencing.internal.Epoch;
import org.apache.sis.referencing.internal.Resources;
import org.apache.sis.geometry.AbstractDirectPosition;
import org.apache.sis.geometry.AbstractEnvelope;
@@ -375,7 +376,7 @@ public class Formatter implements Localized {
this.unitFormat = new UnitFormat(symbols.getLocale());
this.buffer = new StringBuffer();
unitFormat.setStyle(UnitFormat.Style.NAME);
- if (convention.usesCommonUnits) {
+ if (convention.usesCommonUnits()) {
unitFormat.setLocale(Locale.US);
}
}
@@ -438,7 +439,7 @@ public class Formatter implements Localized {
this.indentation = indentation;
this.listSizeLimit = listSizeLimit;
this.transliterator = (convention == Convention.INTERNAL) ?
Transliterator.IDENTITY : Transliterator.DEFAULT;
- unitFormat.setLocale(convention.usesCommonUnits ? Locale.US :
Locale.ROOT);
+ unitFormat.setLocale(convention.usesCommonUnits() ? Locale.US :
Locale.ROOT);
}
/**
@@ -508,6 +509,8 @@ public class Formatter implements Localized {
/**
* Appends in the {@linkplain #buffer} the ANSI escape sequence for the
given kind of element.
* This method does nothing unless syntax coloring has been explicitly
enabled.
+ *
+ * @param type the key of the colors to apply if syntax coloring is
enabled, or {@code null} if none.
*/
private void setColor(final ElementKind type) {
if (colors != null) {
@@ -898,14 +901,13 @@ public class Formatter implements Localized {
* {@link ReferenceSystem} and {@link CoordinateOperation} objects.
*/
private void appendForSubtypes(final IdentifiedObject object) {
- InternationalString anchor = null, scope = null;
- Extent area = null;
if (object instanceof Datum) {
- anchor = ((Datum) object).getAnchorDefinition().orElse(null);
+ final var datum = (Datum) object;
+ appendOnNewLine(WKTKeywords.Anchor,
datum.getAnchorDefinition().orElse(null), null);
+ datum.getAnchorEpoch().ifPresent((epoch) -> append(new
Epoch(epoch, WKTKeywords.AnchorEpoch)));
} else if (!(object instanceof ReferenceSystem || object instanceof
CoordinateOperation)) {
return;
}
- appendOnNewLine(WKTKeywords.Anchor, anchor, null);
final boolean usage = convention.supports(Convention.WKT2_2019);
for (final ObjectDomain domain : object.getDomains()) {
if (usage) {
@@ -914,8 +916,8 @@ public class Formatter implements Localized {
appendFormattable(domain, DefaultObjectDomain::castOrCopy);
} else {
// ISO 19162:2015
- scope = domain.getScope();
- area = domain.getDomainOfValidity();
+ InternationalString scope = domain.getScope();
+ Extent area = domain.getDomainOfValidity();
if (scope != null || area != null) {
append(scope, area);
break;
@@ -1091,10 +1093,9 @@ public class Formatter implements Localized {
* @param keyword the {@linkplain KeywordCase#CAMEL_CASE camel-case}
keyword.
* Example: {@code "Scope"}, {@code "Area"} or {@code
"Remarks"}.
* @param text the text, or {@code null} if none.
- * @param type the key of the colors to apply if syntax coloring is
enabled.
+ * @param type the key of the colors to apply if syntax coloring is
enabled, or {@code null} if none.
*/
private void appendOnNewLine(final String keyword, final
InternationalString text, final ElementKind type) {
- ArgumentChecks.ensureNonNull("keyword", keyword);
if (text != null) {
String localized = text.toString(locale);
if (localized != null && !(localized =
localized.strip()).isEmpty()) {
@@ -1134,6 +1135,9 @@ public class Formatter implements Localized {
* Appends the given string as a quoted text. If the given string contains
the closing quote character,
* that character will be doubled (WKT 2) or deleted (WKT 1). We check for
the closing quote only because
* it is the character that the parser will look for determining the text
end.
+ *
+ * @param text the text to append.
+ * @param type the key of the colors to apply if syntax coloring is
enabled, or {@code null} if none.
*/
private void quote(String text, final ElementKind type) {
setColor(type);
@@ -1231,7 +1235,7 @@ public class Formatter implements Localized {
if (date != null) {
appendSeparator();
if (date instanceof Instant) {
- dateFormat.format(Date.from((Instant) date), buffer, dummy);
+ dateFormat.format(TemporalDate.toDate((Instant) date), buffer,
dummy);
} else {
// Preserve the data structure (e.g. whether there is hours or
not, timezone or not).
buffer.append(date);
@@ -1746,7 +1750,7 @@ public class Formatter implements Localized {
}
/**
- * Returns {@code true} if the element at the given depth specified a
contextual unit.
+ * Returns {@code true} if the element at the given depth has specified a
contextual unit.
* This method returns {@code true} if the formattable object given by
{@code getEnclosingElement(depth)}
* has invoked {@link #addContextualUnit(Unit)} with a non-null unit at
least once.
*
@@ -1770,8 +1774,9 @@ public class Formatter implements Localized {
* <p>If the given unit is null, then this method does nothing and returns
{@code null}.</p>
*
* <h4>Special case</h4>
- * If the WKT conventions are {@code WKT1_COMMON_UNITS}, then this method
ignores the given unit
- * and returns {@code null}. See {@link Convention#WKT1_COMMON_UNITS}
javadoc for more information.
+ * If the <abbr>WKT</abbr> conventions are {@code WKT1_COMMON_UNITS} or
{@code WKT1_IGNORE_AXES},
+ * then this method ignores the given unit and returns {@code null}.
+ * See {@link Convention#WKT1_COMMON_UNITS} javadoc for more information.
*
* @param <Q> the unit quantity.
* @param unit the contextual unit to add, or {@code null} if none.
@@ -1779,7 +1784,7 @@ public class Formatter implements Localized {
*/
@SuppressWarnings("unchecked")
public <Q extends Quantity<Q>> Unit<Q> addContextualUnit(final Unit<Q>
unit) {
- if (unit == null || convention.usesCommonUnits) {
+ if (unit == null || convention.usesCommonUnits()) {
return null;
}
hasContextualUnit |= 1;
@@ -1807,11 +1812,11 @@ public class Formatter implements Localized {
if (unit != null && units.remove(unit.getSystemUnit()) != unit) {
/*
* The unit that we removed was not the expected one. Probably
the user has invoked
- * addContextualUnit(…) again without a matching call to
`restoreContextualUnit(…)`.
- * However, this check does not work in
`Convention.WKT1_COMMON_UNITS` mode, since the
- * map is always empty in that mode.
+ * `addContextualUnit(…)` again without a matching call to
`restoreContextualUnit(…)`.
+ * However, this check does not work in
`Convention.WKT1_COMMON_UNITS` mode,
+ * because the map is always empty in that mode.
*/
- if (!convention.usesCommonUnits) {
+ if (!convention.usesCommonUnits()) {
throw new IllegalStateException();
}
}
@@ -1819,10 +1824,7 @@ public class Formatter implements Localized {
} else if (units.put(previous.getSystemUnit(), previous) != unit) {
/*
* The unit that we replaced was not the expected one. Probably
the user has invoked
- * addContextualUnit(…) again without a matching call to
`restoreContextualUnit(…)`.
- * Note that this case should never happen in
`Convention.WKT1_COMMON_UNITS` mode,
- * since `previous` should never be non-null in that mode (if the
user followed
- * the documented pattern).
+ * `addContextualUnit(…)` again without a matching call to
`restoreContextualUnit(…)`.
*/
throw new IllegalStateException();
}
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
index 96e320971d..be3ca10f52 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/GeodeticObjectParser.java
@@ -31,7 +31,7 @@ import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.text.ParseException;
-import java.time.Instant;
+import java.time.LocalDate;
import java.time.temporal.Temporal;
import static java.util.Collections.singletonMap;
import javax.measure.Unit;
@@ -220,7 +220,7 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
{
super(sourceFile, fragments, symbols, numberFormat, dateFormat,
unitFormat, factories, errorLocale);
this.transliterator = transliterator;
- usesCommonUnits = convention.usesCommonUnits;
+ usesCommonUnits = convention.usesCommonUnits();
ignoreAxes = convention == Convention.WKT1_IGNORE_AXES;
}
@@ -515,12 +515,11 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
* String, IdentifiedObject)} method. If an anchor has been found, its
value is stored in the returned map.
*/
private Map<String,Object> parseAnchorAndClose(final Element element,
final String name) throws ParseException {
- final Element anchor = element.pullElement(OPTIONAL,
WKTKeywords.Anchor);
+ String anchor = pullElementAsString(element, WKTKeywords.Anchor);
+ Temporal epoch = Epoch.fromYear(pullElementAsDouble(element,
WKTKeywords.AnchorEpoch, OPTIONAL), 0);
final Map<String,Object> properties = parseMetadataAndClose(element,
name, null);
- if (anchor != null) {
- properties.put(Datum.ANCHOR_DEFINITION_KEY,
anchor.pullString("anchorDefinition"));
- anchor.close(ignoredElements);
- }
+ if (anchor != null) properties.put(Datum.ANCHOR_DEFINITION_KEY,
anchor);
+ if (epoch != null) properties.put(Datum.ANCHOR_EPOCH_KEY, epoch);
return properties;
}
@@ -593,8 +592,8 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
element.close(ignoredElements);
warning(parent, element,
Errors.formatInternational(Errors.Keys.UnsupportedType_1,
"TimeExtent[String,String]"), null);
} else {
- final Instant startTime = element.pullDate("startTime");
- final Instant endTime = element.pullDate("endTime");
+ final Temporal startTime = element.pullTime("startTime");
+ final Temporal endTime = element.pullTime("endTime");
element.close(ignoredElements);
final var t = new DefaultTemporalExtent(startTime, endTime);
if (extent == null) extent = new DefaultExtent();
@@ -1267,7 +1266,7 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
final Map<String,?> properties = parseMetadataAndClose(element, name,
null);
final DatumFactory datumFactory = factories.getDatumFactory();
try {
- if (inverseFlattening == 0) { // OGC
convention for a sphere.
+ if (inverseFlattening == 0) { // OGC and ISO 19162
convention for a sphere.
return datumFactory.createEllipsoid(properties, semiMajorAxis,
semiMajorAxis, unit);
} else {
return datumFactory.createFlattenedSphere(properties,
semiMajorAxis, inverseFlattening, unit);
@@ -1359,8 +1358,18 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
* @throws ParseException if the {@code "Method"} element cannot be parsed.
*/
private Conversion parseDerivingConversion(final int mode, Element parent,
final String wrapper,
- final Unit<?> defaultUnit, final Unit<Angle> defaultAngularUnit)
throws ParseException
+ Unit<?> defaultUnit, Unit<Angle> defaultAngularUnit) throws
ParseException
{
+ /*
+ * ISO 19162:2015 was not very specific about the default units of
measurement for parameters.
+ * ISO 19162:2019 clarified the policy by saying that default units
should be metres or degrees.
+ * This is different than our understanding of OGC 01-009, which seems
to inherit the units from
+ * the context.
+ */
+ if (wrapper != null) {
+ defaultUnit = Units.METRE;
+ defaultAngularUnit = Units.DEGREE;
+ }
final String name;
if (wrapper == null) {
name = null; // Will actually be ignored. WKT 1 does not provide
name for Conversion objects.
@@ -1518,7 +1527,10 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
private GeodeticDatum parseDatum(final int mode, final Element parent,
final PrimeMeridian meridian, final Temporal epoch)
throws ParseException
{
- final Element element = parent.pullElement(mode, WKTKeywords.Datum,
WKTKeywords.GeodeticDatum);
+ final Element element = parent.pullElement(mode,
+ WKTKeywords.GeodeticDatum,
+ WKTKeywords.Datum,
+ WKTKeywords.TRF);
if (element == null) {
return null;
}
@@ -1562,7 +1574,8 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
final Element element = parent.pullElement(mode,
WKTKeywords.VerticalDatum,
WKTKeywords.VDatum,
- WKTKeywords.Vert_Datum);
+ WKTKeywords.Vert_Datum,
+ WKTKeywords.VRF);
if (element == null) {
return null;
}
@@ -1593,6 +1606,8 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
* TimeDatum["<name>", TimeOrigin[<time origin>] {,<authority>}]
* }
*
+ * @todo {@code CALANDAR[…]} element is not yet supported.
+ *
* @param mode {@link #FIRST}, {@link #OPTIONAL} or {@link #MANDATORY}.
* @param parent the parent element.
* @return the {@code "TimeDatum"} element as a {@link TemporalDatum}
object.
@@ -1603,10 +1618,16 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
if (element == null) {
return null;
}
- final String name = element.pullString ("name");
- final Element origin = element.pullElement(MANDATORY,
WKTKeywords.TimeOrigin);
- final Instant epoch = origin .pullDate("origin");
- origin.close(ignoredElements);
+ final String name = element.pullString ("name");
+ final Element origin = element.pullElement(OPTIONAL,
WKTKeywords.TimeOrigin);
+ final Temporal epoch;
+ if (origin != null) {
+ epoch = origin .pullTime("origin");
+ origin.close(ignoredElements);
+ } else {
+ // Default to the date of signing of the Convention du Mètre (from
ISO 19162:2019 specification)
+ epoch = LocalDate.of(1875, 5, 20);
+ }
final DatumFactory datumFactory = factories.getDatumFactory();
try {
return
datumFactory.createTemporalDatum(parseAnchorAndClose(element, name), epoch);
@@ -2068,8 +2089,8 @@ class GeodeticObjectParser extends MathTransformParser
implements Comparator<Coo
* But sometimes the axis (which was not available when we
created the datum) provides
* more information. Verify if we can have a better type now,
and if so rebuild the datum.
*
- * TODO: remove this hack. It is mostly for old standard. The
check for dynamic datum
- * is a dirty trick for checking if we have a newer standard.
+ * Note: we exclude the reconstruction of dynamic datum for
simplicity in the use of the factory.
+ * This block is a dirty trick anyway (a workaround for a
metadata excluded from the WKT standard).
*/
if (method == null && datum != null && !(datum instanceof
DynamicReferenceFrame)) {
var type =
VerticalDatumTypes.fromDatum(datum.getName().getCode(), datum.getAlias(),
cs.getAxis(0));
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/WKTFormat.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/WKTFormat.java
index 72c02f399d..e3fa29c0a6 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/WKTFormat.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/io/wkt/WKTFormat.java
@@ -89,14 +89,14 @@ import org.opengis.metadata.Identifier;
*
* <h3>Example</h3>
* In the example below, the {@code $WGS84} substring which appear in the
argument given to the
- * {@code parseObject(…)} method will be expanded into the full {@code
GeodeticCRS[“WGS84”, …]}
+ * {@code parseObject(…)} method will be expanded into the full {@code
GeographicCRS[“WGS84”, …]}
* string before the parsing proceed.
*
* <blockquote><code>
* {@linkplain #addFragment addFragment}("deg", "AngleUnit[“degree”,
0.0174532925199433]");<br>
* {@linkplain #addFragment addFragment}("lat", "Axis[“Latitude”, NORTH,
<strong>$deg</strong>]");<br>
* {@linkplain #addFragment addFragment}("lon", "Axis[“Longitude”, EAST,
<strong>$deg</strong>]");<br>
- * {@linkplain #addFragment addFragment}("MyBaseCRS", "GeodeticCRS[“WGS84”,
Datum[</code> <i>…etc…</i> <code>],
+ * {@linkplain #addFragment addFragment}("MyBaseCRS", "GeographicCRS[“WGS84”,
Datum[</code> <i>…etc…</i> <code>],
* CS[</code> <i>…etc…</i> <code>], <strong>$lat</strong>,
<strong>$lon</strong>]");<br>
* Object crs = {@linkplain #parseObject(String)
parseObject}("ProjectedCRS[“Mercator_1SP”, <strong>$MyBaseCRS</strong>,
* </code> <i>…etc…</i> <code>]");
@@ -858,7 +858,7 @@ public class WKTFormat extends CompoundFormat<Object> {
* (WKT after the ellipsoid omitted for brevity):
*
* {@snippet lang="java" :
- * Object crs = parseObject("GeodeticCRS[“Tokyo”, Datum[“Tokyo”,
$MyEllipsoid], …]");
+ * Object crs = parseObject("GeographicCRS[“Tokyo”, Datum[“Tokyo”,
$MyEllipsoid], …]");
* }
*
* For removing a fragment, use <code>{@linkplain
#getFragmentNames()}.remove(name)</code>.
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/DefaultParameterValue.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/DefaultParameterValue.java
index 315009eda6..4467e9c98e 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/DefaultParameterValue.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/parameter/DefaultParameterValue.java
@@ -38,6 +38,7 @@ import org.opengis.parameter.ParameterValue;
import org.opengis.parameter.ParameterDescriptor;
import org.opengis.parameter.InvalidParameterTypeException;
import org.opengis.parameter.InvalidParameterValueException;
+import org.opengis.referencing.operation.MathTransform;
import org.apache.sis.io.wkt.FormattableObject;
import org.apache.sis.io.wkt.Formatter;
import org.apache.sis.io.wkt.Convention;
@@ -51,6 +52,7 @@ import org.apache.sis.referencing.internal.Resources;
import org.apache.sis.referencing.privy.WKTUtilities;
import org.apache.sis.referencing.privy.WKTKeywords;
import org.apache.sis.math.DecimalFunctions;
+import org.apache.sis.measure.Units;
import org.apache.sis.system.Loggers;
import org.apache.sis.util.Utilities;
import org.apache.sis.util.ArgumentChecks;
@@ -1058,7 +1060,7 @@ convert: if (componentType != null) {
* <p><b>WKT 2:</b></p>
* {@snippet lang="wkt" :
* ProjectedCRS[…
- * BaseGeodCRS[…
+ * BaseGeogCRS[…
* AngleUnit[“grad”, 0.015707963267948967]],
* Conversion[“Lambert zone II”,
* Method[“Lambert Conic Conformal (1SP)”],
@@ -1088,105 +1090,98 @@ convert: if (componentType != null) {
return WKTKeywords.ParameterFile;
} else {
formatter.appendAny(value);
+ return WKTKeywords.Parameter;
}
- } else {
+ }
+ /*
+ * In the WKT 1 specification, the unit of measurement is given by the
context.
+ * If this parameter value does not use the same unit, we will need to
convert it.
+ * Otherwise we can write the value as-is.
+ *
+ * Note that we take the descriptor unit as a starting point instead
of this parameter unit
+ * in order to give precedence to the descriptor units in
Convention.WKT1_COMMON_UNITS mode.
+ */
+ Unit<?> contextualUnit;
+ if (descriptor == null || (contextualUnit = descriptor.getUnit()) ==
null) {
+ // Should be very rare (probably a buggy descriptor), but we try
to be safe.
+ contextualUnit = unit;
+ }
+ contextualUnit = formatter.toContextualUnit(contextualUnit);
+ if (isWKT1) {
+ unit = contextualUnit;
+ } else if (convention != Convention.INTERNAL) {
+ unit = WKTUtilities.toFormattable(unit);
+ }
+ double value;
+ try {
+ value = doubleValue(unit);
+ } catch (IllegalStateException exception) {
/*
- * In the WKT 1 specification, the unit of measurement is given by
the context.
- * If this parameter value does not use the same unit, we will
need to convert it.
- * Otherwise we can write the value as-is.
- *
- * Note that we take the descriptor unit as a starting point
instead of this parameter unit
- * in order to give precedence to the descriptor units in
Convention.WKT1_COMMON_UNITS mode.
+ * May happen if a parameter is mandatory (e.g. "semi-major") but
no value has been set for this parameter.
+ * The name of the problematic parameter (needed for producing an
error message) is given by the descriptor.
+ * Null descriptor should be illegal but may happen after
unmarshalling of invalid GML.
+ * We make this WKT formatting robust since it is used by
`toString()` implementation.
*/
- Unit<?> contextualUnit;
- if (descriptor == null || (contextualUnit = descriptor.getUnit())
== null) {
- // Should be very rare (probably a buggy descriptor), but we
try to be safe.
- contextualUnit = unit;
- }
- contextualUnit = formatter.toContextualUnit(contextualUnit);
- boolean ignoreUnits;
- if (isWKT1) {
- unit = contextualUnit;
- ignoreUnits = true;
+ if (descriptor != null) {
+ formatter.setInvalidWKT(descriptor, exception);
} else {
- if (convention != Convention.INTERNAL) {
- unit = WKTUtilities.toFormattable(unit);
- }
- ignoreUnits = unit.equals(contextualUnit);
+ formatter.setInvalidWKT(DefaultParameterValue.class,
exception);
}
- double value;
- try {
- value = doubleValue(unit);
- } catch (IllegalStateException exception) {
+ value = Double.NaN;
+ }
+ formatter.append(value);
+ /*
+ * In the WKT 2 specification, the unit and the identifier are
optional but recommended.
+ * We follow that recommendation in strict WKT2 mode, but omit unit in
non-strict modes.
+ * Except if the parameter unit is not the same as the contextual
unit, in which case it
+ * is not possible to omit the unit (unless the value is the same in
both units, like 0).
+ */
+ boolean ignoreUnits = false;
+ if (convention.isSimplified()) {
+ /*
+ * The contextual units may be defined either in the direct
parent, or in the parent of the parent,
+ * depending if we are formatting WKT 1 or WKT 2 respectively.
This is because WKT 2 wraps the
+ * parameters in an additional `CONVERSION[…]` element which is
not present in WKT 1.
+ * Taking the example documented in the Javadoc of this method:
+ *
+ * - in WKT 1, `PROJCS[…]` is the immediate parent of
`PARAMETER[…]`, but
+ * - in WKT 2, `ProjectedCRS[…]` is the parent of `Conversion[…]`,
+ * which is the parent of `Parameter[…]`.
+ */
+ if (formatter.hasContextualUnit(isWKT1 ? 1 : 2) ||
+ formatter.getEnclosingElement(1) instanceof MathTransform)
+ {
+ ignoreUnits = Double.isNaN(value)
+ ? unit.equals(contextualUnit)
+ : doubleValue(contextualUnit) == value; //
Equivalent to above line but more aggressive.
/*
- * May happen if a parameter is mandatory (e.g. "semi-major")
- * but no value has been set for this parameter.
+ * ISO 19162:2019 became more restrictive than older standards
about contextual units in parameters.
+ * For avoiding ambiguity, allow the omission only for decimal
degrees and base units.
*/
- if (descriptor != null) {
- formatter.setInvalidWKT(descriptor, exception);
- } else {
- /*
- * Null descriptor should be illegal but may happen after
unmarshalling of invalid GML.
- * We make this WKT formatting robust since it is used by
'toString()' implementation.
- */
- formatter.setInvalidWKT(DefaultParameterValue.class,
exception);
+ if (ignoreUnits && !isWKT1) {
+ ignoreUnits = Units.isAngular(unit)
+ ? Units.DEGREE.equals(unit)
+ : Units.toStandardUnit(unit) == 1;
}
- value = Double.NaN;
- }
- formatter.append(value);
- /*
- * In the WKT 2 specification, the unit and the identifier are
optional but recommended.
- * We follow that recommendation in strict WKT2 mode, but omit
them in non-strict modes.
- * The only exception is when the parameter unit is not the same
as the contextual unit,
- * in which case we have no choice: we must format that unit,
unless the numerical value
- * is identical in both units (typically the 0 value).
- */
- if (!ignoreUnits && !Double.isNaN(value)) {
- // Test equivalent to unit.equals(contextualUnit) but more
aggressive.
- ignoreUnits = Numerics.equals(value,
doubleValue(contextualUnit));
- }
- if (ignoreUnits && convention != Convention.INTERNAL) {
- // One last check about if we are really allowed to ignore
units.
- ignoreUnits = convention.isSimplified() &&
hasContextualUnit(formatter);
}
- if (!ignoreUnits) {
- if (!isWKT1) {
- formatter.append(unit);
- } else if (!ignoreUnits) {
- if (descriptor != null) {
- formatter.setInvalidWKT(descriptor, null);
- } else {
- /*
- * Null descriptor should be illegal but may happen
after unmarshalling of invalid GML.
- * We make this WKT formatting robust since it is used
by 'toString()' implementation.
- */
- formatter.setInvalidWKT(DefaultParameterValue.class,
null);
- }
- }
+ }
+ if (!ignoreUnits) {
+ if (!isWKT1) {
+ formatter.append(unit);
+ } else if (descriptor != null) {
+ formatter.setInvalidWKT(descriptor, null);
+ } else {
+ /*
+ * Null descriptor should be illegal but may happen after
unmarshalling of invalid GML.
+ * We make this WKT formatting robust since it is used by
`toString()` implementation.
+ */
+ formatter.setInvalidWKT(DefaultParameterValue.class, null);
}
}
// ID will be added by the Formatter itself.
return WKTKeywords.Parameter;
}
- /**
- * Returns {@code true} if the given formatter has contextual units, in
which case the WKT format can omit
- * the unit of measurement. The contextual units may be defined either in
the direct parent or in the parent
- * of the parent, depending if we are formatting WKT1 or WKT2
respectively. This is because WKT2 wraps the
- * parameters in an additional {@code CONVERSION[…]} element which is not
present in WKT1.
- *
- * <p>Taking the example documented in {@link #formatTo(Formatter)}:</p>
- * <ul>
- * <li>in WKT 1, {@code PROJCS[…]} is the immediate parent of {@code
PARAMETER[…]}, but</li>
- * <li>in WKT 2, {@code ProjectedCRS[…]} is the parent of {@code
Conversion[…]},
- * which is the parent of {@code Parameter[…]}.</li>
- * </ul>
- */
- private static boolean hasContextualUnit(final Formatter formatter) {
- return formatter.hasContextualUnit(1) || // In WKT1
- formatter.hasContextualUnit(2); // In WKT2
- }
-
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
index 720f251bcb..645680f0de 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/AbstractIdentifiedObject.java
@@ -891,13 +891,13 @@ public class AbstractIdentifiedObject extends
FormattableObject implements Ident
* </ul>
*
* Keywords and metadata (scope, extent, identifier and remarks) shall not
be formatted here.
- * For example if this formattable element is for a {@code GeodeticCRS[…]}
element,
+ * For example if this formattable element is for a {@code
GeographicCRS[…]} element,
* then subclasses shall write the content starting at the insertion point
shown below:
*
* <div class="horizontal-flow">
* <div><p><b>WKT example</b></p>
* <pre class="text">
- * GeodeticCRS["WGS 84", ID["EPSG", 4326]]
+ * GeographicCRS["WGS 84", ID["EPSG", 4326]]
* ↑
* (insertion point)</pre>
* </div><div>
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
index 85a52f9802..a534aeacc8 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/CRS.java
@@ -304,7 +304,7 @@ public final class CRS extends Static {
*
* {@snippet lang="wkt" :
* ProjectedCRS["SIRGAS 2000 / Brazil Mercator",
- * BaseGeodCRS["SIRGAS 2000",
+ * BaseGeogCRS["SIRGAS 2000",
* Datum["Sistema de Referencia Geocentrico para las Americas 2000",
* Ellipsoid["GRS 1980", 6378137, 298.257222101]]],
* Conversion["Petrobras Mercator",
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
index 72119d0ec0..fb7b9fd5c6 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultDerivedCRS.java
@@ -36,6 +36,7 @@ import org.opengis.referencing.crs.ProjectedCRS;
import org.opengis.referencing.crs.EngineeringCRS;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.cs.CoordinateSystem;
+import org.opengis.referencing.cs.EllipsoidalCS;
import org.opengis.referencing.cs.VerticalCS;
import org.opengis.referencing.cs.TimeCS;
import org.opengis.referencing.operation.Conversion;
@@ -680,6 +681,9 @@ public class DefaultDerivedCRS extends AbstractDerivedCRS
implements DerivedCRS
/** Returns the WKT keyword for this derived CRS type. */
@Override String keyword(final Formatter formatter) {
+ if (formatter.getConvention().supports(Convention.WKT2_2019) &&
getCoordinateSystem() instanceof EllipsoidalCS) {
+ return formatter.shortOrLong(WKTKeywords.GeogCRS,
WKTKeywords.GeographicCRS);
+ }
return formatter.shortOrLong(WKTKeywords.GeodCRS,
WKTKeywords.GeodeticCRS);
}
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
index bbc1e2e742..7071186029 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeodeticCRS.java
@@ -173,7 +173,7 @@ class DefaultGeodeticCRS extends
AbstractSingleCRS<GeodeticDatum> implements Geo
}
/**
- * Formats this CRS as a <i>Well Known Text</i> {@code GeodeticCRS[…]}
element.
+ * Formats this CRS as a <i>Well Known Text</i> {@code GeodeticCRS[…]} or
{@code GeographicCRS[…]} element.
* More information about the WKT format is documented in subclasses.
*
* @return {@code "GeodeticCRS"} (WKT 2) or {@code "GeogCS"}/{@code
"GeocCS"} (WKT 1).
@@ -184,8 +184,8 @@ class DefaultGeodeticCRS extends
AbstractSingleCRS<GeodeticDatum> implements Geo
CoordinateSystem cs = getCoordinateSystem();
final Convention convention = formatter.getConvention();
final boolean isWKT1 = (convention.majorVersion() == 1);
- final boolean isGeographicWKT1 = isWKT1 && (cs instanceof
EllipsoidalCS);
- if (isGeographicWKT1 && cs.getDimension() == 3) {
+ final boolean isGeographic = (cs instanceof EllipsoidalCS);
+ if (isWKT1 && isGeographic && cs.getDimension() == 3) {
/*
* Version 1 of WKT format did not have three-dimensional
GeographicCRS. Instead, such CRS were formatted
* as a CompoundCRS made of a two-dimensional GeographicCRS with a
VerticalCRS for the ellipsoidal height.
@@ -237,7 +237,7 @@ class DefaultGeodeticCRS extends
AbstractSingleCRS<GeodeticDatum> implements Geo
*/
final boolean isBaseCRS;
if (isWKT1) {
- if (!isGeographicWKT1) { // If not
geographic, then presumed geocentric.
+ if (!isGeographic) { // If not
geographic, then presumed geocentric.
if (cs instanceof CartesianCS) {
cs = Legacy.forGeocentricCRS((CartesianCS) cs, true);
} else {
@@ -271,7 +271,10 @@ class DefaultGeodeticCRS extends
AbstractSingleCRS<GeodeticDatum> implements Geo
* have a GeodeticCRS. We need to make the choice in this base class.
The CS type is a sufficient criterion.
*/
if (isWKT1) {
- return isGeographicWKT1 ? WKTKeywords.GeogCS : WKTKeywords.GeocCS;
+ return isGeographic ? WKTKeywords.GeogCS : WKTKeywords.GeocCS;
+ } else if (isGeographic && convention.supports(Convention.WKT2_2019)) {
+ return isBaseCRS ? WKTKeywords.BaseGeogCRS
+ : formatter.shortOrLong(WKTKeywords.GeogCRS,
WKTKeywords.GeographicCRS);
} else {
return isBaseCRS ? WKTKeywords.BaseGeodCRS
: formatter.shortOrLong(WKTKeywords.GeodCRS,
WKTKeywords.GeodeticCRS);
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeographicCRS.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeographicCRS.java
index 72cd05a3d1..219b2fda34 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeographicCRS.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultGeographicCRS.java
@@ -366,14 +366,14 @@ public class DefaultGeographicCRS extends
DefaultGeodeticCRS implements Geograph
}
/**
- * Formats this CRS as a <i>Well Known Text</i> {@code GeodeticCRS[…]}
element.
+ * Formats this CRS as a <i>Well Known Text</i> {@code GeographicCRS[…]}
element.
*
* <h4>Example</h4>
* Well-Known Text (version 2)
* of a geographic coordinate reference system using the WGS 84 datum.
*
* {@snippet lang="wkt" :
- * GeodeticCRS["WGS 84",
+ * GeographicCRS["WGS 84",
* Datum["World Geodetic System 1984",
* Ellipsoid["WGS84", 6378137.0, 298.257223563, LengthUnit["metre",
1]]],
* PrimeMeridian["Greenwich", 0.0, AngleUnit["degree",
0.017453292519943295]],
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
index bc289ee30f..d07064f1b0 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DefaultProjectedCRS.java
@@ -338,7 +338,7 @@ public class DefaultProjectedCRS extends AbstractDerivedCRS
implements Projected
*
* {@snippet lang="wkt" :
* ProjectedCRS[“NTF (Paris) / Lambert zone II”,
- * BaseGeodCRS[“NTF (Paris)”,
+ * BaseGeogCRS[“NTF (Paris)”,
* Datum[“Nouvelle Triangulation Francaise”,
* Ellipsoid[“NTF”, 6378249.2, 293.4660212936269,
LengthUnit[“metre”, 1]]],
* PrimeMeridian[“Paris”, 2.5969213, AngleUnit[“grad”,
0.015707963267948967]]],
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DynamicCRS.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DynamicCRS.java
index 31bbc386b1..23290ce2aa 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DynamicCRS.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/crs/DynamicCRS.java
@@ -67,7 +67,7 @@ final class DynamicCRS extends FormattableObject {
*/
@Override
protected String formatTo(final Formatter formatter) {
- formatter.append(new Epoch(epoch, true));
+ formatter.append(new Epoch(epoch, WKTKeywords.FrameEpoch));
return WKTKeywords.Dynamic;
}
}
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultPrimeMeridian.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultPrimeMeridian.java
index 2e1c286114..ca097b7b45 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultPrimeMeridian.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/datum/DefaultPrimeMeridian.java
@@ -315,7 +315,7 @@ public class DefaultPrimeMeridian extends
AbstractIdentifiedObject implements Pr
*
* {@snippet lang="wkt" :
* ProjectedCRS[“NTF (Paris) / Lambert zone II”,
- * BaseGeodCRS[“NTF (Paris)”,
+ * BaseGeogCRS[“NTF (Paris)”,
* Datum[“Nouvelle Triangulation Francaise”,
* Ellipsoid[“NTF”, 6378249.2, 293.4660212936269]],
* PrimeMeridian[“Paris”, 2.5969213],
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
index ff3f7e2713..f20b2fa4de 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/factory/GeodeticObjectFactory.java
@@ -1795,7 +1795,7 @@ public class GeodeticObjectFactory extends
AbstractFactory implements CRSFactory
*
* {@snippet lang="wkt" :
* ProjectedCRS["SIRGAS 2000 / Brazil Mercator",
- * BaseGeodCRS["SIRGAS 2000",
+ * BaseGeogCRS["SIRGAS 2000",
* Datum["Sistema de Referencia Geocentrico para las Americas 2000",
* Ellipsoid["GRS 1980", 6378137, 298.257222101]]],
* Conversion["Petrobras Mercator",
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Epoch.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Epoch.java
index 0c3f131d3d..7544caea8c 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Epoch.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/internal/Epoch.java
@@ -27,7 +27,6 @@ import java.time.temporal.ChronoField;
import org.apache.sis.io.wkt.Formatter;
import org.apache.sis.io.wkt.FormattableObject;
import org.apache.sis.math.DecimalFunctions;
-import org.apache.sis.referencing.privy.WKTKeywords;
import org.apache.sis.util.privy.Constants;
@@ -50,18 +49,19 @@ public final class Epoch extends FormattableObject {
public final int precision;
/**
- * Whether this epoch is the frame epoch instead of the coordinate epoch.
+ * The keyword of the <abbr>WKT</abbr> element which will contain the
epoch.
+ * This is {@code "Epoch"}, {@code "FrameEpoch"} or {@code "AnchorEpoch"}.
*/
- private final boolean frame;
+ private final String keyword;
/**
* Converts the given epoch to a fractional year.
*
- * @param epoch the epoch to express as a fractional year.
- * @param frame whether this epoch is the frame epoch instead of the
coordinate epoch
+ * @param epoch the epoch to express as a fractional year.
+ * @param keyword the keyword of the <abbr>WKT</abbr> element which will
contain the epoch.
*/
- public Epoch(Temporal epoch, final boolean frame) {
- this.frame = frame;
+ public Epoch(Temporal epoch, final String keyword) {
+ this.keyword = keyword;
if (epoch instanceof Instant) {
epoch = OffsetDateTime.ofInstant((Instant) epoch, ZoneOffset.UTC);
}
@@ -140,11 +140,11 @@ public final class Epoch extends FormattableObject {
* Formats this epoch as a <i>Well Known Text</i> {@code
CoordinateMetadata[…]} element.
*
* @param formatter the formatter where to format the inner content of
this WKT element.
- * @return {@code "Epoch"} or {@code "FrameEpoch"}.
+ * @return {@code "Epoch"}, {@code "FrameEpoch"} or {@code "AnchorEpoch"}.
*/
@Override
protected String formatTo(final Formatter formatter) {
formatter.append(value, precision);
- return frame ? WKTKeywords.FrameEpoch : WKTKeywords.Epoch;
+ return keyword;
}
}
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTKeywords.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTKeywords.java
index 76bf6005cd..9f9f340642 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTKeywords.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTKeywords.java
@@ -55,10 +55,10 @@ public final class WKTKeywords extends Static {
URI = "URI",
Citation = "Citation",
Authority = "Authority",
- Anchor = "Anchor",
Usage = "Usage",
Scope = "Scope",
Area = "Area",
+ BBox = "BBox",
Remark = "Remark";
/**
@@ -100,7 +100,9 @@ public final class WKTKeywords extends Static {
* and {@link org.apache.sis.referencing.crs.DefaultGeographicCRS}.
*/
public static final String
- BBox = "BBox",
+ Anchor = "Anchor",
+ AnchorEpoch = "AnchorEpoch",
+ TRF = "TRF",
Datum = "Datum",
GeodeticDatum = "GeodeticDatum",
GeodeticCRS = "GeodeticCRS",
@@ -120,6 +122,7 @@ public final class WKTKeywords extends Static {
VerticalDatum = "VerticalDatum",
VerticalCRS = "VerticalCRS",
BaseVertCRS = "BaseVertCRS",
+ VRF = "VRF",
VDatum = "VDatum",
Vert_Datum = "Vert_Datum",
VertCRS = "VertCRS",
@@ -269,9 +272,9 @@ public final class WKTKeywords extends Static {
* `Datum` subtypes.
*/
subtypes = new String[][] {
- addType(org.opengis.referencing.datum.GeodeticDatum.class,
GeodeticDatum, Datum),
+ addType(org.opengis.referencing.datum.GeodeticDatum.class,
GeodeticDatum, Datum, TRF),
addType(org.opengis.referencing.datum.TemporalDatum.class,
TimeDatum, TDatum),
- addType(org.opengis.referencing.datum.VerticalDatum.class,
VerticalDatum, VDatum, Vert_Datum),
+ addType(org.opengis.referencing.datum.VerticalDatum.class,
VerticalDatum, VDatum, Vert_Datum, VRF),
addType(org.opengis.referencing.datum.EngineeringDatum.class,
EngineeringDatum, EDatum, Local_Datum)
};
addType(org.opengis.referencing.datum.Datum.class,
ArraysExt.concatenate(subtypes));
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTUtilities.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTUtilities.java
index 71e7ed7df4..ca583fd6dd 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTUtilities.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/privy/WKTUtilities.java
@@ -157,8 +157,8 @@ public final class WKTUtilities extends Static {
}
/**
- * If the given unit is one of the unit that cannot be formatted without
ambiguity in WKT format,
- * return a proposed replacement. Otherwise returns {@code unit} unchanged.
+ * If the given unit is one of the units that cannot be formatted without
ambiguity in <abbr>WKT</abbr> format,
+ * returns a proposed replacement. Otherwise returns {@code unit}
unchanged.
*
* @param <Q> the unit dimension.
* @param unit the unit to test.
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/ElementTest.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/ElementTest.java
index d8ab00ab64..df20596fca 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/ElementTest.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/ElementTest.java
@@ -182,7 +182,7 @@ public final class ElementTest extends TestCase {
public void testPullDate() throws ParseException {
Element element = parse("TimeOrigin[1858-11-17T00:00:00.0Z]");
assertEquals("TimeOrigin", element.keyword);
- assertEquals(Instant.parse("1858-11-17T00:00:00Z"),
element.pullDate("date"));
+ assertEquals(Instant.parse("1858-11-17T00:00:00Z"),
element.pullTime("date"));
element.close(null);
}
@@ -222,7 +222,7 @@ public final class ElementTest extends TestCase {
assertEquals("Modified Julian", element.pullString("name"));
Element inner = element.pullElement(AbstractParser.MANDATORY,
"TimeOrigin");
assertEquals("TimeOrigin", inner.keyword);
- assertEquals(Instant.parse("1858-11-17T00:00:00Z"),
inner.pullDate("date"));
+ assertEquals(Instant.parse("1858-11-17T00:00:00Z"),
inner.pullTime("date"));
inner.close(null);
element.close(null);
}
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
index 77c961fd07..2ab3b9764b 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/io/wkt/GeodeticObjectParserTest.java
@@ -774,8 +774,8 @@ public final class GeodeticObjectParserTest extends
EPSGDependentTestCase {
" Parameter[“Latitude of natural origin”, 52.0,
AngleUnit[“grad”, 0.015707963267948967]],\n" +
" Parameter[“Longitude of natural origin”, 0.0],\n" +
" Parameter[“Scale factor at natural origin”,
0.99987742],\n" +
- " Parameter[“False easting”, 600.0],\n" +
- " Parameter[“False northing”, 2200.0]],\n" +
+ " Parameter[“False easting”, 600.0,
LengthUnit[“kilometre”, 1000]],\n" +
+ " Parameter[“False northing”, 2200.0,
LengthUnit[“kilometre”, 1000]]],\n" +
" CS[Cartesian, 2],\n" +
" Axis[“Easting (E)”, east],\n" +
" Axis[“Northing (N)”, north],\n" +
@@ -810,8 +810,8 @@ public final class GeodeticObjectParserTest extends
EPSGDependentTestCase {
" Parameter[“Latitude of natural origin”, 52.0,
AngleUnit[“grad”, 0.015707963267948967]],\n" +
" Parameter[“Longitude of natural origin”, 0.0],\n" +
" Parameter[“Scale factor at natural origin”,
0.99987742],\n" +
- " Parameter[“False easting”, 600.0],\n" +
- " Parameter[“False northing”, 2200.0]],\n" +
+ " Parameter[“False easting”, 600.0,
LengthUnit[“kilometre”, 1000]],\n" +
+ " Parameter[“False northing”, 2200.0,
LengthUnit[“kilometre”, 1000]]],\n" +
" CS[Cartesian, 2],\n" +
" Axis[“Easting (E)”, east],\n" +
" Axis[“Northing (N)”, north],\n" +
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/parameter/DefaultParameterValueTest.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/parameter/DefaultParameterValueTest.java
index ae70183ebb..79c7a2a391 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/parameter/DefaultParameterValueTest.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/parameter/DefaultParameterValueTest.java
@@ -537,7 +537,8 @@ public final class DefaultParameterValueTest extends
TestCase {
DefaultParameterValue<Double> p = create("Angle", 10.3,
degreesAndMinutes);
assertWktEquals(Convention.WKT1, "PARAMETER[“Angle”, 10.3]", p);
// 10.3 DM == 10.5°
assertWktEquals(Convention.WKT2, "PARAMETER[“Angle”, 10.5,
ANGLEUNIT[“degree”, 0.017453292519943295]]", p);
- assertWktEquals(Convention.INTERNAL, "Parameter[“Angle”, 10.3]", p);
// Value in same unit as descriptor.
+ assertWktEquals(Convention.INTERNAL, "Parameter[“Angle”, 10.3,
Unit[“D.M”, 0.017453292519943295, Id[“EPSG”, 9111]]]", p);
+ // In above line, the parameter value in `INTERNAL` mode was formatted
in the same unit as the descriptor.
p = create("Angle", 0, Units.DEGREE);
p.setValue(10.3, degreesAndMinutes); // Cannot be formatted in WKT1.
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultCompoundCRSTest.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultCompoundCRSTest.java
index 2d78dbffd9..779fba8196 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultCompoundCRSTest.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultCompoundCRSTest.java
@@ -294,7 +294,7 @@ public final class DefaultCompoundCRSTest extends TestCase {
public void testWKT2_Simplified() {
assertWktEquals(Convention.WKT2_SIMPLIFIED,
"CompoundCRS[“WGS 84 + height + time”,\n" +
- " GeodeticCRS[“WGS 84”,\n" +
+ " GeographicCRS[“WGS 84”,\n" +
" Datum[“World Geodetic System 1984”,\n" +
" Ellipsoid[“WGS84”, 6378137.0, 298.257223563]],\n" +
" CS[ellipsoidal, 2],\n" +
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultDerivedCRSTest.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultDerivedCRSTest.java
index 7630a761e0..a8080a1dd2 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultDerivedCRSTest.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultDerivedCRSTest.java
@@ -212,7 +212,7 @@ public final class DefaultDerivedCRSTest extends TestCase {
public void testWKT2_Simplified() {
assertWktEquals(Convention.WKT2_SIMPLIFIED,
"GeodeticCRS[“Back to Greenwich”,\n" +
- " BaseGeodCRS[“NTF (Paris)”,\n" +
+ " BaseGeogCRS[“NTF (Paris)”,\n" +
" Datum[“Nouvelle Triangulation Francaise”,\n" +
" Ellipsoid[“NTF”, 6378249.2, 293.4660212936269]],\n" +
" PrimeMeridian[“Paris”, 2.5969213, Unit[“grad”,
0.015707963267948967]],\n" +
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultGeographicCRSTest.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultGeographicCRSTest.java
index 5d52def9d4..2064a0ecfd 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultGeographicCRSTest.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultGeographicCRSTest.java
@@ -197,7 +197,7 @@ public final class DefaultGeographicCRSTest extends
TestCase {
@Test
public void testWKT2_Simplified() {
assertWktEquals(Convention.WKT2_SIMPLIFIED,
- "GeodeticCRS[“WGS 84”,\n" +
+ "GeographicCRS[“WGS 84”,\n" +
" Datum[“World Geodetic System 1984”,\n" +
" Ellipsoid[“WGS84”, 6378137.0, 298.257223563]],\n" +
" CS[ellipsoidal, 2],\n" +
@@ -216,7 +216,7 @@ public final class DefaultGeographicCRSTest extends
TestCase {
@Test
public void testWKT2_Internal() {
assertWktEquals(Convention.INTERNAL,
- "GeodeticCRS[“WGS 84”,\n" +
+ "GeographicCRS[“WGS 84”,\n" +
" Datum[“World Geodetic System 1984”,\n" +
" Ellipsoid[“WGS84”, 6378137.0, 298.257223563],\n" +
" Usage[\n" +
@@ -242,7 +242,7 @@ public final class DefaultGeographicCRSTest extends
TestCase {
@Test
public void testWKT2_ForNonGreenwich() {
assertWktEquals(Convention.WKT2_SIMPLIFIED,
- "GeodeticCRS[“NTF (Paris)”,\n" +
+ "GeographicCRS[“NTF (Paris)”,\n" +
" Datum[“Nouvelle Triangulation Francaise”,\n" + //
Formatter should replace "ç" by "c".
" Ellipsoid[“NTF”, 6378249.2, 293.4660212936269]],\n" +
" PrimeMeridian[“Paris”, 2.5969213, Unit[“grad”,
0.015707963267948967]],\n" +
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java
index 9392c3a5fc..9c576bbb8b 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/crs/DefaultProjectedCRSTest.java
@@ -266,7 +266,7 @@ public final class DefaultProjectedCRSTest extends
TestCase.WithLogs {
ProjectedCRS crs = create(HardCodedCRS.NTF);
assertWktEquals(Convention.INTERNAL,
"ProjectedCRS[“NTF (Paris) / Lambert zone II”,\n" +
- " BaseGeodCRS[“NTF (Paris)”,\n" +
+ " BaseGeogCRS[“NTF (Paris)”,\n" +
" Datum[“Nouvelle Triangulation Française”,\n" +
" Ellipsoid[“NTF”, 6378249.2, 293.4660212936269],\n" +
" Usage[\n" +
@@ -279,7 +279,7 @@ public final class DefaultProjectedCRSTest extends
TestCase.WithLogs {
" Unit[“grad”, 0.015707963267948967, Id[“EPSG”,
9105]]],\n" +
" Conversion[“Lambert zone II”,\n" +
" Method[“Lambert Conic Conformal (1SP)”, Id[“EPSG”, 9801],
Id[“GeoTIFF”, 9]],\n" +
- " Parameter[“Latitude of natural origin”, 52.0, Id[“EPSG”,
8801], Id[“GeoTIFF”, 3081]],\n" +
+ " Parameter[“Latitude of natural origin”, 52.0,
Unit[“grad”, 0.015707963267948967, Id[“EPSG”, 9105]], Id[“EPSG”, 8801],
Id[“GeoTIFF”, 3081]],\n" +
" Parameter[“Longitude of natural origin”, 0.0, Id[“EPSG”,
8802], Id[“GeoTIFF”, 3080]],\n" +
" Parameter[“Scale factor at natural origin”, 0.99987742,
Id[“EPSG”, 8805], Id[“GeoTIFF”, 3092]],\n" +
" Parameter[“False easting”, 600000.0, Id[“EPSG”, 8806],
Id[“GeoTIFF”, 3082]],\n" +
@@ -304,14 +304,14 @@ public final class DefaultProjectedCRSTest extends
TestCase.WithLogs {
ProjectedCRS crs = create(HardCodedCRS.NTF);
assertWktEquals(Convention.WKT2_SIMPLIFIED,
"ProjectedCRS[“NTF (Paris) / Lambert zone II”,\n" +
- " BaseGeodCRS[“NTF (Paris)”,\n" +
+ " BaseGeogCRS[“NTF (Paris)”,\n" +
" Datum[“Nouvelle Triangulation Francaise”,\n" +
" Ellipsoid[“NTF”, 6378249.2, 293.4660212936269]],\n" +
" PrimeMeridian[“Paris”, 2.5969213],\n" +
" Unit[“grad”, 0.015707963267948967]],\n" +
" Conversion[“Lambert zone II”,\n" +
" Method[“Lambert Conic Conformal (1SP)”],\n" +
- " Parameter[“Latitude of natural origin”, 52.0],\n" +
+ " Parameter[“Latitude of natural origin”, 52.0,
Unit[“grad”, 0.015707963267948967]],\n" +
" Parameter[“Longitude of natural origin”, 0.0],\n" +
" Parameter[“Scale factor at natural origin”,
0.99987742],\n" +
" Parameter[“False easting”, 600000.0],\n" +
@@ -329,7 +329,7 @@ public final class DefaultProjectedCRSTest extends
TestCase.WithLogs {
crs = create(HardCodedCRS.NTF_NORMALIZED_AXES);
assertWktEquals(Convention.WKT2_SIMPLIFIED,
"ProjectedCRS[“NTF (Paris) / Lambert zone II”,\n" +
- " BaseGeodCRS[“NTF (Paris)”,\n" +
+ " BaseGeogCRS[“NTF (Paris)”,\n" +
" Datum[“Nouvelle Triangulation Francaise”,\n" +
" Ellipsoid[“NTF”, 6378249.2, 293.4660212936269]],\n" +
" PrimeMeridian[“Paris”, 2.5969213, Unit[“grad”,
0.015707963267948967]],\n" +
@@ -382,7 +382,7 @@ public final class DefaultProjectedCRSTest extends
TestCase.WithLogs {
assertWktEquals(Convention.WKT2_SIMPLIFIED,
"ProjectedCRS[“NTF (Paris) / Lambert zone II”,\n" +
- " BaseGeodCRS[“NTF (Paris)”,\n" +
+ " BaseGeogCRS[“NTF (Paris)”,\n" +
" Datum[“Nouvelle Triangulation Francaise”,\n" +
" Ellipsoid[“NTF”, 6378249.2, 293.4660212936269]],\n" +
" PrimeMeridian[“Paris”, 2.5969213, Unit[“grad”,
0.015707963267948967]],\n" +
@@ -467,7 +467,7 @@ public final class DefaultProjectedCRSTest extends
TestCase.WithLogs {
assertWktEquals(Convention.WKT2_SIMPLIFIED,
"ProjectedCRS[“Equidistant Cylindrical (Spherical)”,\n" +
- " BaseGeodCRS[“WGS 84”,\n" +
+ " BaseGeogCRS[“WGS 84”,\n" +
" Datum[“World Geodetic System 1984”,\n" +
" Ellipsoid[“WGS84”, 6378137.0, 298.257223563]],\n" +
" Unit[“degree”, 0.017453292519943295]],\n" +
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultGeodeticDatumTest.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultGeodeticDatumTest.java
index a1445d78dd..66da7ea085 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultGeodeticDatumTest.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/datum/DefaultGeodeticDatumTest.java
@@ -343,6 +343,7 @@ public final class DefaultGeodeticDatumTest extends
TestCase {
" Ellipsoid[“WGS 84”, 6378137.0, 298.257223563, Id[“EPSG”,
7030],\n" +
" Remark[“Defining parameters cited in EPSG
database.”]],\n" +
" Anchor[“Station coordinates changed by a few centimetres in
1994, 1997, 2002 and 2012.”],\n" +
+ " AnchorEpoch[1984.000],\n" + // The 3 digits are because of
<gml:realizationEpoch> in test file.
" Usage[\n" +
" Scope[“Satellite navigation.”],\n" +
" Area[“World.”],\n" +
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/EpochTest.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/EpochTest.java
index 5a0a91bfee..603ea383d0 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/EpochTest.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/internal/EpochTest.java
@@ -21,6 +21,7 @@ import java.time.YearMonth;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;
+import org.apache.sis.referencing.privy.WKTKeywords;
// Test dependencies
import org.junit.jupiter.api.Test;
@@ -47,7 +48,7 @@ public final class EpochTest extends TestCase {
*/
@Test
public void testYear() {
- var epoch = new Epoch(Year.of(2010), false);
+ var epoch = new Epoch(Year.of(2010), WKTKeywords.Epoch);
assertEquals(2010, epoch.value);
assertEquals(0, epoch.precision);
assertEquals("Epoch[2010]", epoch.toString());
@@ -58,12 +59,12 @@ public final class EpochTest extends TestCase {
*/
@Test
public void testYearMonth() {
- var epoch = new Epoch(YearMonth.of(2016, 1), false);
+ var epoch = new Epoch(YearMonth.of(2016, 1), WKTKeywords.Epoch);
assertEquals(2016, epoch.value);
assertEquals(2, epoch.precision);
assertEquals("Epoch[2016.00]", epoch.toString());
- epoch = new Epoch(YearMonth.of(2016, 7), false);
+ epoch = new Epoch(YearMonth.of(2016, 7), WKTKeywords.Epoch);
assertEquals(2016.49726775956, epoch.value, 1E-11);
assertEquals(2, epoch.precision);
assertEquals("Epoch[2016.50]", epoch.toString());
@@ -74,7 +75,7 @@ public final class EpochTest extends TestCase {
*/
@Test
public void testLocalDate() {
- var epoch = new Epoch(LocalDate.of(2016, 7, 20), false);
+ var epoch = new Epoch(LocalDate.of(2016, 7, 20), WKTKeywords.Epoch);
assertEquals(2016.54918032787, epoch.value, 1E-11);
assertEquals(3, epoch.precision);
assertEquals("Epoch[2016.549]", epoch.toString());
@@ -85,7 +86,7 @@ public final class EpochTest extends TestCase {
*/
@Test
public void testLocalDateTime() {
- var epoch = new Epoch(LocalDateTime.of(2014, 2, 15, 10, 40), false);
+ var epoch = new Epoch(LocalDateTime.of(2014, 2, 15, 10, 40),
WKTKeywords.Epoch);
assertEquals(2014.12450532725, epoch.value, 1E-11);
assertEquals(8, epoch.precision);
assertEquals("Epoch[2014.12450533]", epoch.toString());
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
index e8488c69c5..f2b47dbd5c 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/CoordinateOperationFinderTest.java
@@ -240,7 +240,7 @@ public final class CoordinateOperationFinderTest extends
MathTransformTestCase {
@Test
public void testGeocentricTranslationInGeographic3D() throws
ParseException, FactoryException, TransformException {
final GeographicCRS sourceCRS = (GeographicCRS) parse(
- "GeodeticCRS[“NAD27”,\n" +
+ "GeographicCRS[“NAD27”,\n" +
" Datum[“North American Datum 1927”,\n" +
" Ellipsoid[“Clarke 1866”, 6378206.4,
294.9786982138982],\n" +
" ToWGS84[-8, 160, 176]]," +
// See comment in above test.
@@ -318,7 +318,7 @@ public final class CoordinateOperationFinderTest extends
MathTransformTestCase {
@Test
public void testLongitudeRotation() throws ParseException,
FactoryException, TransformException {
final CoordinateReferenceSystem sourceCRS = parse(
- "GeodeticCRS[“NTF (Paris)”, $NTF,\n" +
+ "GeographicCRS[“NTF (Paris)”, $NTF,\n" +
" PrimeMeridian[“Paris”, 2.5969213],\n" + // in
grads, not degrees.
" CS[ellipsoidal, 2],\n" +
" Axis[“Latitude (φ)”, NORTH],\n" +
@@ -947,7 +947,7 @@ public final class CoordinateOperationFinderTest extends
MathTransformTestCase {
public void testProjected4D_to_2D() throws ParseException,
FactoryException, TransformException {
final CoordinateReferenceSystem targetCRS = parse(
"ProjectedCRS[“WGS 84 / World Mercator”,\n" +
- " BaseGeodCRS[“WGS 84”,\n" +
+ " BaseGeogCRS[“WGS 84”,\n" +
" Datum[“World Geodetic System 1984”,\n" +
" Ellipsoid[“WGS 84”, 6378137.0, 298.257223563]]],\n" +
" Conversion[“WGS 84 / World Mercator”,\n" +
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/CoordinateOperationRegistryTest.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/CoordinateOperationRegistryTest.java
index d6c33c5849..7d2a5b1e59 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/CoordinateOperationRegistryTest.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/CoordinateOperationRegistryTest.java
@@ -150,7 +150,7 @@ public final class CoordinateOperationRegistryTest extends
MathTransformTestCase
@Test
public void testLongitudeRotationBetweenConformCRS() throws
ParseException, FactoryException, TransformException {
final CoordinateReferenceSystem sourceCRS = parse(
- "GeodeticCRS[“NTF (Paris)”,\n" +
+ "GeographicCRS[“NTF (Paris)”,\n" +
" $NTF,\n" +
" PrimeMeridian[“Paris”, 2.5969213],\n" +
" CS[ellipsoidal, 2],\n" +
@@ -188,7 +188,7 @@ public final class CoordinateOperationRegistryTest extends
MathTransformTestCase
@Test
public void testLongitudeRotationBetweenNormalizedCRS() throws
ParseException, FactoryException, TransformException {
final CoordinateReferenceSystem sourceCRS = parse(
- "GeodeticCRS[“NTF (Paris)”,\n" +
+ "GeographicCRS[“NTF (Paris)”,\n" +
" $NTF,\n" +
" PrimeMeridian[“Paris”, 2.33722917],\n" +
" CS[ellipsoidal, 2],\n" +
@@ -218,7 +218,7 @@ public final class CoordinateOperationRegistryTest extends
MathTransformTestCase
@Test
public void testInverse() throws ParseException, FactoryException,
TransformException {
final CoordinateReferenceSystem targetCRS = parse(
- "GeodeticCRS[“NTF (Paris)”,\n" +
+ "GeographicCRS[“NTF (Paris)”,\n" +
" $NTF,\n" +
" PrimeMeridian[“Paris”, 2.5969213],\n" +
" CS[ellipsoidal, 2],\n" +
@@ -249,7 +249,7 @@ public final class CoordinateOperationRegistryTest extends
MathTransformTestCase
@Test
public void testLongitudeRotationBetweenGeographic3D() throws
ParseException, FactoryException, TransformException {
final CoordinateReferenceSystem sourceCRS = parse(
- "GeodeticCRS[“NTF (Paris)”,\n" +
+ "GeographicCRS[“NTF (Paris)”,\n" +
" $NTF,\n" +
" PrimeMeridian[“Paris”, 2.5969213],\n" +
" CS[ellipsoidal, 3],\n" +
@@ -282,7 +282,7 @@ public final class CoordinateOperationRegistryTest extends
MathTransformTestCase
@Test
public void testLongitudeRotationBetweenNormalizedGeographic3D() throws
ParseException, FactoryException, TransformException {
final CoordinateReferenceSystem sourceCRS = parse(
- "GeodeticCRS[“NTF (Paris)”,\n" +
+ "GeographicCRS[“NTF (Paris)”,\n" +
" $NTF,\n" +
" PrimeMeridian[“Paris”, 2.33722917],\n" +
" CS[ellipsoidal, 3],\n" +
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/DefaultConcatenatedOperationTest.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/DefaultConcatenatedOperationTest.java
index 440eb63f24..c46636d736 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/DefaultConcatenatedOperationTest.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/DefaultConcatenatedOperationTest.java
@@ -107,14 +107,14 @@ public final class DefaultConcatenatedOperationTest
extends TestCase {
final DefaultConcatenatedOperation op = createGeocentricTranslation();
assertWktEquals(Convention.WKT2_SIMPLIFIED,
// Pseudo-WKT actually.
"ConcatenatedOperation[“Tokyo to JGD2000”,\n" +
- " SourceCRS[GeodeticCRS[“Tokyo”,\n" +
+ " SourceCRS[GeographicCRS[“Tokyo”,\n" +
" Datum[“Tokyo 1918”,\n" +
" Ellipsoid[“Bessel 1841”, 6377397.155, 299.1528128]],\n"
+
" CS[ellipsoidal, 3],\n" +
" Axis[“Longitude (L)”, east, Unit[“degree”,
0.017453292519943295]],\n" +
" Axis[“Latitude (B)”, north, Unit[“degree”,
0.017453292519943295]],\n" +
" Axis[“Ellipsoidal height (h)”, up, Unit[“metre”,
1]]]],\n" +
- " TargetCRS[GeodeticCRS[“JGD2000”,\n" +
+ " TargetCRS[GeographicCRS[“JGD2000”,\n" +
" Datum[“Japanese Geodetic Datum 2000”,\n" +
" Ellipsoid[“GRS 1980”, 6378137.0, 298.257222101]],\n" +
" CS[ellipsoidal, 3],\n" +
diff --git
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactoryTest.java
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactoryTest.java
index b96ed6d376..270dc42282 100644
---
a/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactoryTest.java
+++
b/endorsed/src/org.apache.sis.referencing/test/org/apache/sis/referencing/operation/DefaultCoordinateOperationFactoryTest.java
@@ -83,14 +83,14 @@ public final class DefaultCoordinateOperationFactoryTest
extends MathTransformTe
parser = new WKTFormat();
parser.addFragment("NTF",
"ProjectedCRS[“NTF (Paris) / Lambert zone II”,\n" +
- " BaseGeodCRS[“NTF (Paris)”,\n" +
+ " BaseGeogCRS[“NTF (Paris)”,\n" +
" Datum[“Nouvelle Triangulation Française (Paris)”,\n" +
" Ellipsoid[“Clarke 1880 (IGN)”, 6378249.2,
293.4660212936269]],\n" +
" PrimeMeridian[“Paris”, 2.5969213],\n" +
" Unit[“grad”, 0.015707963267948967]]\n," +
" Conversion[“Lambert zone II”,\n" +
" Method[“Lambert Conic Conformal (1SP)”],\n" +
- " Parameter[“Latitude of natural origin”, 52.0],\n" +
+ " Parameter[“Latitude of natural origin”, 52.0,
Unit[“grad”, 0.015707963267948967]],\n" +
" Parameter[“Scale factor at natural origin”,
0.99987742],\n" +
" Parameter[“False easting”, 600000.0],\n" +
" Parameter[“False northing”, 2200000.0]],\n" +
@@ -102,7 +102,7 @@ public final class DefaultCoordinateOperationFactoryTest
extends MathTransformTe
parser.addFragment("Mercator",
"ProjectedCRS[“WGS 84 / World Mercator”,\n" +
- " BaseGeodCRS[“WGS 84”,\n" +
+ " BaseGeogCRS[“WGS 84”,\n" +
" Datum[“World Geodetic System 1984”,\n" +
" Ellipsoid[“WGS 84”, 6378137.0, 298.257223563]],\n" +
" Unit[“degree”, 0.017453292519943295]],\n" +
diff --git
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/WKTPane.java
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/WKTPane.java
index 2818320b00..98cd70a217 100644
---
a/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/WKTPane.java
+++
b/optional/src/org.apache.sis.gui/main/org/apache/sis/gui/referencing/WKTPane.java
@@ -76,6 +76,7 @@ final class WKTPane extends StringConverter<Convention>
implements ChangeListene
final Convention[] sc = { // Selected conventions in the
order we want them to appear.
Convention.WKT2_SIMPLIFIED,
Convention.WKT2,
+ Convention.WKT2_2015,
Convention.WKT1,
Convention.WKT1_COMMON_UNITS
};
@@ -104,6 +105,7 @@ final class WKTPane extends StringConverter<Convention>
implements ChangeListene
switch (c) {
case WKT2_SIMPLIFIED: simplified = true; // Fall through.
case WKT2: version = 2; break;
+ case WKT2_2015: version = "2 (2015)"; break;
case WKT1: version = 1; break;
case WKT1_COMMON_UNITS: version = "GDAL 1-2"; break;
default: return c.name();